summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro18
-rw-r--r--src/3rdparty/pcre/COPYING5
-rw-r--r--src/3rdparty/pcre/config.h41
-rwxr-xr-xsrc/3rdparty/pcre/import_from_pcre_tarball.sh155
-rw-r--r--src/3rdparty/pcre/patches/README3
-rw-r--r--src/3rdparty/pcre/pcre.h677
-rw-r--r--src/3rdparty/pcre/pcre.pro46
-rw-r--r--src/3rdparty/pcre/pcre16_byte_order.c45
-rw-r--r--src/3rdparty/pcre/pcre16_chartables.c45
-rw-r--r--src/3rdparty/pcre/pcre16_compile.c45
-rw-r--r--src/3rdparty/pcre/pcre16_config.c45
-rw-r--r--src/3rdparty/pcre/pcre16_dfa_exec.c45
-rw-r--r--src/3rdparty/pcre/pcre16_exec.c45
-rw-r--r--src/3rdparty/pcre/pcre16_fullinfo.c45
-rw-r--r--src/3rdparty/pcre/pcre16_get.c45
-rw-r--r--src/3rdparty/pcre/pcre16_globals.c45
-rw-r--r--src/3rdparty/pcre/pcre16_jit_compile.c45
-rw-r--r--src/3rdparty/pcre/pcre16_maketables.c45
-rw-r--r--src/3rdparty/pcre/pcre16_newline.c45
-rw-r--r--src/3rdparty/pcre/pcre16_ord2utf16.c90
-rw-r--r--src/3rdparty/pcre/pcre16_refcount.c45
-rw-r--r--src/3rdparty/pcre/pcre16_string_utils.c45
-rw-r--r--src/3rdparty/pcre/pcre16_study.c45
-rw-r--r--src/3rdparty/pcre/pcre16_tables.c45
-rw-r--r--src/3rdparty/pcre/pcre16_ucd.c45
-rw-r--r--src/3rdparty/pcre/pcre16_utf16_utils.c130
-rw-r--r--src/3rdparty/pcre/pcre16_valid_utf16.c137
-rw-r--r--src/3rdparty/pcre/pcre16_version.c45
-rw-r--r--src/3rdparty/pcre/pcre16_xclass.c45
-rw-r--r--src/3rdparty/pcre/pcre_byte_order.c319
-rw-r--r--src/3rdparty/pcre/pcre_config.c190
-rw-r--r--src/3rdparty/pcre/pcre_fullinfo.c245
-rw-r--r--src/3rdparty/pcre/pcre_get.c669
-rw-r--r--src/3rdparty/pcre/pcre_globals.c86
-rw-r--r--src/3rdparty/pcre/pcre_refcount.c92
-rw-r--r--src/3rdparty/pcre/pcre_string_utils.c211
-rw-r--r--src/3rdparty/pcre/pcre_version.c98
-rw-r--r--src/3rdparty/pcre/qt_attribution.json16
-rw-r--r--src/3rdparty/pcre2/AUTHORS (renamed from src/3rdparty/pcre/AUTHORS)17
-rw-r--r--src/3rdparty/pcre2/LICENCE (renamed from src/3rdparty/pcre/LICENCE)36
-rwxr-xr-xsrc/3rdparty/pcre2/import_from_pcre2_tarball.sh134
-rw-r--r--src/3rdparty/pcre2/pcre2.pro52
-rw-r--r--src/3rdparty/pcre2/src/config.h52
-rw-r--r--src/3rdparty/pcre2/src/pcre2.h732
-rw-r--r--src/3rdparty/pcre2/src/pcre2_auto_possess.c1289
-rw-r--r--src/3rdparty/pcre2/src/pcre2_chartables.c (renamed from src/3rdparty/pcre/pcre_chartables.c)14
-rw-r--r--src/3rdparty/pcre2/src/pcre2_compile.c (renamed from src/3rdparty/pcre/pcre_compile.c)9000
-rw-r--r--src/3rdparty/pcre2/src/pcre2_config.c218
-rw-r--r--src/3rdparty/pcre2/src/pcre2_context.c391
-rw-r--r--src/3rdparty/pcre2/src/pcre2_dfa_match.c (renamed from src/3rdparty/pcre/pcre_dfa_exec.c)1452
-rw-r--r--src/3rdparty/pcre2/src/pcre2_error.c322
-rw-r--r--src/3rdparty/pcre2/src/pcre2_find_bracket.c218
-rw-r--r--src/3rdparty/pcre2/src/pcre2_internal.h (renamed from src/3rdparty/pcre/pcre_internal.h)2042
-rw-r--r--src/3rdparty/pcre2/src/pcre2_intmodedep.h852
-rw-r--r--src/3rdparty/pcre2/src/pcre2_jit_compile.c (renamed from src/3rdparty/pcre/pcre_jit_compile.c)1803
-rw-r--r--src/3rdparty/pcre2/src/pcre2_jit_match.c189
-rw-r--r--src/3rdparty/pcre2/src/pcre2_jit_misc.c227
-rw-r--r--src/3rdparty/pcre2/src/pcre2_maketables.c (renamed from src/3rdparty/pcre/pcre_maketables.c)59
-rw-r--r--src/3rdparty/pcre2/src/pcre2_match.c (renamed from src/3rdparty/pcre/pcre_exec.c)3540
-rw-r--r--src/3rdparty/pcre2/src/pcre2_match_data.c147
-rw-r--r--src/3rdparty/pcre2/src/pcre2_newline.c (renamed from src/3rdparty/pcre/pcre_newline.c)151
-rw-r--r--src/3rdparty/pcre2/src/pcre2_ord2utf.c (renamed from src/3rdparty/pcre/pcre_ord2utf8.c)68
-rw-r--r--src/3rdparty/pcre2/src/pcre2_pattern_info.c410
-rw-r--r--src/3rdparty/pcre2/src/pcre2_printint.c832
-rw-r--r--src/3rdparty/pcre2/src/pcre2_serialize.c265
-rw-r--r--src/3rdparty/pcre2/src/pcre2_string_utils.c201
-rw-r--r--src/3rdparty/pcre2/src/pcre2_study.c (renamed from src/3rdparty/pcre/pcre_study.c)1043
-rw-r--r--src/3rdparty/pcre2/src/pcre2_substitute.c850
-rw-r--r--src/3rdparty/pcre2/src/pcre2_substring.c542
-rw-r--r--src/3rdparty/pcre2/src/pcre2_tables.c (renamed from src/3rdparty/pcre/pcre_tables.c)440
-rw-r--r--src/3rdparty/pcre2/src/pcre2_ucd.c (renamed from src/3rdparty/pcre/pcre_ucd.c)4481
-rw-r--r--src/3rdparty/pcre2/src/pcre2_ucp.h (renamed from src/3rdparty/pcre/ucp.h)56
-rw-r--r--src/3rdparty/pcre2/src/pcre2_valid_utf.c (renamed from src/3rdparty/pcre/pcre_valid_utf8.c)271
-rw-r--r--src/3rdparty/pcre2/src/pcre2_xclass.c (renamed from src/3rdparty/pcre/pcre_xclass.c)49
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitConfig.h (renamed from src/3rdparty/pcre/sljit/sljitConfig.h)2
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h (renamed from src/3rdparty/pcre/sljit/sljitConfigInternal.h)4
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitExecAllocator.c (renamed from src/3rdparty/pcre/sljit/sljitExecAllocator.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitLir.c (renamed from src/3rdparty/pcre/sljit/sljitLir.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitLir.h (renamed from src/3rdparty/pcre/sljit/sljitLir.h)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeARM_32.c (renamed from src/3rdparty/pcre/sljit/sljitNativeARM_32.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeARM_64.c (renamed from src/3rdparty/pcre/sljit/sljitNativeARM_64.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c (renamed from src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_32.c (renamed from src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_64.c (renamed from src/3rdparty/pcre/sljit/sljitNativeMIPS_64.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_common.c (renamed from src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativePPC_32.c (renamed from src/3rdparty/pcre/sljit/sljitNativePPC_32.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativePPC_64.c (renamed from src/3rdparty/pcre/sljit/sljitNativePPC_64.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativePPC_common.c (renamed from src/3rdparty/pcre/sljit/sljitNativePPC_common.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeSPARC_32.c (renamed from src/3rdparty/pcre/sljit/sljitNativeSPARC_32.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeSPARC_common.c (renamed from src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeTILEGX-encoder.c (renamed from src/3rdparty/pcre/sljit/sljitNativeTILEGX-encoder.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeTILEGX_64.c (renamed from src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c)0
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeX86_32.c (renamed from src/3rdparty/pcre/sljit/sljitNativeX86_32.c)18
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeX86_64.c (renamed from src/3rdparty/pcre/sljit/sljitNativeX86_64.c)30
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeX86_common.c (renamed from src/3rdparty/pcre/sljit/sljitNativeX86_common.c)55
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitUtils.c (renamed from src/3rdparty/pcre/sljit/sljitUtils.c)0
-rw-r--r--src/angle/src/QtANGLE/QtANGLE.pro (renamed from src/angle/src/libGLESv2/libGLESv2.pro)65
-rw-r--r--src/angle/src/libEGL/libEGL.pro27
-rw-r--r--src/angle/src/src.pro2
-rw-r--r--src/corelib/configure.json24
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp8
-rw-r--r--src/corelib/global/global.pri6
-rw-r--r--src/corelib/global/qglobal.cpp328
-rw-r--r--src/corelib/global/qglobal.h21
-rw-r--r--src/corelib/global/qnamespace.h1
-rw-r--r--src/corelib/global/qnamespace.qdoc9
-rw-r--r--src/corelib/global/qoperatingsystemversion.cpp439
-rw-r--r--src/corelib/global/qoperatingsystemversion.h129
-rw-r--r--src/corelib/global/qoperatingsystemversion_darwin.mm101
-rw-r--r--src/corelib/global/qoperatingsystemversion_p.h87
-rw-r--r--src/corelib/global/qoperatingsystemversion_win.cpp171
-rw-r--r--src/corelib/global/qsysinfo.h53
-rw-r--r--src/corelib/io/qdatastream.h281
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp4
-rw-r--r--src/corelib/io/qfilesystemiterator_win.cpp3
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp53
-rw-r--r--src/corelib/io/qfilesystemwatcher_p.h10
-rw-r--r--src/corelib/io/qfilesystemwatcher_win.cpp286
-rw-r--r--src/corelib/io/qfilesystemwatcher_win_p.h15
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp2
-rw-r--r--src/corelib/io/qprocess.cpp2
-rw-r--r--src/corelib/io/qprocess.h6
-rw-r--r--src/corelib/io/qsavefile.h3
-rw-r--r--src/corelib/io/qsettings.cpp250
-rw-r--r--src/corelib/io/qsettings_mac.cpp13
-rw-r--r--src/corelib/io/qsettings_p.h18
-rw-r--r--src/corelib/io/qsettings_win.cpp31
-rw-r--r--src/corelib/io/qstorageinfo.cpp22
-rw-r--r--src/corelib/io/qstorageinfo.h3
-rw-r--r--src/corelib/io/qstorageinfo_p.h1
-rw-r--r--src/corelib/io/qstorageinfo_unix.cpp51
-rw-r--r--src/corelib/io/qtemporarydir.cpp27
-rw-r--r--src/corelib/io/qtemporarydir.h1
-rw-r--r--src/corelib/io/qtextstream.cpp15
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.cpp29
-rw-r--r--src/corelib/itemmodels/qitemselectionmodel.h25
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm54
-rw-r--r--src/corelib/kernel/qcore_mac_p.h6
-rw-r--r--src/corelib/kernel/qdeadlinetimer.cpp76
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp10
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h2
-rw-r--r--src/corelib/kernel/qobject.cpp85
-rw-r--r--src/corelib/kernel/qobject.h8
-rw-r--r--src/corelib/kernel/qsystemsemaphore_systemv.cpp26
-rw-r--r--src/corelib/kernel/qvariant.cpp2
-rw-r--r--src/corelib/kernel/qwineventnotifier.h2
-rw-r--r--src/corelib/mimetypes/qmimetypeparser.cpp3
-rw-r--r--src/corelib/tools/qarraydata.cpp51
-rw-r--r--src/corelib/tools/qarraydata.h11
-rw-r--r--src/corelib/tools/qbytearray.cpp86
-rw-r--r--src/corelib/tools/qbytearray.h2
-rw-r--r--src/corelib/tools/qchar.cpp2
-rw-r--r--src/corelib/tools/qdatetime.cpp33
-rw-r--r--src/corelib/tools/qdatetime_p.h1
-rw-r--r--src/corelib/tools/qlocale.cpp66
-rw-r--r--src/corelib/tools/qlocale.h4
-rw-r--r--src/corelib/tools/qlocale.qdoc11
-rw-r--r--src/corelib/tools/qlocale_p.h4
-rw-r--r--src/corelib/tools/qregularexpression.cpp528
-rw-r--r--src/corelib/tools/qringbuffer.cpp1
-rw-r--r--src/corelib/tools/qstring.cpp148
-rw-r--r--src/corelib/tools/qstring.h14
-rw-r--r--src/corelib/tools/qtimezoneprivate.cpp245
-rw-r--r--src/corelib/tools/qtimezoneprivate_android.cpp52
-rw-r--r--src/corelib/tools/qtimezoneprivate_p.h4
-rw-r--r--src/corelib/tools/qtimezoneprivate_tz.cpp52
-rw-r--r--src/corelib/tools/tools.pri2
-rw-r--r--src/dbus/qdbusutil_p.h6
-rw-r--r--src/gui/configure.json21
-rw-r--r--src/gui/image/qicon.cpp42
-rw-r--r--src/gui/image/qicon_p.h2
-rw-r--r--src/gui/image/qimage.cpp119
-rw-r--r--src/gui/image/qimage_conversions.cpp17
-rw-r--r--src/gui/kernel/qevent.cpp86
-rw-r--r--src/gui/kernel/qevent.h9
-rw-r--r--src/gui/kernel/qevent_p.h9
-rw-r--r--src/gui/kernel/qguiapplication.cpp103
-rw-r--r--src/gui/kernel/qguiapplication_p.h8
-rw-r--r--src/gui/kernel/qplatformscreen.h1
-rw-r--r--src/gui/kernel/qplatformtheme.cpp13
-rw-r--r--src/gui/kernel/qplatformtheme.h3
-rw-r--r--src/gui/kernel/qsurface.cpp2
-rw-r--r--src/gui/kernel/qsurface.h3
-rw-r--r--src/gui/kernel/qtouchdevice.h1
-rw-r--r--src/gui/kernel/qtouchdevice_p.h7
-rw-r--r--src/gui/kernel/qwindow.cpp119
-rw-r--r--src/gui/kernel/qwindow.h15
-rw-r--r--src/gui/kernel/qwindow_p.h17
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp580
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h74
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h18
-rw-r--r--src/gui/opengl/opengl.pri6
-rw-r--r--src/gui/opengl/qopengl.cpp21
-rw-r--r--src/gui/opengl/qopengldebug.h5
-rw-r--r--src/gui/opengl/qopenglengineshadermanager.cpp97
-rw-r--r--src/gui/opengl/qopenglengineshadermanager_p.h1
-rw-r--r--src/gui/opengl/qopenglfunctions.h568
-rw-r--r--src/gui/opengl/qopenglprogrambinarycache.cpp336
-rw-r--r--src/gui/opengl/qopenglprogrambinarycache_p.h100
-rw-r--r--src/gui/opengl/qopenglshaderprogram.cpp541
-rw-r--r--src/gui/opengl/qopenglshaderprogram.h12
-rw-r--r--src/gui/opengl/qopengltextureblitter.cpp4
-rw-r--r--src/gui/opengl/qopengltextureglyphcache.cpp12
-rw-r--r--src/gui/painting/painting.pri3
-rw-r--r--src/gui/painting/qcolorprofile.cpp87
-rw-r--r--src/gui/painting/qcolorprofile_p.h157
-rw-r--r--src/gui/painting/qcoregraphics.mm3
-rw-r--r--src/gui/painting/qdrawhelper.cpp148
-rw-r--r--src/gui/painting/qdrawhelper_p.h14
-rw-r--r--src/gui/painting/qmemrotate.cpp275
-rw-r--r--src/gui/painting/qmemrotate_p.h13
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp46
-rw-r--r--src/gui/painting/qpdf.cpp13
-rw-r--r--src/gui/painting/qrgba64_p.h95
-rw-r--r--src/gui/text/qtextdocument.cpp19
-rw-r--r--src/gui/text/qtextdocument.h1
-rw-r--r--src/gui/text/qtexthtmlparser.cpp57
-rw-r--r--src/gui/text/qtextlayout.cpp10
-rw-r--r--src/gui/util/qdesktopservices.cpp9
-rw-r--r--src/network/access/qhttpnetworkreply.cpp8
-rw-r--r--src/network/access/qhttpnetworkreply_p.h2
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp3
-rw-r--r--src/network/access/qhttpthreaddelegate_p.h3
-rw-r--r--src/network/access/qnetworkaccessbackend_p.h1
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp13
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h4
-rw-r--r--src/network/access/qnetworkrequest.cpp7
-rw-r--r--src/network/access/qnetworkrequest.h1
-rw-r--r--src/network/bearer/qnetworkconfiguration.cpp38
-rw-r--r--src/network/bearer/qnetworkconfiguration.h3
-rw-r--r--src/network/bearer/qnetworkconfiguration_p.h6
-rw-r--r--src/network/kernel/kernel.pri3
-rw-r--r--src/network/kernel/qhostaddress.cpp10
-rw-r--r--src/network/socket/qabstractsocket.cpp35
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp14
-rw-r--r--src/network/socket/qsctpserver.h2
-rw-r--r--src/network/socket/qsctpsocket.h2
-rw-r--r--src/network/socket/qsocks5socketengine.cpp11
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp2
-rw-r--r--src/network/ssl/qsslsocket_winrt.cpp8
-rw-r--r--src/opengl/qgl.h9
-rw-r--r--src/platformsupport/devicediscovery/qdevicediscovery_static.cpp4
-rw-r--r--src/platformsupport/eglconvenience/qeglconvenience.cpp18
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp7
-rw-r--r--src/platformsupport/fbconvenience/qfbcursor.cpp18
-rw-r--r--src/platformsupport/fbconvenience/qfbcursor_p.h11
-rw-r--r--src/platformsupport/fbconvenience/qfbscreen.cpp159
-rw-r--r--src/platformsupport/fbconvenience/qfbscreen_p.h21
-rw-r--r--src/platformsupport/fbconvenience/qfbwindow.cpp32
-rw-r--r--src/platformsupport/fontdatabases/fontdatabases.pro2
-rw-r--r--src/platformsupport/fontdatabases/mac/coretext.pri21
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp7
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h8
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp14
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h26
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp4
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h4
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h4
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp4
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp4
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp4
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp4
-rw-r--r--src/platformsupport/kmsconvenience/kmsconvenience.pro20
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice.cpp651
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice_p.h168
-rw-r--r--src/platformsupport/platformsupport.pro4
-rw-r--r--src/plugins/platforms/bsdfb/qbsdfbscreen.cpp2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplication.mm24
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm14
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h17
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm107
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h61
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm576
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h7
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm123
-rw-r--r--src/plugins/platforms/cocoa/qnswindowdelegate.h7
-rw-r--r--src/plugins/platforms/cocoa/qnswindowdelegate.mm58
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp21
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp18
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp5
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp21
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp19
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp166
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp9
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp27
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h4
-rw-r--r--src/plugins/platforms/eglfs/api/api.pri13
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfscontext_p.h10
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfscursor.cpp4
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfscursor_p.h10
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp11
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsintegration.cpp53
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsintegration_p.h45
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsoffscreenwindow_p.h4
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsscreen.cpp11
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsscreen_p.h22
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfswindow.cpp37
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfswindow_p.h50
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.h14
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmmain.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/eglfs_emu.json3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/eglfs_emu.pro27
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp134
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h74
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp178
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h85
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemumain.cpp56
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h8
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp36
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h15
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp24
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h12
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmmain.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp17
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h12
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp23
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h14
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp27
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h19
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp16
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h8
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp461
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h60
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp121
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h48
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp52
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h62
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.h6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmalimain.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h10
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivmain.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h12
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlmain.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.h14
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11main.cpp2
-rw-r--r--src/plugins/platforms/eglfs/eglfs-plugin.pro2
-rw-r--r--src/plugins/platforms/eglfs/eglfsdeviceintegration.pro5
-rw-r--r--src/plugins/platforms/eglfs/qeglfsmain.cpp2
-rw-r--r--src/plugins/platforms/ios/kernel.pro5
-rw-r--r--src/plugins/platforms/ios/optional/nsphotolibrarysupport/nsphotolibrarysupport.pro6
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm3
-rw-r--r--src/plugins/platforms/ios/qiosmessagedialog.mm3
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm7
-rw-r--r--src/plugins/platforms/ios/qiostextinputoverlay.mm4
-rw-r--r--src/plugins/platforms/ios/quiview.mm3
-rw-r--r--src/plugins/platforms/linuxfb/linuxfb.pro14
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp409
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.h (renamed from src/gui/painting/qgammatables.cpp)38
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp13
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbintegration.h4
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp2
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbscreen.h6
-rw-r--r--src/plugins/platforms/minimalegl/minimalegl.pro7
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglintegration.cpp12
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglintegration.h3
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglscreen.cpp14
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglscreen.h4
-rw-r--r--src/plugins/platforms/qnx/qnx.pro14
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.cpp8
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.h4
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp6
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.h8
-rw-r--r--src/plugins/platforms/vnc/qvncscreen.cpp13
-rw-r--r--src/plugins/platforms/vnc/qvncscreen.h4
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.h2
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp17
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h3
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.h12
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.h20
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp131
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h39
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp94
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.h18
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp37
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h18
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h34
-rw-r--r--src/plugins/platforms/windows/qwindowsgdiintegration.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsgdinativeinterface.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h31
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.h26
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h38
-rw-r--r--src/plugins/platforms/windows/qwindowsinternalmimedata.h6
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp52
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp9
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp1
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.h18
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp11
-rw-r--r--src/plugins/platforms/windows/qwindowsole.h12
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.h10
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h52
-rw-r--r--src/plugins/platforms/windows/qwindowssessionmanager.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowssessionmanager.h14
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.h21
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h12
-rw-r--r--src/plugins/platforms/windows/qwindowsthreadpoolrunner.h2
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp95
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h131
-rw-r--r--src/plugins/platforms/windows/windows.pri4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp45
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h2
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3theme.cpp23
-rw-r--r--src/printsupport/kernel/qplatformprintplugin.cpp14
-rw-r--r--src/src.pro12
-rw-r--r--src/testlib/qtestcase.cpp37
-rw-r--r--src/tools/bootstrap/bootstrap.pro5
-rw-r--r--src/tools/moc/generator.cpp20
-rw-r--r--src/tools/moc/preprocessor.cpp29
-rw-r--r--src/tools/moc/preprocessor.h1
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.cpp24
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.h4
-rw-r--r--src/widgets/accessible/simplewidgets.cpp12
-rw-r--r--src/widgets/dialogs/qfileinfogatherer.cpp48
-rw-r--r--src/widgets/dialogs/qfileinfogatherer_p.h4
-rw-r--r--src/widgets/dialogs/qwizard_win.cpp3
-rw-r--r--src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp10
-rw-r--r--src/widgets/itemviews/qlistview.cpp8
-rw-r--r--src/widgets/kernel/qapplication.cpp42
-rw-r--r--src/widgets/kernel/qapplication_p.h6
-rw-r--r--src/widgets/kernel/qwidget.cpp19
-rw-r--r--src/widgets/kernel/qwidget.h1
-rw-r--r--src/widgets/styles/qcommonstyle.cpp2
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm24
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp3
-rw-r--r--src/widgets/util/qsystemtrayicon.cpp117
-rw-r--r--src/widgets/util/qsystemtrayicon.h1
-rw-r--r--src/widgets/util/qsystemtrayicon_p.h19
-rw-r--r--src/widgets/util/qsystemtrayicon_qpa.cpp17
-rw-r--r--src/widgets/util/qsystemtrayicon_win.cpp57
-rw-r--r--src/widgets/util/qsystemtrayicon_x11.cpp17
-rw-r--r--src/widgets/widgets/qmenubar.cpp1
-rw-r--r--src/widgets/widgets/qsplitter.cpp71
-rw-r--r--src/widgets/widgets/qsplitter.h1
-rw-r--r--src/widgets/widgets/qsplitter_p.h1
451 files changed, 29024 insertions, 22751 deletions
diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
index 4ba2ee3ec4..0f7d7c2bda 100644
--- a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
+++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
@@ -13,7 +13,7 @@ load(qt_helper_lib)
SHAPERS += opentype # HB's main shaper; enabling it should be enough most of the time
# native shaper on Apple platforms; could be used alone to handle both OT and AAT fonts
-darwin:!if(watchos:CONFIG(simulator, simulator|device)): SHAPERS += coretext
+darwin: SHAPERS += coretext
DEFINES += HAVE_CONFIG_H
DEFINES += HB_NO_UNICODE_FUNCS HB_DISABLE_DEPRECATED
@@ -155,4 +155,20 @@ contains(SHAPERS, coretext) {
# On Mac OS they are part of the ApplicationServices umbrella framework,
# even in 10.8 where they were also made available stand-alone.
LIBS_PRIVATE += -framework ApplicationServices
+
+ # CoreText is documented to be available on watchOS, but the headers aren't present
+ # in the watchOS Simulator SDK like they are supposed to be. Work around the problem
+ # by adding the device SDK's headers to the search path as a fallback.
+ # rdar://25314492, rdar://27844864
+ watchos:simulator {
+ simulator_system_frameworks = $$xcodeSDKInfo(Path, $${simulator.sdk})/System/Library/Frameworks
+ device_system_frameworks = $$xcodeSDKInfo(Path, $${device.sdk})/System/Library/Frameworks
+ for (arch, QMAKE_APPLE_SIMULATOR_ARCHS) {
+ QMAKE_CXXFLAGS += \
+ -Xarch_$${arch} \
+ -F$$simulator_system_frameworks \
+ -Xarch_$${arch} \
+ -F$$device_system_frameworks
+ }
+ }
}
diff --git a/src/3rdparty/pcre/COPYING b/src/3rdparty/pcre/COPYING
deleted file mode 100644
index 58eed01b61..0000000000
--- a/src/3rdparty/pcre/COPYING
+++ /dev/null
@@ -1,5 +0,0 @@
-PCRE LICENCE
-
-Please see the file LICENCE in the PCRE distribution for licensing details.
-
-End
diff --git a/src/3rdparty/pcre/config.h b/src/3rdparty/pcre/config.h
deleted file mode 100644
index de3832a8e2..0000000000
--- a/src/3rdparty/pcre/config.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#define HAVE_MEMMOVE 1
-#define HAVE_STDLIB_H 1
-#define HAVE_STRING_H 1
-
-#define LINK_SIZE 2
-#define MATCH_LIMIT 10000000
-#define MATCH_LIMIT_RECURSION MATCH_LIMIT
-#define MAX_NAME_COUNT 10000
-#define MAX_NAME_SIZE 32
-#define NEWLINE 10
-#define PARENS_NEST_LIMIT 250
-
-#define POSIX_MALLOC_THRESHOLD 10
-#define SUPPORT_UCP
-#define SUPPORT_UTF16
-
-/*
- man 3 pcrejit for a list of supported platforms;
- as PCRE 8.35, stable JIT support is available for:
- - ARM v5, v7, and Thumb2 (__GNUC__ compilers only)
- - x86/x86-64
- - MIPS 32bit (__GNUC__ compilers only)
- - Power PC 32-bit and 64-bit (__GNUC__ compilers only)
-*/
-#if !defined(PCRE_DISABLE_JIT) && (\
- /* ARM */ \
- (defined(__GNUC__) && (defined(__arm__) || defined(__TARGET_ARCH_ARM))) \
- /* x86 32/64 */ \
- || defined(__i386) || defined(__i386__) || defined(_M_IX86) \
- || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) \
- /* MIPS32 */ \
- || (defined(__GNUC__) \
- && (defined(__mips) || defined(__mips__)) \
- && !(defined(_MIPS_ARCH_MIPS64) || defined(__mips64))) \
- || (defined(__GNUC__) \
- && (defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \
- || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \
- || defined(_M_MPPC) || defined(_M_PPC))) \
- )
-# define SUPPORT_JIT
-#endif
diff --git a/src/3rdparty/pcre/import_from_pcre_tarball.sh b/src/3rdparty/pcre/import_from_pcre_tarball.sh
deleted file mode 100755
index 6bab1d4581..0000000000
--- a/src/3rdparty/pcre/import_from_pcre_tarball.sh
+++ /dev/null
@@ -1,155 +0,0 @@
-#! /bin/sh
-#############################################################################
-##
-## Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is the build configuration utility of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-# This is a small script to copy the required files from a PCRE tarball
-# into 3rdparty/pcre/ , following the instructions found in the NON-UNIX-USE
-# file. Documentation, tests, demos etc. are not imported.
-
-if [ $# -ne 2 ]; then
- echo "Usage: $0 pcre_tarball_dir/ \$QTDIR/src/3rdparty/pcre/"
- exit 1
-fi
-
-PCRE_DIR=$1
-TARGET_DIR=$2
-
-if [ ! -d "$PCRE_DIR" -o ! -r "$PCRE_DIR" -o ! -d "$TARGET_DIR" -o ! -w "$TARGET_DIR" ]; then
- echo "Either the PCRE source dir or the target dir do not exist,"
- echo "are not directories or have the wrong permissions."
- exit 2
-fi
-
-# with 1 argument, copies PCRE_DIR/$1 to TARGET_DIR/$1
-# with 2 arguments, copies PCRE_DIR/$1 to TARGET_DIR/$2
-copy_file() {
- if [ $# -lt 1 -o $# -gt 2 ]; then
- echo "Wrong number of arguments to copy_file"
- exit 3
- fi
-
- SOURCE_FILE=$1
- if [ -n "$2" ]; then
- DEST_FILE=$2
- else
- DEST_FILE=$1
- fi
-
- mkdir -p "$TARGET_DIR/$(dirname "$SOURCE_FILE")"
- cp "$PCRE_DIR/$SOURCE_FILE" "$TARGET_DIR/$DEST_FILE"
-}
-
-copy_file "pcre.h.generic" "pcre.h"
-copy_file "pcre_chartables.c.dist" "pcre_chartables.c"
-
-FILES="
- AUTHORS
- COPYING
- LICENCE
- pcre_internal.h
- ucp.h
- pcre_byte_order.c
- pcre_compile.c
- pcre_config.c
- pcre_dfa_exec.c
- pcre_exec.c
- pcre_fullinfo.c
- pcre_get.c
- pcre_globals.c
- pcre_jit_compile.c
- pcre_maketables.c
- pcre_newline.c
- pcre_ord2utf8.c
- pcre_refcount.c
- pcre_string_utils.c
- pcre_study.c
- pcre_tables.c
- pcre_ucd.c
- pcre_valid_utf8.c
- pcre_version.c
- pcre_xclass.c
- pcre16_byte_order.c
- pcre16_chartables.c
- pcre16_compile.c
- pcre16_config.c
- pcre16_dfa_exec.c
- pcre16_exec.c
- pcre16_fullinfo.c
- pcre16_get.c
- pcre16_globals.c
- pcre16_jit_compile.c
- pcre16_maketables.c
- pcre16_newline.c
- pcre16_ord2utf16.c
- pcre16_refcount.c
- pcre16_string_utils.c
- pcre16_study.c
- pcre16_tables.c
- pcre16_ucd.c
- pcre16_utf16_utils.c
- pcre16_valid_utf16.c
- pcre16_version.c
- pcre16_xclass.c
- sljit/sljitConfig.h
- sljit/sljitConfigInternal.h
- sljit/sljitExecAllocator.c
- sljit/sljitLir.c
- sljit/sljitLir.h
- sljit/sljitNativeARM_32.c
- sljit/sljitNativeARM_64.c
- sljit/sljitNativeARM_T2_32.c
- sljit/sljitNativeMIPS_32.c
- sljit/sljitNativeMIPS_64.c
- sljit/sljitNativeMIPS_common.c
- sljit/sljitNativePPC_32.c
- sljit/sljitNativePPC_64.c
- sljit/sljitNativePPC_common.c
- sljit/sljitNativeSPARC_32.c
- sljit/sljitNativeSPARC_common.c
- sljit/sljitNativeTILEGX_64.c
- sljit/sljitNativeTILEGX-encoder.c
- sljit/sljitNativeX86_32.c
- sljit/sljitNativeX86_64.c
- sljit/sljitNativeX86_common.c
- sljit/sljitUtils.c
-"
-
-for i in $FILES; do
- copy_file "$i"
-done
diff --git a/src/3rdparty/pcre/patches/README b/src/3rdparty/pcre/patches/README
deleted file mode 100644
index 1d2bc389dd..0000000000
--- a/src/3rdparty/pcre/patches/README
+++ /dev/null
@@ -1,3 +0,0 @@
-These patches are landed in upstream PCRE (they're marked with
-their SVN revision number). When upgrading PCRE remember check
-if the version you're upgrading to already contains them or not.
diff --git a/src/3rdparty/pcre/pcre.h b/src/3rdparty/pcre/pcre.h
deleted file mode 100644
index 7055970065..0000000000
--- a/src/3rdparty/pcre/pcre.h
+++ /dev/null
@@ -1,677 +0,0 @@
-/*************************************************
-* 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-2014 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 39
-#define PCRE_PRERELEASE
-#define PCRE_DATE 2016-06-14
-
-/* 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 <stdlib.h>
-
-/* Allow for C++ users */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Public options. Some are compile-time only, some are run-time only, and some
-are both. Most of the compile-time options are saved with the compiled regex so
-that they can be inspected during studying (and therefore JIT compiling). Note
-that pcre_study() has its own set of options. Originally, all the options
-defined here used distinct bits. However, almost all the bits in a 32-bit word
-are now used, so in order to conserve them, option bits that were previously
-only recognized at matching time (i.e. by pcre_exec() or pcre_dfa_exec()) may
-also be used for compile-time options that affect only compiling and are not
-relevant for studying or JIT compiling.
-
-Some options for pcre_compile() change its behaviour but do not affect the
-behaviour of the execution functions. Other options are passed through to the
-execution functions and affect their behaviour, with or without affecting the
-behaviour of pcre_compile().
-
-Options that can be passed to pcre_compile() are tagged Cx below, with these
-variants:
-
-C1 Affects compile only
-C2 Does not affect compile; affects exec, dfa_exec
-C3 Affects compile, exec, dfa_exec
-C4 Affects compile, exec, dfa_exec, study
-C5 Affects compile, exec, study
-
-Options that can be set for pcre_exec() and/or pcre_dfa_exec() are flagged with
-E and D, respectively. They take precedence over C3, C4, and C5 settings passed
-from pcre_compile(). Those that are compatible with JIT execution are flagged
-with J. */
-
-#define PCRE_CASELESS 0x00000001 /* C1 */
-#define PCRE_MULTILINE 0x00000002 /* C1 */
-#define PCRE_DOTALL 0x00000004 /* C1 */
-#define PCRE_EXTENDED 0x00000008 /* C1 */
-#define PCRE_ANCHORED 0x00000010 /* C4 E D */
-#define PCRE_DOLLAR_ENDONLY 0x00000020 /* C2 */
-#define PCRE_EXTRA 0x00000040 /* C1 */
-#define PCRE_NOTBOL 0x00000080 /* E D J */
-#define PCRE_NOTEOL 0x00000100 /* E D J */
-#define PCRE_UNGREEDY 0x00000200 /* C1 */
-#define PCRE_NOTEMPTY 0x00000400 /* E D J */
-#define PCRE_UTF8 0x00000800 /* C4 ) */
-#define PCRE_UTF16 0x00000800 /* C4 ) Synonyms */
-#define PCRE_UTF32 0x00000800 /* C4 ) */
-#define PCRE_NO_AUTO_CAPTURE 0x00001000 /* C1 */
-#define PCRE_NO_UTF8_CHECK 0x00002000 /* C1 E D J ) */
-#define PCRE_NO_UTF16_CHECK 0x00002000 /* C1 E D J ) Synonyms */
-#define PCRE_NO_UTF32_CHECK 0x00002000 /* C1 E D J ) */
-#define PCRE_AUTO_CALLOUT 0x00004000 /* C1 */
-#define PCRE_PARTIAL_SOFT 0x00008000 /* E D J ) Synonyms */
-#define PCRE_PARTIAL 0x00008000 /* E D J ) */
-
-/* This pair use the same bit. */
-#define PCRE_NEVER_UTF 0x00010000 /* C1 ) Overlaid */
-#define PCRE_DFA_SHORTEST 0x00010000 /* D ) Overlaid */
-
-/* This pair use the same bit. */
-#define PCRE_NO_AUTO_POSSESS 0x00020000 /* C1 ) Overlaid */
-#define PCRE_DFA_RESTART 0x00020000 /* D ) Overlaid */
-
-#define PCRE_FIRSTLINE 0x00040000 /* C3 */
-#define PCRE_DUPNAMES 0x00080000 /* C1 */
-#define PCRE_NEWLINE_CR 0x00100000 /* C3 E D */
-#define PCRE_NEWLINE_LF 0x00200000 /* C3 E D */
-#define PCRE_NEWLINE_CRLF 0x00300000 /* C3 E D */
-#define PCRE_NEWLINE_ANY 0x00400000 /* C3 E D */
-#define PCRE_NEWLINE_ANYCRLF 0x00500000 /* C3 E D */
-#define PCRE_BSR_ANYCRLF 0x00800000 /* C3 E D */
-#define PCRE_BSR_UNICODE 0x01000000 /* C3 E D */
-#define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* C5 */
-#define PCRE_NO_START_OPTIMIZE 0x04000000 /* C2 E D ) Synonyms */
-#define PCRE_NO_START_OPTIMISE 0x04000000 /* C2 E D ) */
-#define PCRE_PARTIAL_HARD 0x08000000 /* E D J */
-#define PCRE_NOTEMPTY_ATSTART 0x10000000 /* E D J */
-#define PCRE_UCP 0x20000000 /* C3 */
-
-/* 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/32 */
-#define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16/32 */
-#define PCRE_ERROR_BADUTF32 (-10) /* Same for 8/16/32 */
-#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)
-#define PCRE_ERROR_DFA_BADRESTART (-30)
-#define PCRE_ERROR_JIT_BADOPTION (-31)
-#define PCRE_ERROR_BADLENGTH (-32)
-#define PCRE_ERROR_UNSET (-33)
-
-/* 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
-#define PCRE_UTF8_ERR22 22 /* Unused (was non-character) */
-
-/* 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 /* Unused (was non-character) */
-
-/* Specific error codes for UTF-32 validity checks */
-
-#define PCRE_UTF32_ERR0 0
-#define PCRE_UTF32_ERR1 1
-#define PCRE_UTF32_ERR2 2 /* Unused (was non-character) */
-#define PCRE_UTF32_ERR3 3
-
-/* 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
-#define PCRE_INFO_MAXLOOKBEHIND 18
-#define PCRE_INFO_FIRSTCHARACTER 19
-#define PCRE_INFO_FIRSTCHARACTERFLAGS 20
-#define PCRE_INFO_REQUIREDCHAR 21
-#define PCRE_INFO_REQUIREDCHARFLAGS 22
-#define PCRE_INFO_MATCHLIMIT 23
-#define PCRE_INFO_RECURSIONLIMIT 24
-#define PCRE_INFO_MATCH_EMPTY 25
-
-/* 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
-#define PCRE_CONFIG_UTF32 12
-#define PCRE_CONFIG_PARENS_LIMIT 13
-
-/* Request types for pcre_study(). Do not re-arrange, in order to remain
-compatible. */
-
-#define PCRE_STUDY_JIT_COMPILE 0x0001
-#define PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE 0x0002
-#define PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE 0x0004
-#define PCRE_STUDY_EXTRA_NEEDED 0x0008
-
-/* Bit flags for the pcre[16|32]_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_pcre32; /* declaration; the definition is private */
-typedef struct real_pcre32 pcre32;
-
-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;
-
-struct real_pcre32_jit_stack; /* declaration; the definition is private */
-typedef struct real_pcre32_jit_stack pcre32_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
-
-/* If PCRE is compiled with 32 bit character support, PCRE_UCHAR32 must contain
-a 32 bit wide signed data type. Otherwise it can be a dummy data type since
-pcre32 functions are not implemented. There is a check for this in pcre_internal.h. */
-#ifndef PCRE_UCHAR32
-#define PCRE_UCHAR32 unsigned int
-#endif
-
-#ifndef PCRE_SPTR32
-#define PCRE_SPTR32 const PCRE_UCHAR32 *
-#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;
-
-/* Same structure as above, but with 32 bit char pointers. */
-
-typedef struct pcre32_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_UCHAR32 **mark; /* For passing back a mark pointer */
- void *executable_jit; /* Contains a pointer to a compiled jit code */
-} pcre32_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;
-
-/* Same structure as above, but with 32 bit char pointers. */
-
-typedef struct pcre32_callout_block {
- int version; /* Identifies version of block */
- /* ------------------------ Version 0 ------------------------------- */
- int callout_number; /* Number compiled into pattern */
- int *offset_vector; /* The offset vector */
- PCRE_SPTR32 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_UCHAR32 *mark; /* Pointer to current mark or NULL */
- /* ------------------------------------------------------------------ */
-} pcre32_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 int (*pcre_stack_guard)(void);
-
-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 *);
-PCRE_EXP_DECL int (*pcre16_stack_guard)(void);
-
-PCRE_EXP_DECL void *(*pcre32_malloc)(size_t);
-PCRE_EXP_DECL void (*pcre32_free)(void *);
-PCRE_EXP_DECL void *(*pcre32_stack_malloc)(size_t);
-PCRE_EXP_DECL void (*pcre32_stack_free)(void *);
-PCRE_EXP_DECL int (*pcre32_callout)(pcre32_callout_block *);
-PCRE_EXP_DECL int (*pcre32_stack_guard)(void);
-#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 int pcre_stack_guard(void);
-
-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 *);
-PCRE_EXP_DECL int pcre16_stack_guard(void);
-
-PCRE_EXP_DECL void *pcre32_malloc(size_t);
-PCRE_EXP_DECL void pcre32_free(void *);
-PCRE_EXP_DECL void *pcre32_stack_malloc(size_t);
-PCRE_EXP_DECL void pcre32_stack_free(void *);
-PCRE_EXP_DECL int pcre32_callout(pcre32_callout_block *);
-PCRE_EXP_DECL int pcre32_stack_guard(void);
-#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 *);
-typedef pcre32_jit_stack *(*pcre32_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 pcre32 *pcre32_compile(PCRE_SPTR32, 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 pcre32 *pcre32_compile2(PCRE_SPTR32, 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 pcre32_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 pcre32_copy_named_substring(const pcre32 *, PCRE_SPTR32,
- int *, int, PCRE_SPTR32, PCRE_UCHAR32 *, 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 pcre32_copy_substring(PCRE_SPTR32, int *, int, int,
- PCRE_UCHAR32 *, 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 pcre32_dfa_exec(const pcre32 *, const pcre32_extra *,
- PCRE_SPTR32, 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 int pcre32_exec(const pcre32 *, const pcre32_extra *,
- PCRE_SPTR32, int, int, int, int *, int);
-PCRE_EXP_DECL int pcre_jit_exec(const pcre *, const pcre_extra *,
- PCRE_SPTR, int, int, int, int *, int,
- pcre_jit_stack *);
-PCRE_EXP_DECL int pcre16_jit_exec(const pcre16 *, const pcre16_extra *,
- PCRE_SPTR16, int, int, int, int *, int,
- pcre16_jit_stack *);
-PCRE_EXP_DECL int pcre32_jit_exec(const pcre32 *, const pcre32_extra *,
- PCRE_SPTR32, int, int, int, int *, int,
- pcre32_jit_stack *);
-PCRE_EXP_DECL void pcre_free_substring(const char *);
-PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16);
-PCRE_EXP_DECL void pcre32_free_substring(PCRE_SPTR32);
-PCRE_EXP_DECL void pcre_free_substring_list(const char **);
-PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *);
-PCRE_EXP_DECL void pcre32_free_substring_list(PCRE_SPTR32 *);
-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 pcre32_fullinfo(const pcre32 *, const pcre32_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 pcre32_get_named_substring(const pcre32 *, PCRE_SPTR32,
- int *, int, PCRE_SPTR32, PCRE_SPTR32 *);
-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 pcre32_get_stringnumber(const pcre32 *, PCRE_SPTR32);
-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 pcre32_get_stringtable_entries(const pcre32 *, PCRE_SPTR32,
- PCRE_UCHAR32 **, PCRE_UCHAR32 **);
-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 pcre32_get_substring(PCRE_SPTR32, int *, int, int,
- PCRE_SPTR32 *);
-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 int pcre32_get_substring_list(PCRE_SPTR32, int *, int,
- PCRE_SPTR32 **);
-PCRE_EXP_DECL const unsigned char *pcre_maketables(void);
-PCRE_EXP_DECL const unsigned char *pcre16_maketables(void);
-PCRE_EXP_DECL const unsigned char *pcre32_maketables(void);
-PCRE_EXP_DECL int pcre_refcount(pcre *, int);
-PCRE_EXP_DECL int pcre16_refcount(pcre16 *, int);
-PCRE_EXP_DECL int pcre32_refcount(pcre32 *, 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 pcre32_extra *pcre32_study(const pcre32 *, int, const char **);
-PCRE_EXP_DECL void pcre_free_study(pcre_extra *);
-PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *);
-PCRE_EXP_DECL void pcre32_free_study(pcre32_extra *);
-PCRE_EXP_DECL const char *pcre_version(void);
-PCRE_EXP_DECL const char *pcre16_version(void);
-PCRE_EXP_DECL const char *pcre32_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 pcre32_pattern_to_host_byte_order(pcre32 *, pcre32_extra *,
- const unsigned char *);
-PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *,
- PCRE_SPTR16, int, int *, int);
-PCRE_EXP_DECL int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *,
- PCRE_SPTR32, 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 pcre32_jit_stack *pcre32_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 pcre32_jit_stack_free(pcre32_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 *);
-PCRE_EXP_DECL void pcre32_assign_jit_stack(pcre32_extra *,
- pcre32_jit_callback, void *);
-PCRE_EXP_DECL void pcre_jit_free_unused_memory(void);
-PCRE_EXP_DECL void pcre16_jit_free_unused_memory(void);
-PCRE_EXP_DECL void pcre32_jit_free_unused_memory(void);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* End of pcre.h */
diff --git a/src/3rdparty/pcre/pcre.pro b/src/3rdparty/pcre/pcre.pro
deleted file mode 100644
index add4a932b3..0000000000
--- a/src/3rdparty/pcre/pcre.pro
+++ /dev/null
@@ -1,46 +0,0 @@
-TARGET = qtpcre
-
-CONFIG += \
- static \
- hide_symbols \
- exceptions_off rtti_off warn_off
-
-win32: MODULE_DEFINES += PCRE_STATIC
-MODULE_INCLUDEPATH += $$PWD
-
-load(qt_helper_lib)
-
-DEFINES += HAVE_CONFIG_H
-
-# platform/compiler specific definitions
-uikit|qnx|winrt: DEFINES += PCRE_DISABLE_JIT
-
-SOURCES += \
- $$PWD/pcre16_byte_order.c \
- $$PWD/pcre16_chartables.c \
- $$PWD/pcre16_compile.c \
- $$PWD/pcre16_config.c \
- $$PWD/pcre16_dfa_exec.c \
- $$PWD/pcre16_exec.c \
- $$PWD/pcre16_fullinfo.c \
- $$PWD/pcre16_get.c \
- $$PWD/pcre16_globals.c \
- $$PWD/pcre16_jit_compile.c \
- $$PWD/pcre16_maketables.c \
- $$PWD/pcre16_newline.c \
- $$PWD/pcre16_ord2utf16.c \
- $$PWD/pcre16_refcount.c \
- $$PWD/pcre16_string_utils.c \
- $$PWD/pcre16_study.c \
- $$PWD/pcre16_tables.c \
- $$PWD/pcre16_ucd.c \
- $$PWD/pcre16_utf16_utils.c \
- $$PWD/pcre16_valid_utf16.c \
- $$PWD/pcre16_version.c \
- $$PWD/pcre16_xclass.c
-
-HEADERS += \
- $$PWD/config.h \
- $$PWD/pcre.h \
- $$PWD/pcre_internal.h \
- $$PWD/ucp.h
diff --git a/src/3rdparty/pcre/pcre16_byte_order.c b/src/3rdparty/pcre/pcre16_byte_order.c
deleted file mode 100644
index 11d2973a3d..0000000000
--- a/src/3rdparty/pcre/pcre16_byte_order.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index 7c0ff35f5e..0000000000
--- a/src/3rdparty/pcre/pcre16_chartables.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index e499b67087..0000000000
--- a/src/3rdparty/pcre/pcre16_compile.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index b52138764f..0000000000
--- a/src/3rdparty/pcre/pcre16_config.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index 2ba740e972..0000000000
--- a/src/3rdparty/pcre/pcre16_dfa_exec.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index 7417b1770c..0000000000
--- a/src/3rdparty/pcre/pcre16_exec.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index 544dca6ed5..0000000000
--- a/src/3rdparty/pcre/pcre16_fullinfo.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index 3ded08c622..0000000000
--- a/src/3rdparty/pcre/pcre16_get.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index a136b3d8c2..0000000000
--- a/src/3rdparty/pcre/pcre16_globals.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index ab0cacd764..0000000000
--- a/src/3rdparty/pcre/pcre16_jit_compile.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index b1cd1c579d..0000000000
--- a/src/3rdparty/pcre/pcre16_maketables.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index 7fe201400f..0000000000
--- a/src/3rdparty/pcre/pcre16_newline.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index 8e2ce5ea6c..0000000000
--- a/src/3rdparty/pcre/pcre16_ord2utf16.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*************************************************
-* 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 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
-*/
-
-unsigned int
-PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer)
-{
-#ifdef SUPPORT_UTF
-
-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
deleted file mode 100644
index d3d1543973..0000000000
--- a/src/3rdparty/pcre/pcre16_refcount.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index 382c40799f..0000000000
--- a/src/3rdparty/pcre/pcre16_string_utils.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index f87de081fc..0000000000
--- a/src/3rdparty/pcre/pcre16_study.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index d84297093a..0000000000
--- a/src/3rdparty/pcre/pcre16_tables.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index ee23439a01..0000000000
--- a/src/3rdparty/pcre/pcre16_ucd.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index 49ced0c0b1..0000000000
--- a/src/3rdparty/pcre/pcre16_utf16_utils.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*************************************************
-* 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 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 /* Not SUPPORT_UTF */
-(void)(output); /* Keep picky compilers happy */
-(void)(input);
-(void)(keep_boms);
-(void)(host_byte_order);
-#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
deleted file mode 100644
index 09076539d0..0000000000
--- a/src/3rdparty/pcre/pcre16_valid_utf16.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*************************************************
-* 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-2013 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 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 Unused (was non-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_uint32 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. */
- }
- 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);
-(void)(erroroffset);
-#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
deleted file mode 100644
index e991b1a8cf..0000000000
--- a/src/3rdparty/pcre/pcre16_version.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index 5aac2a36c6..0000000000
--- a/src/3rdparty/pcre/pcre16_xclass.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*************************************************
-* 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
deleted file mode 100644
index cf5f12b04e..0000000000
--- a/src/3rdparty/pcre/pcre_byte_order.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*************************************************
-* 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-2014 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 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
-*/
-
-#if defined COMPILE_PCRE8
-PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *argument_re,
- pcre_extra *extra_data, const unsigned char *tables)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *argument_re,
- pcre16_extra *extra_data, const unsigned char *tables)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *argument_re,
- pcre32_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;
-#if defined SUPPORT_UTF && defined COMPILE_PCRE16
-BOOL utf;
-BOOL utf16_char;
-#endif /* SUPPORT_UTF && COMPILE_PCRE16 */
-#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_uint32(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_uint32(re->flags);
-re->limit_match = swap_uint32(re->limit_match);
-re->limit_recursion = swap_uint32(re->limit_recursion);
-
-#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
-re->first_char = swap_uint16(re->first_char);
-re->req_char = swap_uint16(re->req_char);
-#elif defined COMPILE_PCRE32
-re->first_char = swap_uint32(re->first_char);
-re->req_char = swap_uint32(re->req_char);
-#endif
-
-re->max_lookbehind = swap_uint16(re->max_lookbehind);
-re->top_bracket = swap_uint16(re->top_bracket);
-re->top_backref = swap_uint16(re->top_backref);
-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;
-#if defined SUPPORT_UTF && defined COMPILE_PCRE16
-utf = (re->options & PCRE_UTF16) != 0;
-utf16_char = FALSE;
-#endif /* SUPPORT_UTF && COMPILE_PCRE16 */
-
-while(TRUE)
- {
- /* Swap previous characters. */
- while (length-- > 0)
- {
-#if defined COMPILE_PCRE16
- *ptr = swap_uint16(*ptr);
-#elif defined COMPILE_PCRE32
- *ptr = swap_uint32(*ptr);
-#endif
- ptr++;
- }
-#if defined SUPPORT_UTF && defined COMPILE_PCRE16
- 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;
-#if defined COMPILE_PCRE16
- *ptr = swap_uint16(*ptr);
-#elif defined COMPILE_PCRE32
- *ptr = swap_uint32(*ptr);
-#endif
- switch (*ptr)
- {
- case OP_END:
- return 0;
-
-#if defined SUPPORT_UTF && defined COMPILE_PCRE16
- 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++;
-#if defined COMPILE_PCRE16
- *ptr = swap_uint16(*ptr);
-#elif defined COMPILE_PCRE32
- *ptr = swap_uint32(*ptr);
-#endif
-#ifndef COMPILE_PCRE32
- if (LINK_SIZE > 1)
- {
- /* LINK_SIZE can be 1 or 2 in 16 bit mode. */
- ptr++;
- *ptr = swap_uint16(*ptr);
- }
-#endif
- ptr++;
- length = (GET(ptr, -LINK_SIZE)) - (1 + LINK_SIZE + 1);
-#if defined COMPILE_PCRE16
- *ptr = swap_uint16(*ptr);
-#elif defined COMPILE_PCRE32
- *ptr = swap_uint32(*ptr);
-#endif
- 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/32 bit mode. */
-#else /* In 8-bit mode, the pattern does not need to be processed. */
-return 0;
-#endif /* !COMPILE_PCRE8 */
-}
-
-/* End of pcre_byte_order.c */
diff --git a/src/3rdparty/pcre/pcre_config.c b/src/3rdparty/pcre/pcre_config.c
deleted file mode 100644
index 1cbdd9c960..0000000000
--- a/src/3rdparty/pcre/pcre_config.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*************************************************
-* 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 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
-*/
-
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_config(int what, void *where)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre16_config(int what, void *where)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_config(int what, void *where)
-#endif
-{
-switch (what)
- {
- case PCRE_CONFIG_UTF8:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
- *((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 || defined COMPILE_PCRE32
- *((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_UTF32:
-#if defined COMPILE_PCRE8 || 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_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_PARENS_LIMIT:
- *((unsigned long int *)where) = PARENS_NEST_LIMIT;
- 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_fullinfo.c b/src/3rdparty/pcre/pcre_fullinfo.c
deleted file mode 100644
index a6c2ece6ca..0000000000
--- a/src/3rdparty/pcre/pcre_fullinfo.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*************************************************
-* 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-2013 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 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
-*/
-
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data,
- int what, void *where)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre16_fullinfo(const pcre16 *argument_re, const pcre16_extra *extra_data,
- int what, void *where)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_fullinfo(const pcre32 *argument_re, const pcre32_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)? (int)re->first_char :
- ((re->flags & PCRE_STARTLINE) != 0)? -1 : -2;
- break;
-
- case PCRE_INFO_FIRSTCHARACTER:
- *((pcre_uint32 *)where) =
- (re->flags & PCRE_FIRSTSET) != 0 ? re->first_char : 0;
- break;
-
- case PCRE_INFO_FIRSTCHARACTERFLAGS:
- *((int *)where) =
- ((re->flags & PCRE_FIRSTSET) != 0) ? 1 :
- ((re->flags & PCRE_STARTLINE) != 0) ? 2 : 0;
- 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)? (int)re->req_char : -1;
- break;
-
- case PCRE_INFO_REQUIREDCHAR:
- *((pcre_uint32 *)where) =
- ((re->flags & PCRE_REQCHSET) != 0) ? re->req_char : 0;
- break;
-
- case PCRE_INFO_REQUIREDCHARFLAGS:
- *((int *)where) =
- ((re->flags & PCRE_REQCHSET) != 0);
- 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;
-
- case PCRE_INFO_MAXLOOKBEHIND:
- *((int *)where) = re->max_lookbehind;
- break;
-
- case PCRE_INFO_MATCHLIMIT:
- if ((re->flags & PCRE_MLSET) == 0) return PCRE_ERROR_UNSET;
- *((pcre_uint32 *)where) = re->limit_match;
- break;
-
- case PCRE_INFO_RECURSIONLIMIT:
- if ((re->flags & PCRE_RLSET) == 0) return PCRE_ERROR_UNSET;
- *((pcre_uint32 *)where) = re->limit_recursion;
- break;
-
- case PCRE_INFO_MATCH_EMPTY:
- *((int *)where) = (re->flags & PCRE_MATCH_EMPTY) != 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
deleted file mode 100644
index 9475d5e88c..0000000000
--- a/src/3rdparty/pcre/pcre_get.c
+++ /dev/null
@@ -1,669 +0,0 @@
-/*************************************************
-* 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 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
-*/
-
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_get_stringnumber(const pcre *code, const char *stringname)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre16_get_stringnumber(const pcre16 *code, PCRE_SPTR16 stringname)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_get_stringnumber(const pcre32 *code, PCRE_SPTR32 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
-#ifdef COMPILE_PCRE32
-if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
- return rc;
-if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
-
-if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
- return rc;
-if ((rc = pcre32_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
-*/
-
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_get_stringtable_entries(const pcre *code, const char *stringname,
- char **firstptr, char **lastptr)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 stringname,
- PCRE_UCHAR16 **firstptr, PCRE_UCHAR16 **lastptr)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_get_stringtable_entries(const pcre32 *code, PCRE_SPTR32 stringname,
- PCRE_UCHAR32 **firstptr, PCRE_UCHAR32 **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
-#ifdef COMPILE_PCRE32
-if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
- return rc;
-if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
-
-if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
- return rc;
-if ((rc = pcre32_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;
- }
-#if defined COMPILE_PCRE8
- *firstptr = (char *)first;
- *lastptr = (char *)last;
-#elif defined COMPILE_PCRE16
- *firstptr = (PCRE_UCHAR16 *)first;
- *lastptr = (PCRE_UCHAR16 *)last;
-#elif defined COMPILE_PCRE32
- *firstptr = (PCRE_UCHAR32 *)first;
- *lastptr = (PCRE_UCHAR32 *)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
- stringcount number of captured 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
-*/
-
-#if defined COMPILE_PCRE8
-static int
-get_first_set(const pcre *code, const char *stringname, int *ovector,
- int stringcount)
-#elif defined COMPILE_PCRE16
-static int
-get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector,
- int stringcount)
-#elif defined COMPILE_PCRE32
-static int
-get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector,
- int stringcount)
-#endif
-{
-const REAL_PCRE *re = (const REAL_PCRE *)code;
-int entrysize;
-pcre_uchar *entry;
-#if defined COMPILE_PCRE8
-char *first, *last;
-#elif defined COMPILE_PCRE16
-PCRE_UCHAR16 *first, *last;
-#elif defined COMPILE_PCRE32
-PCRE_UCHAR32 *first, *last;
-#endif
-
-#if defined 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);
-#elif defined COMPILE_PCRE16
-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);
-#elif defined COMPILE_PCRE32
-if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
- return pcre32_get_stringnumber(code, stringname);
-entrysize = pcre32_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 (n < stringcount && 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
-*/
-
-#if defined 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)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
- int stringnumber, PCRE_UCHAR16 *buffer, int size)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_copy_substring(PCRE_SPTR32 subject, int *ovector, int stringcount,
- int stringnumber, PCRE_UCHAR32 *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
-*/
-
-#if defined 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)
-#elif defined COMPILE_PCRE16
-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)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
- int *ovector, int stringcount, PCRE_SPTR32 stringname,
- PCRE_UCHAR32 *buffer, int size)
-#endif
-{
-int n = get_first_set(code, stringname, ovector, stringcount);
-if (n <= 0) return n;
-#if defined COMPILE_PCRE8
-return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
-#elif defined COMPILE_PCRE16
-return pcre16_copy_substring(subject, ovector, stringcount, n, buffer, size);
-#elif defined COMPILE_PCRE32
-return pcre32_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
-*/
-
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_get_substring_list(const char *subject, int *ovector, int stringcount,
- const char ***listptr)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount,
- PCRE_SPTR16 **listptr)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_get_substring_list(PCRE_SPTR32 subject, int *ovector, int stringcount,
- PCRE_SPTR32 **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(1);
- if (ovector[i+1] > ovector[i]) size += IN_UCHARS(ovector[i+1] - ovector[i]);
- }
-
-stringlist = (pcre_uchar **)(PUBL(malloc))(size);
-if (stringlist == NULL) return PCRE_ERROR_NOMEMORY;
-
-#if defined COMPILE_PCRE8
-*listptr = (const char **)stringlist;
-#elif defined COMPILE_PCRE16
-*listptr = (PCRE_SPTR16 *)stringlist;
-#elif defined COMPILE_PCRE32
-*listptr = (PCRE_SPTR32 *)stringlist;
-#endif
-p = (pcre_uchar *)(stringlist + stringcount + 1);
-
-for (i = 0; i < double_count; i += 2)
- {
- int len = (ovector[i+1] > ovector[i])? (ovector[i+1] - ovector[i]) : 0;
- 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
-*/
-
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
-pcre_free_substring_list(const char **pointer)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
-pcre16_free_substring_list(PCRE_SPTR16 *pointer)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
-pcre32_free_substring_list(PCRE_SPTR32 *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
-*/
-
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_get_substring(const char *subject, int *ovector, int stringcount,
- int stringnumber, const char **stringptr)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
- int stringnumber, PCRE_SPTR16 *stringptr)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_get_substring(PCRE_SPTR32 subject, int *ovector, int stringcount,
- int stringnumber, PCRE_SPTR32 *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;
-#if defined COMPILE_PCRE8
-*stringptr = (const char *)substring;
-#elif defined COMPILE_PCRE16
-*stringptr = (PCRE_SPTR16)substring;
-#elif defined COMPILE_PCRE32
-*stringptr = (PCRE_SPTR32)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
-*/
-
-#if defined 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)
-#elif defined COMPILE_PCRE16
-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)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
- int *ovector, int stringcount, PCRE_SPTR32 stringname,
- PCRE_SPTR32 *stringptr)
-#endif
-{
-int n = get_first_set(code, stringname, ovector, stringcount);
-if (n <= 0) return n;
-#if defined COMPILE_PCRE8
-return pcre_get_substring(subject, ovector, stringcount, n, stringptr);
-#elif defined COMPILE_PCRE16
-return pcre16_get_substring(subject, ovector, stringcount, n, stringptr);
-#elif defined COMPILE_PCRE32
-return pcre32_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
-*/
-
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
-pcre_free_substring(const char *pointer)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
-pcre16_free_substring(PCRE_SPTR16 pointer)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
-pcre32_free_substring(PCRE_SPTR32 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
deleted file mode 100644
index 0f106aa901..0000000000
--- a/src/3rdparty/pcre/pcre_globals.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*************************************************
-* 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-2014 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 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;
-PCRE_EXP_DATA_DEFN int (*PUBL(stack_guard))(void) = 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;
-PCRE_EXP_DATA_DEFN int (*PUBL(stack_guard))(void) = NULL;
-#endif
-
-/* End of pcre_globals.c */
diff --git a/src/3rdparty/pcre/pcre_refcount.c b/src/3rdparty/pcre/pcre_refcount.c
deleted file mode 100644
index 79efa90f21..0000000000
--- a/src/3rdparty/pcre/pcre_refcount.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*************************************************
-* 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 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
-*/
-
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_refcount(pcre *argument_re, int adjust)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre16_refcount(pcre16 *argument_re, int adjust)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_refcount(pcre32 *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
deleted file mode 100644
index 25eacc8507..0000000000
--- a/src/3rdparty/pcre/pcre_string_utils.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*************************************************
-* 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-2014 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains internal functions for comparing and finding the length
-of strings for different data item sizes. */
-
-
-#ifdef 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 a 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;
-}
-
-#ifdef COMPILE_PCRE32
-
-int
-PRIV(strcmp_uc_uc_utf)(const pcre_uchar *str1, const pcre_uchar *str2)
-{
-pcre_uchar c1;
-pcre_uchar c2;
-
-while (*str1 != '\0' || *str2 != '\0')
- {
- c1 = UCHAR21INC(str1);
- c2 = UCHAR21INC(str2);
- if (c1 != c2)
- return ((c1 > c2) << 1) - 1;
- }
-/* Both length and characters must be equal. */
-return 0;
-}
-
-#endif /* COMPILE_PCRE32 */
-
-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;
-}
-
-#ifdef COMPILE_PCRE32
-
-int
-PRIV(strcmp_uc_c8_utf)(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 = UCHAR21INC(str1);
- c2 = (pcre_uchar)*ustr2++;
- if (c1 != c2)
- return ((c1 > c2) << 1) - 1;
- }
-/* Both length and characters must be equal. */
-return 0;
-}
-
-#endif /* COMPILE_PCRE32 */
-
-/* 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_version.c b/src/3rdparty/pcre/pcre_version.c
deleted file mode 100644
index ae86ff28bc..0000000000
--- a/src/3rdparty/pcre/pcre_version.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*************************************************
-* 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 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. */
-
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
-pcre_version(void)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
-pcre16_version(void)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
-pcre32_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/qt_attribution.json b/src/3rdparty/pcre/qt_attribution.json
deleted file mode 100644
index fc7515175a..0000000000
--- a/src/3rdparty/pcre/qt_attribution.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "Id": "pcre",
- "Name": "PCRE",
- "QDocModule": "qtcore",
- "QtUsage": "Optionally used in Qt Core (QRegularExpression). Configure with -system-pcre or -no-pcre to avoid.",
-
- "Description": "The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl 5.",
- "Homepage": "http://www.pcre.org/",
- "Version": "8.39",
- "License": "BSD 3-clause \"New\" or \"Revised\" License",
- "LicenseId": "BSD-3-Clause",
- "LicenseFile": "LICENCE",
- "Copyright": "Copyright (c) 1997-2016 University of Cambridge
-Copyright (c) 2009-2016 Zoltan Herczeg
-Copyright (c) 2007-2012, Google Inc."
-}
diff --git a/src/3rdparty/pcre/AUTHORS b/src/3rdparty/pcre2/AUTHORS
index 342417a8a1..d9a0e15690 100644
--- a/src/3rdparty/pcre/AUTHORS
+++ b/src/3rdparty/pcre2/AUTHORS
@@ -1,5 +1,5 @@
-THE MAIN PCRE LIBRARY
----------------------
+THE MAIN PCRE2 LIBRARY CODE
+---------------------------
Written by: Philip Hazel
Email local part: ph10
@@ -12,8 +12,8 @@ Copyright (c) 1997-2016 University of Cambridge
All rights reserved
-PCRE JUST-IN-TIME COMPILATION SUPPORT
--------------------------------------
+PCRE2 JUST-IN-TIME COMPILATION SUPPORT
+--------------------------------------
Written by: Zoltan Herczeg
Email local part: hzmester
@@ -33,13 +33,4 @@ Emain domain: freemail.hu
Copyright(c) 2009-2016 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/LICENCE b/src/3rdparty/pcre2/LICENCE
index dd977af971..6600a65907 100644
--- a/src/3rdparty/pcre/LICENCE
+++ b/src/3rdparty/pcre2/LICENCE
@@ -1,18 +1,18 @@
-PCRE LICENCE
-------------
+PCRE2 LICENCE
+-------------
-PCRE is a library of functions to support regular expressions whose syntax
+PCRE2 is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.
-Release 8 of PCRE is distributed under the terms of the "BSD" licence, as
-specified below. The documentation for PCRE, supplied in the "doc"
+Release 10 of PCRE2 is distributed under the terms of the "BSD" licence, as
+specified below. The documentation for PCRE2, supplied in the "doc"
directory, is distributed under the same terms as the software itself. The data
in the testdata directory is not copyrighted and is in the public domain.
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.
+included in the distribution is a just-in-time compiler that can be used to
+optimize pattern matching. This is an optional feature that can be omitted when
+the library is built.
THE BASIC LIBRARY FUNCTIONS
@@ -29,8 +29,8 @@ Copyright (c) 1997-2016 University of Cambridge
All rights reserved.
-PCRE JUST-IN-TIME COMPILATION SUPPORT
--------------------------------------
+PCRE2 JUST-IN-TIME COMPILATION SUPPORT
+--------------------------------------
Written by: Zoltan Herczeg
Email local part: hzmester
@@ -51,15 +51,6 @@ Copyright(c) 2009-2016 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
-----------------
@@ -73,10 +64,9 @@ modification, are permitted provided that the following conditions are met:
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.
+ * Neither the name of the University of Cambridge nor the names of any
+ 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
diff --git a/src/3rdparty/pcre2/import_from_pcre2_tarball.sh b/src/3rdparty/pcre2/import_from_pcre2_tarball.sh
new file mode 100755
index 0000000000..b20d6c61f2
--- /dev/null
+++ b/src/3rdparty/pcre2/import_from_pcre2_tarball.sh
@@ -0,0 +1,134 @@
+#! /bin/sh
+#############################################################################
+##
+## Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+## Contact: http://www.qt.io/licensing/
+##
+## This file is the build configuration utility of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL21$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see http://www.qt.io/terms-conditions. For further
+## information use the contact form at http://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 or version 3 as published by the Free
+## Software Foundation and appearing in the file LICENSE.LGPLv21 and
+## LICENSE.LGPLv3 included in the packaging of this file. Please review the
+## following information to ensure the GNU Lesser General Public License
+## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## As a special exception, The Qt Company gives you certain additional
+## rights. These rights are described in The Qt Company LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+# This is a small script to copy the required files from a PCRE2 tarball
+# into 3rdparty/pcre2/ , following the instructions found in the NON-AUTOTOOLS-BUILD
+# file. Documentation, tests, demos etc. are not imported.
+
+if [ $# -ne 2 ]; then
+ echo "Usage: $0 pcre2_tarball_dir/ \$QTDIR/src/3rdparty/pcre2/"
+ exit 1
+fi
+
+PCRE2_DIR=$1
+TARGET_DIR=$2
+
+if [ ! -d "$PCRE2_DIR" -o ! -r "$PCRE2_DIR" -o ! -d "$TARGET_DIR" -o ! -w "$TARGET_DIR" ]; then
+ echo "Either the PCRE2 source dir or the target dir do not exist,"
+ echo "are not directories or have the wrong permissions."
+ exit 2
+fi
+
+# with 1 argument, copies PCRE2_DIR/$1 to TARGET_DIR/$1
+# with 2 arguments, copies PCRE2_DIR/$1 to TARGET_DIR/$2
+copy_file() {
+ if [ $# -lt 1 -o $# -gt 2 ]; then
+ echo "Wrong number of arguments to copy_file"
+ exit 3
+ fi
+
+ SOURCE_FILE=$1
+ if [ -n "$2" ]; then
+ DEST_FILE=$2
+ else
+ DEST_FILE=$1
+ fi
+
+ mkdir -p "$TARGET_DIR/$(dirname "$SOURCE_FILE")"
+ cp "$PCRE2_DIR/$SOURCE_FILE" "$TARGET_DIR/$DEST_FILE"
+}
+
+copy_file "src/pcre2.h.generic" "src/pcre2.h"
+copy_file "src/pcre2_chartables.c.dist" "src/pcre2_chartables.c"
+
+FILES="
+ AUTHORS
+ LICENCE
+
+ src/pcre2_auto_possess.c
+ src/pcre2_compile.c
+ src/pcre2_config.c
+ src/pcre2_context.c
+ src/pcre2_dfa_match.c
+ src/pcre2_error.c
+ src/pcre2_find_bracket.c
+ src/pcre2_internal.h
+ src/pcre2_intmodedep.h
+ src/pcre2_jit_compile.c
+ src/pcre2_jit_match.c
+ src/pcre2_jit_misc.c
+ src/pcre2_maketables.c
+ src/pcre2_match.c
+ src/pcre2_match_data.c
+ src/pcre2_newline.c
+ src/pcre2_ord2utf.c
+ src/pcre2_pattern_info.c
+ src/pcre2_printint.c
+ src/pcre2_serialize.c
+ src/pcre2_string_utils.c
+ src/pcre2_study.c
+ src/pcre2_substitute.c
+ src/pcre2_substring.c
+ src/pcre2_tables.c
+ src/pcre2_ucd.c
+ src/pcre2_ucp.h
+ src/pcre2_valid_utf.c
+ src/pcre2_xclass.c
+ src/sljit/sljitConfig.h
+ src/sljit/sljitConfigInternal.h
+ src/sljit/sljitExecAllocator.c
+ src/sljit/sljitLir.c
+ src/sljit/sljitLir.h
+ src/sljit/sljitNativeARM_32.c
+ src/sljit/sljitNativeARM_64.c
+ src/sljit/sljitNativeARM_T2_32.c
+ src/sljit/sljitNativeMIPS_32.c
+ src/sljit/sljitNativeMIPS_64.c
+ src/sljit/sljitNativeMIPS_common.c
+ src/sljit/sljitNativePPC_32.c
+ src/sljit/sljitNativePPC_64.c
+ src/sljit/sljitNativePPC_common.c
+ src/sljit/sljitNativeSPARC_32.c
+ src/sljit/sljitNativeSPARC_common.c
+ src/sljit/sljitNativeTILEGX_64.c
+ src/sljit/sljitNativeTILEGX-encoder.c
+ src/sljit/sljitNativeX86_32.c
+ src/sljit/sljitNativeX86_64.c
+ src/sljit/sljitNativeX86_common.c
+ src/sljit/sljitUtils.c
+"
+
+for i in $FILES; do
+ copy_file "$i"
+done
diff --git a/src/3rdparty/pcre2/pcre2.pro b/src/3rdparty/pcre2/pcre2.pro
new file mode 100644
index 0000000000..d3a4e08bc5
--- /dev/null
+++ b/src/3rdparty/pcre2/pcre2.pro
@@ -0,0 +1,52 @@
+TARGET = qtpcre2
+
+CONFIG += \
+ static \
+ hide_symbols \
+ exceptions_off rtti_off warn_off
+
+
+MODULE_DEFINES += PCRE2_CODE_UNIT_WIDTH=16
+win32: MODULE_DEFINES += PCRE2_STATIC
+MODULE_INCLUDEPATH += $$PWD/src
+
+load(qt_helper_lib)
+
+DEFINES += HAVE_CONFIG_H
+
+# platform/compiler specific definitions
+ios|qnx|winrt: DEFINES += PCRE2_DISABLE_JIT
+
+SOURCES += \
+ $$PWD/src/pcre2_auto_possess.c \
+ $$PWD/src/pcre2_chartables.c \
+ $$PWD/src/pcre2_compile.c \
+ $$PWD/src/pcre2_config.c \
+ $$PWD/src/pcre2_context.c \
+ $$PWD/src/pcre2_dfa_match.c \
+ $$PWD/src/pcre2_error.c \
+ $$PWD/src/pcre2_find_bracket.c \
+ $$PWD/src/pcre2_jit_compile.c \
+ $$PWD/src/pcre2_maketables.c \
+ $$PWD/src/pcre2_match.c \
+ $$PWD/src/pcre2_match_data.c \
+ $$PWD/src/pcre2_newline.c \
+ $$PWD/src/pcre2_ord2utf.c \
+ $$PWD/src/pcre2_pattern_info.c \
+ $$PWD/src/pcre2_printint.c \
+ $$PWD/src/pcre2_serialize.c \
+ $$PWD/src/pcre2_string_utils.c \
+ $$PWD/src/pcre2_study.c \
+ $$PWD/src/pcre2_substitute.c \
+ $$PWD/src/pcre2_substring.c \
+ $$PWD/src/pcre2_tables.c \
+ $$PWD/src/pcre2_ucd.c \
+ $$PWD/src/pcre2_valid_utf.c \
+ $$PWD/src/pcre2_xclass.c
+
+HEADERS += \
+ $$PWD/src/config.h \
+ $$PWD/src/pcre2.h \
+ $$PWD/src/pcre2_internal.h \
+ $$PWD/src/pcre2_intmodedep.h \
+ $$PWD/src/pcre2_ucp.h
diff --git a/src/3rdparty/pcre2/src/config.h b/src/3rdparty/pcre2/src/config.h
new file mode 100644
index 0000000000..fbebfe6be0
--- /dev/null
+++ b/src/3rdparty/pcre2/src/config.h
@@ -0,0 +1,52 @@
+#define HAVE_INTTYPES_H 1
+#define HAVE_MEMMOVE 1
+#define HAVE_LIMITS_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+
+#define LINK_SIZE 2
+#define MATCH_LIMIT 10000000
+#define MATCH_LIMIT_RECURSION MATCH_LIMIT
+#define MAX_NAME_COUNT 10000
+#define MAX_NAME_SIZE 32
+#define NEWLINE_DEFAULT 2
+#define PARENS_NEST_LIMIT 250
+
+#define SUPPORT_UNICODE
+
+/*
+ man 3 pcre2jit for a list of supported platforms;
+ as PCRE2 10.22, stable JIT support is available for:
+ - ARM 32-bit (v5, v7, and Thumb2)
+ - ARM 64-bit
+ - Intel x86 32-bit and 64-bit
+ - MIPS 32-bit and 64-bit
+ - Power PC 32-bit and 64-bit
+ - SPARC 32-bit
+
+ For non-x86 platforms we stick to the __GNUC__ compilers only.
+*/
+#if !defined(PCRE2_DISABLE_JIT) && (\
+ /* ARM */ \
+ (defined(__GNUC__) \
+ && (defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(__aarch64__))) \
+ /* x86 32/64 */ \
+ || defined(__i386) || defined(__i386__) || defined(_M_IX86) \
+ || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) \
+ /* MIPS */ \
+ || (defined(__GNUC__) \
+ && (defined(__mips) || defined(__mips__))) \
+ /* PPC */ \
+ || (defined(__GNUC__) \
+ && (defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \
+ || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \
+ || defined(_M_MPPC) || defined(_M_PPC))) \
+ /* SPARC */ \
+ || (defined(__GNUC__) \
+ && (defined(__sparc__) && !defined(__sparc64__))) \
+ )
+# define SUPPORT_JIT
+#endif
+
diff --git a/src/3rdparty/pcre2/src/pcre2.h b/src/3rdparty/pcre2/src/pcre2.h
new file mode 100644
index 0000000000..20d221b803
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2.h
@@ -0,0 +1,732 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* This is the public header file for the PCRE library, second API, to be
+#included by applications that call PCRE2 functions.
+
+ Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef _PCRE2_H
+#define _PCRE2_H
+
+/* The current PCRE version information. */
+
+#define PCRE2_MAJOR 10
+#define PCRE2_MINOR 22
+#define PCRE2_PRERELEASE
+#define PCRE2_DATE 2016-07-29
+
+/* When an application links to a PCRE DLL in Windows, the symbols that are
+imported have to be identified as such. When building PCRE2, the appropriate
+export setting is defined in pcre2_internal.h, which includes this file. So we
+don't change existing definitions of PCRE2_EXP_DECL. */
+
+#if defined(_WIN32) && !defined(PCRE2_STATIC)
+# ifndef PCRE2_EXP_DECL
+# define PCRE2_EXP_DECL extern __declspec(dllimport)
+# endif
+#endif
+
+/* By default, we use the standard "extern" declarations. */
+
+#ifndef PCRE2_EXP_DECL
+# ifdef __cplusplus
+# define PCRE2_EXP_DECL extern "C"
+# else
+# define PCRE2_EXP_DECL extern
+# endif
+#endif
+
+/* Have to include limits.h, stdlib.h and stdint.h to ensure that size_t and
+uint8_t, UCHAR_MAX, etc are defined. */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+/* Allow for C++ users compiling this directly. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The following option bits can be passed to pcre2_compile(), pcre2_match(),
+or pcre2_dfa_match(). PCRE2_NO_UTF_CHECK affects only the function to which it
+is passed. Put these bits at the most significant end of the options word so
+others can be added next to them */
+
+#define PCRE2_ANCHORED 0x80000000u
+#define PCRE2_NO_UTF_CHECK 0x40000000u
+
+/* The following option bits can be passed only to pcre2_compile(). However,
+they may affect compilation, JIT compilation, and/or interpretive execution.
+The following tags indicate which:
+
+C alters what is compiled by pcre2_compile()
+J alters what is compiled by pcre2_jit_compile()
+M is inspected during pcre2_match() execution
+D is inspected during pcre2_dfa_match() execution
+*/
+
+#define PCRE2_ALLOW_EMPTY_CLASS 0x00000001u /* C */
+#define PCRE2_ALT_BSUX 0x00000002u /* C */
+#define PCRE2_AUTO_CALLOUT 0x00000004u /* C */
+#define PCRE2_CASELESS 0x00000008u /* C */
+#define PCRE2_DOLLAR_ENDONLY 0x00000010u /* J M D */
+#define PCRE2_DOTALL 0x00000020u /* C */
+#define PCRE2_DUPNAMES 0x00000040u /* C */
+#define PCRE2_EXTENDED 0x00000080u /* C */
+#define PCRE2_FIRSTLINE 0x00000100u /* J M D */
+#define PCRE2_MATCH_UNSET_BACKREF 0x00000200u /* C J M */
+#define PCRE2_MULTILINE 0x00000400u /* C */
+#define PCRE2_NEVER_UCP 0x00000800u /* C */
+#define PCRE2_NEVER_UTF 0x00001000u /* C */
+#define PCRE2_NO_AUTO_CAPTURE 0x00002000u /* C */
+#define PCRE2_NO_AUTO_POSSESS 0x00004000u /* C */
+#define PCRE2_NO_DOTSTAR_ANCHOR 0x00008000u /* C */
+#define PCRE2_NO_START_OPTIMIZE 0x00010000u /* J M D */
+#define PCRE2_UCP 0x00020000u /* C J M D */
+#define PCRE2_UNGREEDY 0x00040000u /* C */
+#define PCRE2_UTF 0x00080000u /* C J M D */
+#define PCRE2_NEVER_BACKSLASH_C 0x00100000u /* C */
+#define PCRE2_ALT_CIRCUMFLEX 0x00200000u /* J M D */
+#define PCRE2_ALT_VERBNAMES 0x00400000u /* C */
+#define PCRE2_USE_OFFSET_LIMIT 0x00800000u /* J M D */
+
+/* These are for pcre2_jit_compile(). */
+
+#define PCRE2_JIT_COMPLETE 0x00000001u /* For full matching */
+#define PCRE2_JIT_PARTIAL_SOFT 0x00000002u
+#define PCRE2_JIT_PARTIAL_HARD 0x00000004u
+
+/* These are for pcre2_match(), pcre2_dfa_match(), and pcre2_jit_match(). Note
+that PCRE2_ANCHORED and PCRE2_NO_UTF_CHECK can also be passed to these
+functions (though pcre2_jit_match() ignores the latter since it bypasses all
+sanity checks). */
+
+#define PCRE2_NOTBOL 0x00000001u
+#define PCRE2_NOTEOL 0x00000002u
+#define PCRE2_NOTEMPTY 0x00000004u /* ) These two must be kept */
+#define PCRE2_NOTEMPTY_ATSTART 0x00000008u /* ) adjacent to each other. */
+#define PCRE2_PARTIAL_SOFT 0x00000010u
+#define PCRE2_PARTIAL_HARD 0x00000020u
+
+/* These are additional options for pcre2_dfa_match(). */
+
+#define PCRE2_DFA_RESTART 0x00000040u
+#define PCRE2_DFA_SHORTEST 0x00000080u
+
+/* These are additional options for pcre2_substitute(), which passes any others
+through to pcre2_match(). */
+
+#define PCRE2_SUBSTITUTE_GLOBAL 0x00000100u
+#define PCRE2_SUBSTITUTE_EXTENDED 0x00000200u
+#define PCRE2_SUBSTITUTE_UNSET_EMPTY 0x00000400u
+#define PCRE2_SUBSTITUTE_UNKNOWN_UNSET 0x00000800u
+#define PCRE2_SUBSTITUTE_OVERFLOW_LENGTH 0x00001000u
+
+/* A further option for pcre2_match(), not allowed for pcre2_dfa_match(),
+ignored for pcre2_jit_match(). */
+
+#define PCRE2_NO_JIT 0x00002000u
+
+/* Newline and \R settings, for use in compile contexts. The newline values
+must be kept in step with values set in config.h and both sets must all be
+greater than zero. */
+
+#define PCRE2_NEWLINE_CR 1
+#define PCRE2_NEWLINE_LF 2
+#define PCRE2_NEWLINE_CRLF 3
+#define PCRE2_NEWLINE_ANY 4
+#define PCRE2_NEWLINE_ANYCRLF 5
+
+#define PCRE2_BSR_UNICODE 1
+#define PCRE2_BSR_ANYCRLF 2
+
+/* Error codes: no match and partial match are "expected" errors. */
+
+#define PCRE2_ERROR_NOMATCH (-1)
+#define PCRE2_ERROR_PARTIAL (-2)
+
+/* Error codes for UTF-8 validity checks */
+
+#define PCRE2_ERROR_UTF8_ERR1 (-3)
+#define PCRE2_ERROR_UTF8_ERR2 (-4)
+#define PCRE2_ERROR_UTF8_ERR3 (-5)
+#define PCRE2_ERROR_UTF8_ERR4 (-6)
+#define PCRE2_ERROR_UTF8_ERR5 (-7)
+#define PCRE2_ERROR_UTF8_ERR6 (-8)
+#define PCRE2_ERROR_UTF8_ERR7 (-9)
+#define PCRE2_ERROR_UTF8_ERR8 (-10)
+#define PCRE2_ERROR_UTF8_ERR9 (-11)
+#define PCRE2_ERROR_UTF8_ERR10 (-12)
+#define PCRE2_ERROR_UTF8_ERR11 (-13)
+#define PCRE2_ERROR_UTF8_ERR12 (-14)
+#define PCRE2_ERROR_UTF8_ERR13 (-15)
+#define PCRE2_ERROR_UTF8_ERR14 (-16)
+#define PCRE2_ERROR_UTF8_ERR15 (-17)
+#define PCRE2_ERROR_UTF8_ERR16 (-18)
+#define PCRE2_ERROR_UTF8_ERR17 (-19)
+#define PCRE2_ERROR_UTF8_ERR18 (-20)
+#define PCRE2_ERROR_UTF8_ERR19 (-21)
+#define PCRE2_ERROR_UTF8_ERR20 (-22)
+#define PCRE2_ERROR_UTF8_ERR21 (-23)
+
+/* Error codes for UTF-16 validity checks */
+
+#define PCRE2_ERROR_UTF16_ERR1 (-24)
+#define PCRE2_ERROR_UTF16_ERR2 (-25)
+#define PCRE2_ERROR_UTF16_ERR3 (-26)
+
+/* Error codes for UTF-32 validity checks */
+
+#define PCRE2_ERROR_UTF32_ERR1 (-27)
+#define PCRE2_ERROR_UTF32_ERR2 (-28)
+
+/* Error codes for pcre2[_dfa]_match(), substring extraction functions, context
+functions, and serializing functions. They are in numerical order. Originally
+they were in alphabetical order too, but now that PCRE2 is released, the
+numbers must not be changed. */
+
+#define PCRE2_ERROR_BADDATA (-29)
+#define PCRE2_ERROR_MIXEDTABLES (-30) /* Name was changed */
+#define PCRE2_ERROR_BADMAGIC (-31)
+#define PCRE2_ERROR_BADMODE (-32)
+#define PCRE2_ERROR_BADOFFSET (-33)
+#define PCRE2_ERROR_BADOPTION (-34)
+#define PCRE2_ERROR_BADREPLACEMENT (-35)
+#define PCRE2_ERROR_BADUTFOFFSET (-36)
+#define PCRE2_ERROR_CALLOUT (-37) /* Never used by PCRE2 itself */
+#define PCRE2_ERROR_DFA_BADRESTART (-38)
+#define PCRE2_ERROR_DFA_RECURSE (-39)
+#define PCRE2_ERROR_DFA_UCOND (-40)
+#define PCRE2_ERROR_DFA_UFUNC (-41)
+#define PCRE2_ERROR_DFA_UITEM (-42)
+#define PCRE2_ERROR_DFA_WSSIZE (-43)
+#define PCRE2_ERROR_INTERNAL (-44)
+#define PCRE2_ERROR_JIT_BADOPTION (-45)
+#define PCRE2_ERROR_JIT_STACKLIMIT (-46)
+#define PCRE2_ERROR_MATCHLIMIT (-47)
+#define PCRE2_ERROR_NOMEMORY (-48)
+#define PCRE2_ERROR_NOSUBSTRING (-49)
+#define PCRE2_ERROR_NOUNIQUESUBSTRING (-50)
+#define PCRE2_ERROR_NULL (-51)
+#define PCRE2_ERROR_RECURSELOOP (-52)
+#define PCRE2_ERROR_RECURSIONLIMIT (-53)
+#define PCRE2_ERROR_UNAVAILABLE (-54)
+#define PCRE2_ERROR_UNSET (-55)
+#define PCRE2_ERROR_BADOFFSETLIMIT (-56)
+#define PCRE2_ERROR_BADREPESCAPE (-57)
+#define PCRE2_ERROR_REPMISSINGBRACE (-58)
+#define PCRE2_ERROR_BADSUBSTITUTION (-59)
+#define PCRE2_ERROR_BADSUBSPATTERN (-60)
+#define PCRE2_ERROR_TOOMANYREPLACE (-61)
+#define PCRE2_ERROR_BADSERIALIZEDDATA (-62)
+
+/* Request types for pcre2_pattern_info() */
+
+#define PCRE2_INFO_ALLOPTIONS 0
+#define PCRE2_INFO_ARGOPTIONS 1
+#define PCRE2_INFO_BACKREFMAX 2
+#define PCRE2_INFO_BSR 3
+#define PCRE2_INFO_CAPTURECOUNT 4
+#define PCRE2_INFO_FIRSTCODEUNIT 5
+#define PCRE2_INFO_FIRSTCODETYPE 6
+#define PCRE2_INFO_FIRSTBITMAP 7
+#define PCRE2_INFO_HASCRORLF 8
+#define PCRE2_INFO_JCHANGED 9
+#define PCRE2_INFO_JITSIZE 10
+#define PCRE2_INFO_LASTCODEUNIT 11
+#define PCRE2_INFO_LASTCODETYPE 12
+#define PCRE2_INFO_MATCHEMPTY 13
+#define PCRE2_INFO_MATCHLIMIT 14
+#define PCRE2_INFO_MAXLOOKBEHIND 15
+#define PCRE2_INFO_MINLENGTH 16
+#define PCRE2_INFO_NAMECOUNT 17
+#define PCRE2_INFO_NAMEENTRYSIZE 18
+#define PCRE2_INFO_NAMETABLE 19
+#define PCRE2_INFO_NEWLINE 20
+#define PCRE2_INFO_RECURSIONLIMIT 21
+#define PCRE2_INFO_SIZE 22
+#define PCRE2_INFO_HASBACKSLASHC 23
+
+/* Request types for pcre2_config(). */
+
+#define PCRE2_CONFIG_BSR 0
+#define PCRE2_CONFIG_JIT 1
+#define PCRE2_CONFIG_JITTARGET 2
+#define PCRE2_CONFIG_LINKSIZE 3
+#define PCRE2_CONFIG_MATCHLIMIT 4
+#define PCRE2_CONFIG_NEWLINE 5
+#define PCRE2_CONFIG_PARENSLIMIT 6
+#define PCRE2_CONFIG_RECURSIONLIMIT 7
+#define PCRE2_CONFIG_STACKRECURSE 8
+#define PCRE2_CONFIG_UNICODE 9
+#define PCRE2_CONFIG_UNICODE_VERSION 10
+#define PCRE2_CONFIG_VERSION 11
+
+/* Types for code units in patterns and subject strings. */
+
+typedef uint8_t PCRE2_UCHAR8;
+typedef uint16_t PCRE2_UCHAR16;
+typedef uint32_t PCRE2_UCHAR32;
+
+typedef const PCRE2_UCHAR8 *PCRE2_SPTR8;
+typedef const PCRE2_UCHAR16 *PCRE2_SPTR16;
+typedef const PCRE2_UCHAR32 *PCRE2_SPTR32;
+
+/* The PCRE2_SIZE type is used for all string lengths and offsets in PCRE2,
+including pattern offsets for errors and subject offsets after a match. We
+define special values to indicate zero-terminated strings and unset offsets in
+the offset vector (ovector). */
+
+#define PCRE2_SIZE size_t
+#define PCRE2_SIZE_MAX SIZE_MAX
+#define PCRE2_ZERO_TERMINATED (~(PCRE2_SIZE)0)
+#define PCRE2_UNSET (~(PCRE2_SIZE)0)
+
+/* Generic types for opaque structures and JIT callback functions. These
+declarations are defined in a macro that is expanded for each width later. */
+
+#define PCRE2_TYPES_LIST \
+struct pcre2_real_general_context; \
+typedef struct pcre2_real_general_context pcre2_general_context; \
+\
+struct pcre2_real_compile_context; \
+typedef struct pcre2_real_compile_context pcre2_compile_context; \
+\
+struct pcre2_real_match_context; \
+typedef struct pcre2_real_match_context pcre2_match_context; \
+\
+struct pcre2_real_code; \
+typedef struct pcre2_real_code pcre2_code; \
+\
+struct pcre2_real_match_data; \
+typedef struct pcre2_real_match_data pcre2_match_data; \
+\
+struct pcre2_real_jit_stack; \
+typedef struct pcre2_real_jit_stack pcre2_jit_stack; \
+\
+typedef pcre2_jit_stack *(*pcre2_jit_callback)(void *);
+
+
+/* The 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. Define the generic version in a macro; the width-specific
+versions are generated from this macro below. */
+
+#define PCRE2_STRUCTURE_LIST \
+typedef struct pcre2_callout_block { \
+ uint32_t version; /* Identifies version of block */ \
+ /* ------------------------ Version 0 ------------------------------- */ \
+ uint32_t callout_number; /* Number compiled into pattern */ \
+ uint32_t capture_top; /* Max current capture */ \
+ uint32_t capture_last; /* Most recently closed capture */ \
+ PCRE2_SIZE *offset_vector; /* The offset vector */ \
+ PCRE2_SPTR mark; /* Pointer to current mark or NULL */ \
+ PCRE2_SPTR subject; /* The subject being matched */ \
+ PCRE2_SIZE subject_length; /* The length of the subject */ \
+ PCRE2_SIZE start_match; /* Offset to start of this match attempt */ \
+ PCRE2_SIZE current_position; /* Where we currently are in the subject */ \
+ PCRE2_SIZE pattern_position; /* Offset to next item in the pattern */ \
+ PCRE2_SIZE next_item_length; /* Length of next item in the pattern */ \
+ /* ------------------- Added for Version 1 -------------------------- */ \
+ PCRE2_SIZE callout_string_offset; /* Offset to string within pattern */ \
+ PCRE2_SIZE callout_string_length; /* Length of string compiled into pattern */ \
+ PCRE2_SPTR callout_string; /* String compiled into pattern */ \
+ /* ------------------------------------------------------------------ */ \
+} pcre2_callout_block; \
+\
+typedef struct pcre2_callout_enumerate_block { \
+ uint32_t version; /* Identifies version of block */ \
+ /* ------------------------ Version 0 ------------------------------- */ \
+ PCRE2_SIZE pattern_position; /* Offset to next item in the pattern */ \
+ PCRE2_SIZE next_item_length; /* Length of next item in the pattern */ \
+ uint32_t callout_number; /* Number compiled into pattern */ \
+ PCRE2_SIZE callout_string_offset; /* Offset to string within pattern */ \
+ PCRE2_SIZE callout_string_length; /* Length of string compiled into pattern */ \
+ PCRE2_SPTR callout_string; /* String compiled into pattern */ \
+ /* ------------------------------------------------------------------ */ \
+} pcre2_callout_enumerate_block;
+
+
+/* List the generic forms of all other functions in macros, which will be
+expanded for each width below. Start with functions that give general
+information. */
+
+#define PCRE2_GENERAL_INFO_FUNCTIONS \
+PCRE2_EXP_DECL int pcre2_config(uint32_t, void *);
+
+
+/* Functions for manipulating contexts. */
+
+#define PCRE2_GENERAL_CONTEXT_FUNCTIONS \
+PCRE2_EXP_DECL \
+ pcre2_general_context *pcre2_general_context_copy(pcre2_general_context *); \
+PCRE2_EXP_DECL \
+ pcre2_general_context *pcre2_general_context_create( \
+ void *(*)(PCRE2_SIZE, void *), \
+ void (*)(void *, void *), void *); \
+PCRE2_EXP_DECL void pcre2_general_context_free(pcre2_general_context *);
+
+#define PCRE2_COMPILE_CONTEXT_FUNCTIONS \
+PCRE2_EXP_DECL \
+ pcre2_compile_context *pcre2_compile_context_copy(pcre2_compile_context *); \
+PCRE2_EXP_DECL \
+ pcre2_compile_context *pcre2_compile_context_create(pcre2_general_context *);\
+PCRE2_EXP_DECL void pcre2_compile_context_free(pcre2_compile_context *); \
+PCRE2_EXP_DECL int pcre2_set_bsr(pcre2_compile_context *, uint32_t); \
+PCRE2_EXP_DECL int pcre2_set_character_tables(pcre2_compile_context *, \
+ const unsigned char *); \
+PCRE2_EXP_DECL int pcre2_set_max_pattern_length(pcre2_compile_context *, \
+ PCRE2_SIZE); \
+PCRE2_EXP_DECL int pcre2_set_newline(pcre2_compile_context *, uint32_t); \
+PCRE2_EXP_DECL int pcre2_set_parens_nest_limit(pcre2_compile_context *, \
+ uint32_t); \
+PCRE2_EXP_DECL int pcre2_set_compile_recursion_guard(\
+ pcre2_compile_context *, int (*)(uint32_t, void *), \
+ void *);
+
+#define PCRE2_MATCH_CONTEXT_FUNCTIONS \
+PCRE2_EXP_DECL \
+ pcre2_match_context *pcre2_match_context_copy(pcre2_match_context *); \
+PCRE2_EXP_DECL \
+ pcre2_match_context *pcre2_match_context_create(pcre2_general_context *); \
+PCRE2_EXP_DECL void pcre2_match_context_free(pcre2_match_context *); \
+PCRE2_EXP_DECL int pcre2_set_callout(pcre2_match_context *, \
+ int (*)(pcre2_callout_block *, void *), void *); \
+PCRE2_EXP_DECL int pcre2_set_match_limit(pcre2_match_context *, \
+ uint32_t); \
+PCRE2_EXP_DECL int pcre2_set_offset_limit(pcre2_match_context *, \
+ PCRE2_SIZE); \
+PCRE2_EXP_DECL int pcre2_set_recursion_limit(pcre2_match_context *, \
+ uint32_t); \
+PCRE2_EXP_DECL int pcre2_set_recursion_memory_management( \
+ pcre2_match_context *, void *(*)(PCRE2_SIZE, void *), \
+ void (*)(void *, void *), void *);
+
+
+/* Functions concerned with compiling a pattern to PCRE internal code. */
+
+#define PCRE2_COMPILE_FUNCTIONS \
+PCRE2_EXP_DECL \
+ pcre2_code *pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, \
+ int *, PCRE2_SIZE *, pcre2_compile_context *); \
+PCRE2_EXP_DECL void pcre2_code_free(pcre2_code *); \
+PCRE2_EXP_DECL \
+ pcre2_code *pcre2_code_copy(const pcre2_code *);
+
+
+/* Functions that give information about a compiled pattern. */
+
+#define PCRE2_PATTERN_INFO_FUNCTIONS \
+PCRE2_EXP_DECL int pcre2_pattern_info(const pcre2_code *, uint32_t, \
+ void *); \
+PCRE2_EXP_DECL int pcre2_callout_enumerate(const pcre2_code *, \
+ int (*)(pcre2_callout_enumerate_block *, void *), \
+ void *);
+
+
+/* Functions for running a match and inspecting the result. */
+
+#define PCRE2_MATCH_FUNCTIONS \
+PCRE2_EXP_DECL \
+ pcre2_match_data *pcre2_match_data_create(uint32_t, \
+ pcre2_general_context *); \
+PCRE2_EXP_DECL \
+ pcre2_match_data *pcre2_match_data_create_from_pattern(\
+ const pcre2_code *, \
+ pcre2_general_context *); \
+PCRE2_EXP_DECL int pcre2_dfa_match(const pcre2_code *, PCRE2_SPTR, \
+ PCRE2_SIZE, PCRE2_SIZE, uint32_t, \
+ pcre2_match_data *, pcre2_match_context *, int *, \
+ PCRE2_SIZE); \
+PCRE2_EXP_DECL int pcre2_match(const pcre2_code *, \
+ PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, uint32_t, \
+ pcre2_match_data *, pcre2_match_context *); \
+PCRE2_EXP_DECL void pcre2_match_data_free(pcre2_match_data *); \
+PCRE2_EXP_DECL PCRE2_SPTR pcre2_get_mark(pcre2_match_data *); \
+PCRE2_EXP_DECL uint32_t pcre2_get_ovector_count(pcre2_match_data *); \
+PCRE2_EXP_DECL PCRE2_SIZE *pcre2_get_ovector_pointer(pcre2_match_data *); \
+PCRE2_EXP_DECL PCRE2_SIZE pcre2_get_startchar(pcre2_match_data *);
+
+
+/* Convenience functions for handling matched substrings. */
+
+#define PCRE2_SUBSTRING_FUNCTIONS \
+PCRE2_EXP_DECL int pcre2_substring_copy_byname(pcre2_match_data *, \
+ PCRE2_SPTR, PCRE2_UCHAR *, PCRE2_SIZE *); \
+PCRE2_EXP_DECL int pcre2_substring_copy_bynumber(pcre2_match_data *, \
+ uint32_t, PCRE2_UCHAR *, PCRE2_SIZE *); \
+PCRE2_EXP_DECL void pcre2_substring_free(PCRE2_UCHAR *); \
+PCRE2_EXP_DECL int pcre2_substring_get_byname(pcre2_match_data *, \
+ PCRE2_SPTR, PCRE2_UCHAR **, PCRE2_SIZE *); \
+PCRE2_EXP_DECL int pcre2_substring_get_bynumber(pcre2_match_data *, \
+ uint32_t, PCRE2_UCHAR **, PCRE2_SIZE *); \
+PCRE2_EXP_DECL int pcre2_substring_length_byname(pcre2_match_data *, \
+ PCRE2_SPTR, PCRE2_SIZE *); \
+PCRE2_EXP_DECL int pcre2_substring_length_bynumber(pcre2_match_data *, \
+ uint32_t, PCRE2_SIZE *); \
+PCRE2_EXP_DECL int pcre2_substring_nametable_scan(const pcre2_code *, \
+ PCRE2_SPTR, PCRE2_SPTR *, PCRE2_SPTR *); \
+PCRE2_EXP_DECL int pcre2_substring_number_from_name(\
+ const pcre2_code *, PCRE2_SPTR); \
+PCRE2_EXP_DECL void pcre2_substring_list_free(PCRE2_SPTR *); \
+PCRE2_EXP_DECL int pcre2_substring_list_get(pcre2_match_data *, \
+ PCRE2_UCHAR ***, PCRE2_SIZE **);
+
+/* Functions for serializing / deserializing compiled patterns. */
+
+#define PCRE2_SERIALIZE_FUNCTIONS \
+PCRE2_EXP_DECL int32_t pcre2_serialize_encode(const pcre2_code **, \
+ int32_t, uint8_t **, PCRE2_SIZE *, \
+ pcre2_general_context *); \
+PCRE2_EXP_DECL int32_t pcre2_serialize_decode(pcre2_code **, int32_t, \
+ const uint8_t *, pcre2_general_context *); \
+PCRE2_EXP_DECL int32_t pcre2_serialize_get_number_of_codes(const uint8_t *); \
+PCRE2_EXP_DECL void pcre2_serialize_free(uint8_t *);
+
+
+/* Convenience function for match + substitute. */
+
+#define PCRE2_SUBSTITUTE_FUNCTION \
+PCRE2_EXP_DECL int pcre2_substitute(const pcre2_code *, \
+ PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, uint32_t, \
+ pcre2_match_data *, pcre2_match_context *, \
+ PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *, \
+ PCRE2_SIZE *);
+
+
+/* Functions for JIT processing */
+
+#define PCRE2_JIT_FUNCTIONS \
+PCRE2_EXP_DECL int pcre2_jit_compile(pcre2_code *, uint32_t); \
+PCRE2_EXP_DECL int pcre2_jit_match(const pcre2_code *, \
+ PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, uint32_t, \
+ pcre2_match_data *, pcre2_match_context *); \
+PCRE2_EXP_DECL void pcre2_jit_free_unused_memory(pcre2_general_context *); \
+PCRE2_EXP_DECL \
+ pcre2_jit_stack *pcre2_jit_stack_create(PCRE2_SIZE, PCRE2_SIZE, \
+ pcre2_general_context *); \
+PCRE2_EXP_DECL void pcre2_jit_stack_assign(pcre2_match_context *, \
+ pcre2_jit_callback, void *); \
+PCRE2_EXP_DECL void pcre2_jit_stack_free(pcre2_jit_stack *);
+
+
+/* Other miscellaneous functions. */
+
+#define PCRE2_OTHER_FUNCTIONS \
+PCRE2_EXP_DECL int pcre2_get_error_message(int, PCRE2_UCHAR *, PCRE2_SIZE); \
+PCRE2_EXP_DECL \
+ const uint8_t *pcre2_maketables(pcre2_general_context *); \
+
+
+/* Define macros that generate width-specific names from generic versions. The
+three-level macro scheme is necessary to get the macros expanded when we want
+them to be. First we get the width from PCRE2_LOCAL_WIDTH, which is used for
+generating three versions of everything below. After that, PCRE2_SUFFIX will be
+re-defined to use PCRE2_CODE_UNIT_WIDTH, for use when macros such as
+pcre2_compile are called by application code. */
+
+#define PCRE2_JOIN(a,b) a ## b
+#define PCRE2_GLUE(a,b) PCRE2_JOIN(a,b)
+#define PCRE2_SUFFIX(a) PCRE2_GLUE(a,PCRE2_LOCAL_WIDTH)
+
+
+/* Data types */
+
+#define PCRE2_UCHAR PCRE2_SUFFIX(PCRE2_UCHAR)
+#define PCRE2_SPTR PCRE2_SUFFIX(PCRE2_SPTR)
+
+#define pcre2_code PCRE2_SUFFIX(pcre2_code_)
+#define pcre2_jit_callback PCRE2_SUFFIX(pcre2_jit_callback_)
+#define pcre2_jit_stack PCRE2_SUFFIX(pcre2_jit_stack_)
+
+#define pcre2_real_code PCRE2_SUFFIX(pcre2_real_code_)
+#define pcre2_real_general_context PCRE2_SUFFIX(pcre2_real_general_context_)
+#define pcre2_real_compile_context PCRE2_SUFFIX(pcre2_real_compile_context_)
+#define pcre2_real_match_context PCRE2_SUFFIX(pcre2_real_match_context_)
+#define pcre2_real_jit_stack PCRE2_SUFFIX(pcre2_real_jit_stack_)
+#define pcre2_real_match_data PCRE2_SUFFIX(pcre2_real_match_data_)
+
+
+/* Data blocks */
+
+#define pcre2_callout_block PCRE2_SUFFIX(pcre2_callout_block_)
+#define pcre2_callout_enumerate_block PCRE2_SUFFIX(pcre2_callout_enumerate_block_)
+#define pcre2_general_context PCRE2_SUFFIX(pcre2_general_context_)
+#define pcre2_compile_context PCRE2_SUFFIX(pcre2_compile_context_)
+#define pcre2_match_context PCRE2_SUFFIX(pcre2_match_context_)
+#define pcre2_match_data PCRE2_SUFFIX(pcre2_match_data_)
+
+
+/* Functions: the complete list in alphabetical order */
+
+#define pcre2_callout_enumerate PCRE2_SUFFIX(pcre2_callout_enumerate_)
+#define pcre2_code_copy PCRE2_SUFFIX(pcre2_code_copy_)
+#define pcre2_code_free PCRE2_SUFFIX(pcre2_code_free_)
+#define pcre2_compile PCRE2_SUFFIX(pcre2_compile_)
+#define pcre2_compile_context_copy PCRE2_SUFFIX(pcre2_compile_context_copy_)
+#define pcre2_compile_context_create PCRE2_SUFFIX(pcre2_compile_context_create_)
+#define pcre2_compile_context_free PCRE2_SUFFIX(pcre2_compile_context_free_)
+#define pcre2_config PCRE2_SUFFIX(pcre2_config_)
+#define pcre2_dfa_match PCRE2_SUFFIX(pcre2_dfa_match_)
+#define pcre2_general_context_copy PCRE2_SUFFIX(pcre2_general_context_copy_)
+#define pcre2_general_context_create PCRE2_SUFFIX(pcre2_general_context_create_)
+#define pcre2_general_context_free PCRE2_SUFFIX(pcre2_general_context_free_)
+#define pcre2_get_error_message PCRE2_SUFFIX(pcre2_get_error_message_)
+#define pcre2_get_mark PCRE2_SUFFIX(pcre2_get_mark_)
+#define pcre2_get_ovector_pointer PCRE2_SUFFIX(pcre2_get_ovector_pointer_)
+#define pcre2_get_ovector_count PCRE2_SUFFIX(pcre2_get_ovector_count_)
+#define pcre2_get_startchar PCRE2_SUFFIX(pcre2_get_startchar_)
+#define pcre2_jit_compile PCRE2_SUFFIX(pcre2_jit_compile_)
+#define pcre2_jit_match PCRE2_SUFFIX(pcre2_jit_match_)
+#define pcre2_jit_free_unused_memory PCRE2_SUFFIX(pcre2_jit_free_unused_memory_)
+#define pcre2_jit_stack_assign PCRE2_SUFFIX(pcre2_jit_stack_assign_)
+#define pcre2_jit_stack_create PCRE2_SUFFIX(pcre2_jit_stack_create_)
+#define pcre2_jit_stack_free PCRE2_SUFFIX(pcre2_jit_stack_free_)
+#define pcre2_maketables PCRE2_SUFFIX(pcre2_maketables_)
+#define pcre2_match PCRE2_SUFFIX(pcre2_match_)
+#define pcre2_match_context_copy PCRE2_SUFFIX(pcre2_match_context_copy_)
+#define pcre2_match_context_create PCRE2_SUFFIX(pcre2_match_context_create_)
+#define pcre2_match_context_free PCRE2_SUFFIX(pcre2_match_context_free_)
+#define pcre2_match_data_create PCRE2_SUFFIX(pcre2_match_data_create_)
+#define pcre2_match_data_create_from_pattern PCRE2_SUFFIX(pcre2_match_data_create_from_pattern_)
+#define pcre2_match_data_free PCRE2_SUFFIX(pcre2_match_data_free_)
+#define pcre2_pattern_info PCRE2_SUFFIX(pcre2_pattern_info_)
+#define pcre2_serialize_decode PCRE2_SUFFIX(pcre2_serialize_decode_)
+#define pcre2_serialize_encode PCRE2_SUFFIX(pcre2_serialize_encode_)
+#define pcre2_serialize_free PCRE2_SUFFIX(pcre2_serialize_free_)
+#define pcre2_serialize_get_number_of_codes PCRE2_SUFFIX(pcre2_serialize_get_number_of_codes_)
+#define pcre2_set_bsr PCRE2_SUFFIX(pcre2_set_bsr_)
+#define pcre2_set_callout PCRE2_SUFFIX(pcre2_set_callout_)
+#define pcre2_set_character_tables PCRE2_SUFFIX(pcre2_set_character_tables_)
+#define pcre2_set_compile_recursion_guard PCRE2_SUFFIX(pcre2_set_compile_recursion_guard_)
+#define pcre2_set_match_limit PCRE2_SUFFIX(pcre2_set_match_limit_)
+#define pcre2_set_max_pattern_length PCRE2_SUFFIX(pcre2_set_max_pattern_length_)
+#define pcre2_set_newline PCRE2_SUFFIX(pcre2_set_newline_)
+#define pcre2_set_parens_nest_limit PCRE2_SUFFIX(pcre2_set_parens_nest_limit_)
+#define pcre2_set_offset_limit PCRE2_SUFFIX(pcre2_set_offset_limit_)
+#define pcre2_set_recursion_limit PCRE2_SUFFIX(pcre2_set_recursion_limit_)
+#define pcre2_set_recursion_memory_management PCRE2_SUFFIX(pcre2_set_recursion_memory_management_)
+#define pcre2_substitute PCRE2_SUFFIX(pcre2_substitute_)
+#define pcre2_substring_copy_byname PCRE2_SUFFIX(pcre2_substring_copy_byname_)
+#define pcre2_substring_copy_bynumber PCRE2_SUFFIX(pcre2_substring_copy_bynumber_)
+#define pcre2_substring_free PCRE2_SUFFIX(pcre2_substring_free_)
+#define pcre2_substring_get_byname PCRE2_SUFFIX(pcre2_substring_get_byname_)
+#define pcre2_substring_get_bynumber PCRE2_SUFFIX(pcre2_substring_get_bynumber_)
+#define pcre2_substring_length_byname PCRE2_SUFFIX(pcre2_substring_length_byname_)
+#define pcre2_substring_length_bynumber PCRE2_SUFFIX(pcre2_substring_length_bynumber_)
+#define pcre2_substring_list_get PCRE2_SUFFIX(pcre2_substring_list_get_)
+#define pcre2_substring_list_free PCRE2_SUFFIX(pcre2_substring_list_free_)
+#define pcre2_substring_nametable_scan PCRE2_SUFFIX(pcre2_substring_nametable_scan_)
+#define pcre2_substring_number_from_name PCRE2_SUFFIX(pcre2_substring_number_from_name_)
+
+
+/* Now generate all three sets of width-specific structures and function
+prototypes. */
+
+#define PCRE2_TYPES_STRUCTURES_AND_FUNCTIONS \
+PCRE2_TYPES_LIST \
+PCRE2_STRUCTURE_LIST \
+PCRE2_GENERAL_INFO_FUNCTIONS \
+PCRE2_GENERAL_CONTEXT_FUNCTIONS \
+PCRE2_COMPILE_CONTEXT_FUNCTIONS \
+PCRE2_MATCH_CONTEXT_FUNCTIONS \
+PCRE2_COMPILE_FUNCTIONS \
+PCRE2_PATTERN_INFO_FUNCTIONS \
+PCRE2_MATCH_FUNCTIONS \
+PCRE2_SUBSTRING_FUNCTIONS \
+PCRE2_SERIALIZE_FUNCTIONS \
+PCRE2_SUBSTITUTE_FUNCTION \
+PCRE2_JIT_FUNCTIONS \
+PCRE2_OTHER_FUNCTIONS
+
+#define PCRE2_LOCAL_WIDTH 8
+PCRE2_TYPES_STRUCTURES_AND_FUNCTIONS
+#undef PCRE2_LOCAL_WIDTH
+
+#define PCRE2_LOCAL_WIDTH 16
+PCRE2_TYPES_STRUCTURES_AND_FUNCTIONS
+#undef PCRE2_LOCAL_WIDTH
+
+#define PCRE2_LOCAL_WIDTH 32
+PCRE2_TYPES_STRUCTURES_AND_FUNCTIONS
+#undef PCRE2_LOCAL_WIDTH
+
+/* Undefine the list macros; they are no longer needed. */
+
+#undef PCRE2_TYPES_LIST
+#undef PCRE2_STRUCTURE_LIST
+#undef PCRE2_GENERAL_INFO_FUNCTIONS
+#undef PCRE2_GENERAL_CONTEXT_FUNCTIONS
+#undef PCRE2_COMPILE_CONTEXT_FUNCTIONS
+#undef PCRE2_MATCH_CONTEXT_FUNCTIONS
+#undef PCRE2_COMPILE_FUNCTIONS
+#undef PCRE2_PATTERN_INFO_FUNCTIONS
+#undef PCRE2_MATCH_FUNCTIONS
+#undef PCRE2_SUBSTRING_FUNCTIONS
+#undef PCRE2_SERIALIZE_FUNCTIONS
+#undef PCRE2_SUBSTITUTE_FUNCTION
+#undef PCRE2_JIT_FUNCTIONS
+#undef PCRE2_OTHER_FUNCTIONS
+#undef PCRE2_TYPES_STRUCTURES_AND_FUNCTIONS
+
+/* PCRE2_CODE_UNIT_WIDTH must be defined. If it is 8, 16, or 32, redefine
+PCRE2_SUFFIX to use it. If it is 0, undefine the other macros and make
+PCRE2_SUFFIX a no-op. Otherwise, generate an error. */
+
+#undef PCRE2_SUFFIX
+#ifndef PCRE2_CODE_UNIT_WIDTH
+#error PCRE2_CODE_UNIT_WIDTH must be defined before including pcre2.h.
+#error Use 8, 16, or 32; or 0 for a multi-width application.
+#else /* PCRE2_CODE_UNIT_WIDTH is defined */
+#if PCRE2_CODE_UNIT_WIDTH == 8 || \
+ PCRE2_CODE_UNIT_WIDTH == 16 || \
+ PCRE2_CODE_UNIT_WIDTH == 32
+#define PCRE2_SUFFIX(a) PCRE2_GLUE(a, PCRE2_CODE_UNIT_WIDTH)
+#elif PCRE2_CODE_UNIT_WIDTH == 0
+#undef PCRE2_JOIN
+#undef PCRE2_GLUE
+#define PCRE2_SUFFIX(a) a
+#else
+#error PCRE2_CODE_UNIT_WIDTH must be 0, 8, 16, or 32.
+#endif
+#endif /* PCRE2_CODE_UNIT_WIDTH is defined */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* End of pcre2.h */
diff --git a/src/3rdparty/pcre2/src/pcre2_auto_possess.c b/src/3rdparty/pcre2/src/pcre2_auto_possess.c
new file mode 100644
index 0000000000..8d0fa896ec
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_auto_possess.c
@@ -0,0 +1,1289 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+/* This module contains functions that scan a compiled pattern and change
+repeats into possessive repeats where possible. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "pcre2_internal.h"
+
+
+/*************************************************
+* Tables for auto-possessification *
+*************************************************/
+
+/* This table is used to check whether auto-possessification is possible
+between adjacent character-type opcodes. The left-hand (repeated) opcode is
+used to select the row, and the right-hand opcode is use to select the column.
+A value of 1 means that auto-possessification is OK. For example, the second
+value in the first row means that \D+\d can be turned into \D++\d.
+
+The Unicode property types (\P and \p) have to be present to fill out the table
+because of what their opcode values are, but the table values should always be
+zero because property types are handled separately in the code. The last four
+columns apply to items that cannot be repeated, so there is no need to have
+rows for them. Note that OP_DIGIT etc. are generated only when PCRE_UCP is
+*not* set. When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */
+
+#define APTROWS (LAST_AUTOTAB_LEFT_OP - FIRST_AUTOTAB_OP + 1)
+#define APTCOLS (LAST_AUTOTAB_RIGHT_OP - FIRST_AUTOTAB_OP + 1)
+
+static const uint8_t autoposstab[APTROWS][APTCOLS] = {
+/* \D \d \S \s \W \w . .+ \C \P \p \R \H \h \V \v \X \Z \z $ $M */
+ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \D */
+ { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \d */
+ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \S */
+ { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \s */
+ { 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \W */
+ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \w */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* . */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* .+ */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \C */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* \P */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* \p */
+ { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, /* \R */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, /* \H */
+ { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0 }, /* \h */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0 }, /* \V */
+ { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0 }, /* \v */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } /* \X */
+};
+
+#ifdef SUPPORT_UNICODE
+/* This table is used to check whether auto-possessification is possible
+between adjacent Unicode property opcodes (OP_PROP and OP_NOTPROP). The
+left-hand (repeated) opcode is used to select the row, and the right-hand
+opcode is used to select the column. The values are as follows:
+
+ 0 Always return FALSE (never auto-possessify)
+ 1 Character groups are distinct (possessify if both are OP_PROP)
+ 2 Check character categories in the same group (general or particular)
+ 3 TRUE if the two opcodes are not the same (PROP vs NOTPROP)
+
+ 4 Check left general category vs right particular category
+ 5 Check right general category vs left particular category
+
+ 6 Left alphanum vs right general category
+ 7 Left space vs right general category
+ 8 Left word vs right general category
+
+ 9 Right alphanum vs left general category
+ 10 Right space vs left general category
+ 11 Right word vs left general category
+
+ 12 Left alphanum vs right particular category
+ 13 Left space vs right particular category
+ 14 Left word vs right particular category
+
+ 15 Right alphanum vs left particular category
+ 16 Right space vs left particular category
+ 17 Right word vs left particular category
+*/
+
+static const uint8_t propposstab[PT_TABSIZE][PT_TABSIZE] = {
+/* ANY LAMP GC PC SC ALNUM SPACE PXSPACE WORD CLIST UCNC */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_ANY */
+ { 0, 3, 0, 0, 0, 3, 1, 1, 0, 0, 0 }, /* PT_LAMP */
+ { 0, 0, 2, 4, 0, 9, 10, 10, 11, 0, 0 }, /* PT_GC */
+ { 0, 0, 5, 2, 0, 15, 16, 16, 17, 0, 0 }, /* PT_PC */
+ { 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 }, /* PT_SC */
+ { 0, 3, 6, 12, 0, 3, 1, 1, 0, 0, 0 }, /* PT_ALNUM */
+ { 0, 1, 7, 13, 0, 1, 3, 3, 1, 0, 0 }, /* PT_SPACE */
+ { 0, 1, 7, 13, 0, 1, 3, 3, 1, 0, 0 }, /* PT_PXSPACE */
+ { 0, 0, 8, 14, 0, 0, 1, 1, 3, 0, 0 }, /* PT_WORD */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 } /* PT_UCNC */
+};
+
+/* This table is used to check whether auto-possessification is possible
+between adjacent Unicode property opcodes (OP_PROP and OP_NOTPROP) when one
+specifies a general category and the other specifies a particular category. The
+row is selected by the general category and the column by the particular
+category. The value is 1 if the particular category is not part of the general
+category. */
+
+static const uint8_t catposstab[7][30] = {
+/* Cc Cf Cn Co Cs Ll Lm Lo Lt Lu Mc Me Mn Nd Nl No Pc Pd Pe Pf Pi Po Ps Sc Sk Sm So Zl Zp Zs */
+ { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* C */
+ { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* L */
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* M */
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* N */
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 }, /* P */
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1 }, /* S */
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 } /* Z */
+};
+
+/* This table is used when checking ALNUM, (PX)SPACE, SPACE, and WORD against
+a general or particular category. The properties in each row are those
+that apply to the character set in question. Duplication means that a little
+unnecessary work is done when checking, but this keeps things much simpler
+because they can all use the same code. For more details see the comment where
+this table is used.
+
+Note: SPACE and PXSPACE used to be different because Perl excluded VT from
+"space", but from Perl 5.18 it's included, so both categories are treated the
+same here. */
+
+static const uint8_t posspropstab[3][4] = {
+ { ucp_L, ucp_N, ucp_N, ucp_Nl }, /* ALNUM, 3rd and 4th values redundant */
+ { ucp_Z, ucp_Z, ucp_C, ucp_Cc }, /* SPACE and PXSPACE, 2nd value redundant */
+ { ucp_L, ucp_N, ucp_P, ucp_Po } /* WORD */
+};
+#endif /* SUPPORT_UNICODE */
+
+
+
+#ifdef SUPPORT_UNICODE
+/*************************************************
+* Check a character and a property *
+*************************************************/
+
+/* This function is called by compare_opcodes() when a property item is
+adjacent to a fixed character.
+
+Arguments:
+ c the character
+ ptype the property type
+ pdata the data for the type
+ negated TRUE if it's a negated property (\P or \p{^)
+
+Returns: TRUE if auto-possessifying is OK
+*/
+
+static BOOL
+check_char_prop(uint32_t c, unsigned int ptype, unsigned int pdata,
+ BOOL negated)
+{
+const uint32_t *p;
+const ucd_record *prop = GET_UCD(c);
+
+switch(ptype)
+ {
+ case PT_LAMP:
+ return (prop->chartype == ucp_Lu ||
+ prop->chartype == ucp_Ll ||
+ prop->chartype == ucp_Lt) == negated;
+
+ case PT_GC:
+ return (pdata == PRIV(ucp_gentype)[prop->chartype]) == negated;
+
+ case PT_PC:
+ return (pdata == prop->chartype) == negated;
+
+ case PT_SC:
+ return (pdata == prop->script) == negated;
+
+ /* These are specials */
+
+ case PT_ALNUM:
+ return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N) == negated;
+
+ /* Perl space used to exclude VT, but from Perl 5.18 it is included, which
+ means that Perl space and POSIX space are now identical. PCRE was changed
+ at release 8.34. */
+
+ case PT_SPACE: /* Perl space */
+ case PT_PXSPACE: /* POSIX space */
+ switch(c)
+ {
+ HSPACE_CASES:
+ VSPACE_CASES:
+ return negated;
+
+ default:
+ return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated;
+ }
+ break; /* Control never reaches here */
+
+ case PT_WORD:
+ return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
+ c == CHAR_UNDERSCORE) == negated;
+
+ case PT_CLIST:
+ p = PRIV(ucd_caseless_sets) + prop->caseset;
+ for (;;)
+ {
+ if (c < *p) return !negated;
+ if (c == *p++) return negated;
+ }
+ break; /* Control never reaches here */
+ }
+
+return FALSE;
+}
+#endif /* SUPPORT_UNICODE */
+
+
+
+/*************************************************
+* Base opcode of repeated opcodes *
+*************************************************/
+
+/* Returns the base opcode for repeated single character type opcodes. If the
+opcode is not a repeated character type, it returns with the original value.
+
+Arguments: c opcode
+Returns: base opcode for the type
+*/
+
+static PCRE2_UCHAR
+get_repeat_base(PCRE2_UCHAR c)
+{
+return (c > OP_TYPEPOSUPTO)? c :
+ (c >= OP_TYPESTAR)? OP_TYPESTAR :
+ (c >= OP_NOTSTARI)? OP_NOTSTARI :
+ (c >= OP_NOTSTAR)? OP_NOTSTAR :
+ (c >= OP_STARI)? OP_STARI :
+ OP_STAR;
+}
+
+
+/*************************************************
+* Fill the character property list *
+*************************************************/
+
+/* Checks whether the code points to an opcode that can take part in auto-
+possessification, and if so, fills a list with its properties.
+
+Arguments:
+ code points to start of expression
+ utf TRUE if in UTF mode
+ fcc points to the case-flipping table
+ list points to output list
+ list[0] will be filled with the opcode
+ list[1] will be non-zero if this opcode
+ can match an empty character string
+ list[2..7] depends on the opcode
+
+Returns: points to the start of the next opcode if *code is accepted
+ NULL if *code is not accepted
+*/
+
+static PCRE2_SPTR
+get_chr_property_list(PCRE2_SPTR code, BOOL utf, const uint8_t *fcc,
+ uint32_t *list)
+{
+PCRE2_UCHAR c = *code;
+PCRE2_UCHAR base;
+PCRE2_SPTR end;
+uint32_t chr;
+
+#ifdef SUPPORT_UNICODE
+uint32_t *clist_dest;
+const uint32_t *clist_src;
+#else
+(void)utf; /* Suppress "unused parameter" compiler warning */
+#endif
+
+list[0] = c;
+list[1] = FALSE;
+code++;
+
+if (c >= OP_STAR && c <= OP_TYPEPOSUPTO)
+ {
+ base = get_repeat_base(c);
+ c -= (base - OP_STAR);
+
+ if (c == OP_UPTO || c == OP_MINUPTO || c == OP_EXACT || c == OP_POSUPTO)
+ code += IMM2_SIZE;
+
+ list[1] = (c != OP_PLUS && c != OP_MINPLUS && c != OP_EXACT &&
+ c != OP_POSPLUS);
+
+ switch(base)
+ {
+ case OP_STAR:
+ list[0] = OP_CHAR;
+ break;
+
+ case OP_STARI:
+ list[0] = OP_CHARI;
+ break;
+
+ case OP_NOTSTAR:
+ list[0] = OP_NOT;
+ break;
+
+ case OP_NOTSTARI:
+ list[0] = OP_NOTI;
+ break;
+
+ case OP_TYPESTAR:
+ list[0] = *code;
+ code++;
+ break;
+ }
+ c = list[0];
+ }
+
+switch(c)
+ {
+ case OP_NOT_DIGIT:
+ case OP_DIGIT:
+ case OP_NOT_WHITESPACE:
+ case OP_WHITESPACE:
+ case OP_NOT_WORDCHAR:
+ case OP_WORDCHAR:
+ case OP_ANY:
+ case OP_ALLANY:
+ case OP_ANYNL:
+ case OP_NOT_HSPACE:
+ case OP_HSPACE:
+ case OP_NOT_VSPACE:
+ case OP_VSPACE:
+ case OP_EXTUNI:
+ case OP_EODN:
+ case OP_EOD:
+ case OP_DOLL:
+ case OP_DOLLM:
+ return code;
+
+ case OP_CHAR:
+ case OP_NOT:
+ GETCHARINCTEST(chr, code);
+ list[2] = chr;
+ list[3] = NOTACHAR;
+ return code;
+
+ case OP_CHARI:
+ case OP_NOTI:
+ list[0] = (c == OP_CHARI) ? OP_CHAR : OP_NOT;
+ GETCHARINCTEST(chr, code);
+ list[2] = chr;
+
+#ifdef SUPPORT_UNICODE
+ if (chr < 128 || (chr < 256 && !utf))
+ list[3] = fcc[chr];
+ else
+ list[3] = UCD_OTHERCASE(chr);
+#elif defined SUPPORT_WIDE_CHARS
+ list[3] = (chr < 256) ? fcc[chr] : chr;
+#else
+ list[3] = fcc[chr];
+#endif
+
+ /* The othercase might be the same value. */
+
+ if (chr == list[3])
+ list[3] = NOTACHAR;
+ else
+ list[4] = NOTACHAR;
+ return code;
+
+#ifdef SUPPORT_UNICODE
+ case OP_PROP:
+ case OP_NOTPROP:
+ if (code[0] != PT_CLIST)
+ {
+ list[2] = code[0];
+ list[3] = code[1];
+ return code + 2;
+ }
+
+ /* Convert only if we have enough space. */
+
+ clist_src = PRIV(ucd_caseless_sets) + code[1];
+ clist_dest = list + 2;
+ code += 2;
+
+ do {
+ if (clist_dest >= list + 8)
+ {
+ /* Early return if there is not enough space. This should never
+ happen, since all clists are shorter than 5 character now. */
+ list[2] = code[0];
+ list[3] = code[1];
+ return code;
+ }
+ *clist_dest++ = *clist_src;
+ }
+ while(*clist_src++ != NOTACHAR);
+
+ /* All characters are stored. The terminating NOTACHAR is copied from the
+ clist itself. */
+
+ list[0] = (c == OP_PROP) ? OP_CHAR : OP_NOT;
+ return code;
+#endif
+
+ case OP_NCLASS:
+ case OP_CLASS:
+#ifdef SUPPORT_WIDE_CHARS
+ case OP_XCLASS:
+ if (c == OP_XCLASS)
+ end = code + GET(code, 0) - 1;
+ else
+#endif
+ end = code + 32 / sizeof(PCRE2_UCHAR);
+
+ switch(*end)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRPOSSTAR:
+ case OP_CRPOSQUERY:
+ list[1] = TRUE;
+ end++;
+ break;
+
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRPOSPLUS:
+ end++;
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSRANGE:
+ list[1] = (GET2(end, 1) == 0);
+ end += 1 + 2 * IMM2_SIZE;
+ break;
+ }
+ list[2] = (uint32_t)(end - code);
+ return end;
+ }
+return NULL; /* Opcode not accepted */
+}
+
+
+
+/*************************************************
+* Scan further character sets for match *
+*************************************************/
+
+/* Checks whether the base and the current opcode have a common character, in
+which case the base cannot be possessified.
+
+Arguments:
+ code points to the byte code
+ utf TRUE in UTF mode
+ cb compile data block
+ base_list the data list of the base opcode
+ base_end the end of the data list
+ rec_limit points to recursion depth counter
+
+Returns: TRUE if the auto-possessification is possible
+*/
+
+static BOOL
+compare_opcodes(PCRE2_SPTR code, BOOL utf, const compile_block *cb,
+ const uint32_t *base_list, PCRE2_SPTR base_end, int *rec_limit)
+{
+PCRE2_UCHAR c;
+uint32_t list[8];
+const uint32_t *chr_ptr;
+const uint32_t *ochr_ptr;
+const uint32_t *list_ptr;
+PCRE2_SPTR next_code;
+#ifdef SUPPORT_WIDE_CHARS
+PCRE2_SPTR xclass_flags;
+#endif
+const uint8_t *class_bitset;
+const uint8_t *set1, *set2, *set_end;
+uint32_t chr;
+BOOL accepted, invert_bits;
+BOOL entered_a_group = FALSE;
+
+if (--(*rec_limit) <= 0) return FALSE; /* Recursion has gone too deep */
+
+/* Note: the base_list[1] contains whether the current opcode has a greedy
+(represented by a non-zero value) quantifier. This is a different from
+other character type lists, which store here that the character iterator
+matches to an empty string (also represented by a non-zero value). */
+
+for(;;)
+ {
+ /* All operations move the code pointer forward.
+ Therefore infinite recursions are not possible. */
+
+ c = *code;
+
+ /* Skip over callouts */
+
+ if (c == OP_CALLOUT)
+ {
+ code += PRIV(OP_lengths)[c];
+ continue;
+ }
+
+ if (c == OP_CALLOUT_STR)
+ {
+ code += GET(code, 1 + 2*LINK_SIZE);
+ continue;
+ }
+
+ if (c == OP_ALT)
+ {
+ do code += GET(code, 1); while (*code == OP_ALT);
+ c = *code;
+ }
+
+ switch(c)
+ {
+ case OP_END:
+ case OP_KETRPOS:
+ /* TRUE only in greedy case. The non-greedy case could be replaced by
+ an OP_EXACT, but it is probably not worth it. (And note that OP_EXACT
+ uses more memory, which we cannot get at this stage.) */
+
+ return base_list[1] != 0;
+
+ case OP_KET:
+ /* If the bracket is capturing, and referenced by an OP_RECURSE, or
+ it is an atomic sub-pattern (assert, once, etc.) the non-greedy case
+ cannot be converted to a possessive form. */
+
+ if (base_list[1] == 0) return FALSE;
+
+ switch(*(code - GET(code, 1)))
+ {
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ /* Atomic sub-patterns and assertions can always auto-possessify their
+ last iterator. However, if the group was entered as a result of checking
+ a previous iterator, this is not possible. */
+
+ return !entered_a_group;
+ }
+
+ code += PRIV(OP_lengths)[c];
+ continue;
+
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_BRA:
+ case OP_CBRA:
+ next_code = code + GET(code, 1);
+ code += PRIV(OP_lengths)[c];
+
+ while (*next_code == OP_ALT)
+ {
+ if (!compare_opcodes(code, utf, cb, base_list, base_end, rec_limit))
+ return FALSE;
+ code = next_code + 1 + LINK_SIZE;
+ next_code += GET(next_code, 1);
+ }
+
+ entered_a_group = TRUE;
+ continue;
+
+ case OP_BRAZERO:
+ case OP_BRAMINZERO:
+
+ next_code = code + 1;
+ if (*next_code != OP_BRA && *next_code != OP_CBRA
+ && *next_code != OP_ONCE && *next_code != OP_ONCE_NC) return FALSE;
+
+ do next_code += GET(next_code, 1); while (*next_code == OP_ALT);
+
+ /* The bracket content will be checked by the OP_BRA/OP_CBRA case above. */
+
+ next_code += 1 + LINK_SIZE;
+ if (!compare_opcodes(next_code, utf, cb, base_list, base_end, rec_limit))
+ return FALSE;
+
+ code += PRIV(OP_lengths)[c];
+ continue;
+
+ default:
+ break;
+ }
+
+ /* Check for a supported opcode, and load its properties. */
+
+ code = get_chr_property_list(code, utf, cb->fcc, list);
+ if (code == NULL) return FALSE; /* Unsupported */
+
+ /* If either opcode is a small character list, set pointers for comparing
+ characters from that list with another list, or with a property. */
+
+ if (base_list[0] == OP_CHAR)
+ {
+ chr_ptr = base_list + 2;
+ list_ptr = list;
+ }
+ else if (list[0] == OP_CHAR)
+ {
+ chr_ptr = list + 2;
+ list_ptr = base_list;
+ }
+
+ /* Character bitsets can also be compared to certain opcodes. */
+
+ else if (base_list[0] == OP_CLASS || list[0] == OP_CLASS
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ /* In 8 bit, non-UTF mode, OP_CLASS and OP_NCLASS are the same. */
+ || (!utf && (base_list[0] == OP_NCLASS || list[0] == OP_NCLASS))
+#endif
+ )
+ {
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (base_list[0] == OP_CLASS || (!utf && base_list[0] == OP_NCLASS))
+#else
+ if (base_list[0] == OP_CLASS)
+#endif
+ {
+ set1 = (uint8_t *)(base_end - base_list[2]);
+ list_ptr = list;
+ }
+ else
+ {
+ set1 = (uint8_t *)(code - list[2]);
+ list_ptr = base_list;
+ }
+
+ invert_bits = FALSE;
+ switch(list_ptr[0])
+ {
+ case OP_CLASS:
+ case OP_NCLASS:
+ set2 = (uint8_t *)
+ ((list_ptr == list ? code : base_end) - list_ptr[2]);
+ break;
+
+#ifdef SUPPORT_WIDE_CHARS
+ case OP_XCLASS:
+ xclass_flags = (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE;
+ if ((*xclass_flags & XCL_HASPROP) != 0) return FALSE;
+ if ((*xclass_flags & XCL_MAP) == 0)
+ {
+ /* No bits are set for characters < 256. */
+ if (list[1] == 0) return TRUE;
+ /* Might be an empty repeat. */
+ continue;
+ }
+ set2 = (uint8_t *)(xclass_flags + 1);
+ break;
+#endif
+
+ case OP_NOT_DIGIT:
+ invert_bits = TRUE;
+ /* Fall through */
+ case OP_DIGIT:
+ set2 = (uint8_t *)(cb->cbits + cbit_digit);
+ break;
+
+ case OP_NOT_WHITESPACE:
+ invert_bits = TRUE;
+ /* Fall through */
+ case OP_WHITESPACE:
+ set2 = (uint8_t *)(cb->cbits + cbit_space);
+ break;
+
+ case OP_NOT_WORDCHAR:
+ invert_bits = TRUE;
+ /* Fall through */
+ case OP_WORDCHAR:
+ set2 = (uint8_t *)(cb->cbits + cbit_word);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ /* Because the bit sets are unaligned bytes, we need to perform byte
+ comparison here. */
+
+ set_end = set1 + 32;
+ if (invert_bits)
+ {
+ do
+ {
+ if ((*set1++ & ~(*set2++)) != 0) return FALSE;
+ }
+ while (set1 < set_end);
+ }
+ else
+ {
+ do
+ {
+ if ((*set1++ & *set2++) != 0) return FALSE;
+ }
+ while (set1 < set_end);
+ }
+
+ if (list[1] == 0) return TRUE;
+ /* Might be an empty repeat. */
+ continue;
+ }
+
+ /* Some property combinations also acceptable. Unicode property opcodes are
+ processed specially; the rest can be handled with a lookup table. */
+
+ else
+ {
+ uint32_t leftop, rightop;
+
+ leftop = base_list[0];
+ rightop = list[0];
+
+#ifdef SUPPORT_UNICODE
+ accepted = FALSE; /* Always set in non-unicode case. */
+ if (leftop == OP_PROP || leftop == OP_NOTPROP)
+ {
+ if (rightop == OP_EOD)
+ accepted = TRUE;
+ else if (rightop == OP_PROP || rightop == OP_NOTPROP)
+ {
+ int n;
+ const uint8_t *p;
+ BOOL same = leftop == rightop;
+ BOOL lisprop = leftop == OP_PROP;
+ BOOL risprop = rightop == OP_PROP;
+ BOOL bothprop = lisprop && risprop;
+
+ /* There's a table that specifies how each combination is to be
+ processed:
+ 0 Always return FALSE (never auto-possessify)
+ 1 Character groups are distinct (possessify if both are OP_PROP)
+ 2 Check character categories in the same group (general or particular)
+ 3 Return TRUE if the two opcodes are not the same
+ ... see comments below
+ */
+
+ n = propposstab[base_list[2]][list[2]];
+ switch(n)
+ {
+ case 0: break;
+ case 1: accepted = bothprop; break;
+ case 2: accepted = (base_list[3] == list[3]) != same; break;
+ case 3: accepted = !same; break;
+
+ case 4: /* Left general category, right particular category */
+ accepted = risprop && catposstab[base_list[3]][list[3]] == same;
+ break;
+
+ case 5: /* Right general category, left particular category */
+ accepted = lisprop && catposstab[list[3]][base_list[3]] == same;
+ break;
+
+ /* This code is logically tricky. Think hard before fiddling with it.
+ The posspropstab table has four entries per row. Each row relates to
+ one of PCRE's special properties such as ALNUM or SPACE or WORD.
+ Only WORD actually needs all four entries, but using repeats for the
+ others means they can all use the same code below.
+
+ The first two entries in each row are Unicode general categories, and
+ apply always, because all the characters they include are part of the
+ PCRE character set. The third and fourth entries are a general and a
+ particular category, respectively, that include one or more relevant
+ characters. One or the other is used, depending on whether the check
+ is for a general or a particular category. However, in both cases the
+ category contains more characters than the specials that are defined
+ for the property being tested against. Therefore, it cannot be used
+ in a NOTPROP case.
+
+ Example: the row for WORD contains ucp_L, ucp_N, ucp_P, ucp_Po.
+ Underscore is covered by ucp_P or ucp_Po. */
+
+ case 6: /* Left alphanum vs right general category */
+ case 7: /* Left space vs right general category */
+ case 8: /* Left word vs right general category */
+ p = posspropstab[n-6];
+ accepted = risprop && lisprop ==
+ (list[3] != p[0] &&
+ list[3] != p[1] &&
+ (list[3] != p[2] || !lisprop));
+ break;
+
+ case 9: /* Right alphanum vs left general category */
+ case 10: /* Right space vs left general category */
+ case 11: /* Right word vs left general category */
+ p = posspropstab[n-9];
+ accepted = lisprop && risprop ==
+ (base_list[3] != p[0] &&
+ base_list[3] != p[1] &&
+ (base_list[3] != p[2] || !risprop));
+ break;
+
+ case 12: /* Left alphanum vs right particular category */
+ case 13: /* Left space vs right particular category */
+ case 14: /* Left word vs right particular category */
+ p = posspropstab[n-12];
+ accepted = risprop && lisprop ==
+ (catposstab[p[0]][list[3]] &&
+ catposstab[p[1]][list[3]] &&
+ (list[3] != p[3] || !lisprop));
+ break;
+
+ case 15: /* Right alphanum vs left particular category */
+ case 16: /* Right space vs left particular category */
+ case 17: /* Right word vs left particular category */
+ p = posspropstab[n-15];
+ accepted = lisprop && risprop ==
+ (catposstab[p[0]][base_list[3]] &&
+ catposstab[p[1]][base_list[3]] &&
+ (base_list[3] != p[3] || !risprop));
+ break;
+ }
+ }
+ }
+
+ else
+#endif /* SUPPORT_UNICODE */
+
+ accepted = leftop >= FIRST_AUTOTAB_OP && leftop <= LAST_AUTOTAB_LEFT_OP &&
+ rightop >= FIRST_AUTOTAB_OP && rightop <= LAST_AUTOTAB_RIGHT_OP &&
+ autoposstab[leftop - FIRST_AUTOTAB_OP][rightop - FIRST_AUTOTAB_OP];
+
+ if (!accepted) return FALSE;
+
+ if (list[1] == 0) return TRUE;
+ /* Might be an empty repeat. */
+ continue;
+ }
+
+ /* Control reaches here only if one of the items is a small character list.
+ All characters are checked against the other side. */
+
+ do
+ {
+ chr = *chr_ptr;
+
+ switch(list_ptr[0])
+ {
+ case OP_CHAR:
+ ochr_ptr = list_ptr + 2;
+ do
+ {
+ if (chr == *ochr_ptr) return FALSE;
+ ochr_ptr++;
+ }
+ while(*ochr_ptr != NOTACHAR);
+ break;
+
+ case OP_NOT:
+ ochr_ptr = list_ptr + 2;
+ do
+ {
+ if (chr == *ochr_ptr)
+ break;
+ ochr_ptr++;
+ }
+ while(*ochr_ptr != NOTACHAR);
+ if (*ochr_ptr == NOTACHAR) return FALSE; /* Not found */
+ break;
+
+ /* Note that OP_DIGIT etc. are generated only when PCRE2_UCP is *not*
+ set. When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */
+
+ case OP_DIGIT:
+ if (chr < 256 && (cb->ctypes[chr] & ctype_digit) != 0) return FALSE;
+ break;
+
+ case OP_NOT_DIGIT:
+ if (chr > 255 || (cb->ctypes[chr] & ctype_digit) == 0) return FALSE;
+ break;
+
+ case OP_WHITESPACE:
+ if (chr < 256 && (cb->ctypes[chr] & ctype_space) != 0) return FALSE;
+ break;
+
+ case OP_NOT_WHITESPACE:
+ if (chr > 255 || (cb->ctypes[chr] & ctype_space) == 0) return FALSE;
+ break;
+
+ case OP_WORDCHAR:
+ if (chr < 255 && (cb->ctypes[chr] & ctype_word) != 0) return FALSE;
+ break;
+
+ case OP_NOT_WORDCHAR:
+ if (chr > 255 || (cb->ctypes[chr] & ctype_word) == 0) return FALSE;
+ break;
+
+ case OP_HSPACE:
+ switch(chr)
+ {
+ HSPACE_CASES: return FALSE;
+ default: break;
+ }
+ break;
+
+ case OP_NOT_HSPACE:
+ switch(chr)
+ {
+ HSPACE_CASES: break;
+ default: return FALSE;
+ }
+ break;
+
+ case OP_ANYNL:
+ case OP_VSPACE:
+ switch(chr)
+ {
+ VSPACE_CASES: return FALSE;
+ default: break;
+ }
+ break;
+
+ case OP_NOT_VSPACE:
+ switch(chr)
+ {
+ VSPACE_CASES: break;
+ default: return FALSE;
+ }
+ break;
+
+ case OP_DOLL:
+ case OP_EODN:
+ switch (chr)
+ {
+ case CHAR_CR:
+ case CHAR_LF:
+ case CHAR_VT:
+ case CHAR_FF:
+ case CHAR_NEL:
+#ifndef EBCDIC
+ case 0x2028:
+ case 0x2029:
+#endif /* Not EBCDIC */
+ return FALSE;
+ }
+ break;
+
+ case OP_EOD: /* Can always possessify before \z */
+ break;
+
+#ifdef SUPPORT_UNICODE
+ case OP_PROP:
+ case OP_NOTPROP:
+ if (!check_char_prop(chr, list_ptr[2], list_ptr[3],
+ list_ptr[0] == OP_NOTPROP))
+ return FALSE;
+ break;
+#endif
+
+ case OP_NCLASS:
+ if (chr > 255) return FALSE;
+ /* Fall through */
+
+ case OP_CLASS:
+ if (chr > 255) break;
+ class_bitset = (uint8_t *)
+ ((list_ptr == list ? code : base_end) - list_ptr[2]);
+ if ((class_bitset[chr >> 3] & (1 << (chr & 7))) != 0) return FALSE;
+ break;
+
+#ifdef SUPPORT_WIDE_CHARS
+ case OP_XCLASS:
+ if (PRIV(xclass)(chr, (list_ptr == list ? code : base_end) -
+ list_ptr[2] + LINK_SIZE, utf)) return FALSE;
+ break;
+#endif
+
+ default:
+ return FALSE;
+ }
+
+ chr_ptr++;
+ }
+ while(*chr_ptr != NOTACHAR);
+
+ /* At least one character must be matched from this opcode. */
+
+ if (list[1] == 0) return TRUE;
+ }
+
+/* Control never reaches here. There used to be a fail-save return FALSE; here,
+but some compilers complain about an unreachable statement. */
+}
+
+
+
+/*************************************************
+* Scan compiled regex for auto-possession *
+*************************************************/
+
+/* Replaces single character iterations with their possessive alternatives
+if appropriate. This function modifies the compiled opcode! Hitting a
+non-existant opcode may indicate a bug in PCRE2, but it can also be caused if a
+bad UTF string was compiled with PCRE2_NO_UTF_CHECK.
+
+Arguments:
+ code points to start of the byte code
+ utf TRUE in UTF mode
+ cb compile data block
+
+Returns: 0 for success
+ -1 if a non-existant opcode is encountered
+*/
+
+int
+PRIV(auto_possessify)(PCRE2_UCHAR *code, BOOL utf, const compile_block *cb)
+{
+register PCRE2_UCHAR c;
+PCRE2_SPTR end;
+PCRE2_UCHAR *repeat_opcode;
+uint32_t list[8];
+int rec_limit;
+
+for (;;)
+ {
+ c = *code;
+
+ if (c > OP_TABLE_LENGTH) return -1; /* Something gone wrong */
+
+ if (c >= OP_STAR && c <= OP_TYPEPOSUPTO)
+ {
+ c -= get_repeat_base(c) - OP_STAR;
+ end = (c <= OP_MINUPTO) ?
+ get_chr_property_list(code, utf, cb->fcc, list) : NULL;
+ list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO;
+
+ rec_limit = 1000;
+ if (end != NULL && compare_opcodes(end, utf, cb, list, end, &rec_limit))
+ {
+ switch(c)
+ {
+ case OP_STAR:
+ *code += OP_POSSTAR - OP_STAR;
+ break;
+
+ case OP_MINSTAR:
+ *code += OP_POSSTAR - OP_MINSTAR;
+ break;
+
+ case OP_PLUS:
+ *code += OP_POSPLUS - OP_PLUS;
+ break;
+
+ case OP_MINPLUS:
+ *code += OP_POSPLUS - OP_MINPLUS;
+ break;
+
+ case OP_QUERY:
+ *code += OP_POSQUERY - OP_QUERY;
+ break;
+
+ case OP_MINQUERY:
+ *code += OP_POSQUERY - OP_MINQUERY;
+ break;
+
+ case OP_UPTO:
+ *code += OP_POSUPTO - OP_UPTO;
+ break;
+
+ case OP_MINUPTO:
+ *code += OP_POSUPTO - OP_MINUPTO;
+ break;
+ }
+ }
+ c = *code;
+ }
+ else if (c == OP_CLASS || c == OP_NCLASS || c == OP_XCLASS)
+ {
+#ifdef SUPPORT_WIDE_CHARS
+ if (c == OP_XCLASS)
+ repeat_opcode = code + GET(code, 1);
+ else
+#endif
+ repeat_opcode = code + 1 + (32 / sizeof(PCRE2_UCHAR));
+
+ c = *repeat_opcode;
+ if (c >= OP_CRSTAR && c <= OP_CRMINRANGE)
+ {
+ /* end must not be NULL. */
+ end = get_chr_property_list(code, utf, cb->fcc, list);
+
+ list[1] = (c & 1) == 0;
+
+ rec_limit = 1000;
+ if (compare_opcodes(end, utf, cb, list, end, &rec_limit))
+ {
+ switch (c)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ *repeat_opcode = OP_CRPOSSTAR;
+ break;
+
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ *repeat_opcode = OP_CRPOSPLUS;
+ break;
+
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ *repeat_opcode = OP_CRPOSQUERY;
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ *repeat_opcode = OP_CRPOSRANGE;
+ break;
+ }
+ }
+ }
+ c = *code;
+ }
+
+ switch(c)
+ {
+ case OP_END:
+ return 0;
+
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEPOSQUERY:
+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
+ break;
+
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEEXACT:
+ case OP_TYPEPOSUPTO:
+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
+ code += 2;
+ break;
+
+ case OP_CALLOUT_STR:
+ code += GET(code, 1 + 2*LINK_SIZE);
+ break;
+
+#ifdef SUPPORT_WIDE_CHARS
+ case OP_XCLASS:
+ code += GET(code, 1);
+ break;
+#endif
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ code += code[1];
+ break;
+ }
+
+ /* Add in the fixed length from the table */
+
+ code += PRIV(OP_lengths)[c];
+
+ /* In UTF-8 and UTF-16 modes, opcodes that are followed by a character may be
+ followed by a multi-byte character. The length in the table is a minimum, so
+ we have to arrange to skip the extra code units. */
+
+#ifdef MAYBE_UTF_MULTI
+ if (utf) switch(c)
+ {
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+ case OP_STAR:
+ case OP_MINSTAR:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_UPTO:
+ case OP_MINUPTO:
+ case OP_EXACT:
+ case OP_POSSTAR:
+ case OP_POSPLUS:
+ case OP_POSQUERY:
+ case OP_POSUPTO:
+ case OP_STARI:
+ case OP_MINSTARI:
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_QUERYI:
+ case OP_MINQUERYI:
+ case OP_UPTOI:
+ case OP_MINUPTOI:
+ case OP_EXACTI:
+ case OP_POSSTARI:
+ case OP_POSPLUSI:
+ case OP_POSQUERYI:
+ case OP_POSUPTOI:
+ case OP_NOTSTAR:
+ case OP_NOTMINSTAR:
+ case OP_NOTPLUS:
+ case OP_NOTMINPLUS:
+ case OP_NOTQUERY:
+ case OP_NOTMINQUERY:
+ case OP_NOTUPTO:
+ case OP_NOTMINUPTO:
+ case OP_NOTEXACT:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSUPTO:
+ case OP_NOTSTARI:
+ case OP_NOTMINSTARI:
+ case OP_NOTPLUSI:
+ case OP_NOTMINPLUSI:
+ case OP_NOTQUERYI:
+ case OP_NOTMINQUERYI:
+ case OP_NOTUPTOI:
+ case OP_NOTMINUPTOI:
+ case OP_NOTEXACTI:
+ case OP_NOTPOSSTARI:
+ case OP_NOTPOSPLUSI:
+ case OP_NOTPOSQUERYI:
+ case OP_NOTPOSUPTOI:
+ if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);
+ break;
+ }
+#else
+ (void)(utf); /* Keep compiler happy by referencing function argument */
+#endif /* SUPPORT_WIDE_CHARS */
+ }
+}
+
+/* End of pcre2_auto_possess.c */
diff --git a/src/3rdparty/pcre/pcre_chartables.c b/src/3rdparty/pcre2/src/pcre2_chartables.c
index 1e20ec29d0..203cb1a4ab 100644
--- a/src/3rdparty/pcre/pcre_chartables.c
+++ b/src/3rdparty/pcre2/src/pcre2_chartables.c
@@ -3,19 +3,19 @@
*************************************************/
/* 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
+are passed to PCRE2 by the application that calls it. The tables are used only
for characters whose code values are less than 256.
This 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
+called dftables (which is distributed with PCRE2) can be used to build
alternative versions of this file. This is necessary if you are running in an
EBCDIC environment, or if you want to default to a different encoding, for
example ISO-8859-1. When dftables is run, it creates these tables in the
-current locale. If PCRE is configured with --enable-rebuild-chartables, this
+current locale. If PCRE2 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
+array definition from the final binary if PCRE2 is built into a static library
and dead code stripping is activated. This leads to link errors. Pulling in the
header ensures that the array gets flagged as "someone outside this compilation
unit might reference this" and so it will always be supplied to the linker. */
@@ -24,9 +24,9 @@ unit might reference this" and so it will always be supplied to the linker. */
#include "config.h"
#endif
-#include "pcre_internal.h"
+#include "pcre2_internal.h"
-const pcre_uint8 PRIV(default_tables)[] = {
+const uint8_t PRIV(default_tables)[] = {
/* This table is a lower casing table. */
@@ -195,4 +195,4 @@ graph, print, punct, and cntrl. Other classes are built from combinations. */
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 */
+/* End of pcre2_chartables.c */
diff --git a/src/3rdparty/pcre/pcre_compile.c b/src/3rdparty/pcre2/src/pcre2_compile.c
index 7cd3950123..bb9736cd51 100644
--- a/src/3rdparty/pcre/pcre_compile.c
+++ b/src/3rdparty/pcre2/src/pcre2_compile.c
@@ -6,7 +6,8 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2016 University of Cambridge
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -38,55 +39,56 @@ 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 HAVE_CONFIG_H
#include "config.h"
#endif
-#define NLBLOCK cd /* Block containing newline information */
-#define PSSTART start_pattern /* Field containing pattern start */
-#define PSEND end_pattern /* Field containing pattern end */
-
-#include "pcre_internal.h"
+#define NLBLOCK cb /* Block containing newline information */
+#define PSSTART start_pattern /* Field containing processed string start */
+#define PSEND end_pattern /* Field containing processed string end */
+#include "pcre2_internal.h"
-/* When PCRE_DEBUG is defined, we need the pcre(16|32)_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. */
+/* In rare error cases debugging might require calling pcre2_printint(). */
-#ifdef PCRE_DEBUG
-/* pcre_printint.c should not include any headers */
-#define PCRE_INCLUDED
-#include "pcre_printint.c"
-#undef PCRE_INCLUDED
+#if 0
+#ifdef EBCDIC
+#define PRINTABLE(c) ((c) >= 64 && (c) < 255)
+#else
+#define PRINTABLE(c) ((c) >= 32 && (c) < 127)
+#endif
+#include "pcre2_printint.c"
+#define CALL_PRINTINT
#endif
+/* There are a few things that vary with different code unit sizes. Handle them
+by defining macros in order to minimize #if usage. */
-/* Macro for setting individual bits in class bitmaps. */
+#if PCRE2_CODE_UNIT_WIDTH == 8
+#define STRING_UTFn_RIGHTPAR STRING_UTF8_RIGHTPAR, 5
+#define XDIGIT(c) xdigitab[c]
-#define SETBIT(a,b) a[(b)/8] |= (1 << ((b)&7))
+#else /* Either 16-bit or 32-bit */
+#define XDIGIT(c) (MAX_255(c)? xdigitab[c] : 0xff)
-/* 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. */
+#if PCRE2_CODE_UNIT_WIDTH == 16
+#define STRING_UTFn_RIGHTPAR STRING_UTF16_RIGHTPAR, 6
-#define OFLOW_MAX (INT_MAX - 20)
+#else /* 32-bit */
+#define STRING_UTFn_RIGHTPAR STRING_UTF32_RIGHTPAR, 6
+#endif
+#endif
-/* Definitions to allow mutual recursion */
+/* Function definitions to allow mutual recursion */
-static int
- add_list_to_class(pcre_uint8 *, pcre_uchar **, int, compile_data *,
- const pcre_uint32 *, unsigned int);
+static unsigned int
+ add_list_to_class(uint8_t *, PCRE2_UCHAR **, uint32_t, compile_block *,
+ const uint32_t *, unsigned int);
static BOOL
- compile_regex(int, pcre_uchar **, const pcre_uchar **, int *, BOOL, BOOL, int, int,
- pcre_uint32 *, pcre_int32 *, pcre_uint32 *, pcre_int32 *, branch_chain *,
- compile_data *, int *);
+ compile_regex(uint32_t, PCRE2_UCHAR **, PCRE2_SPTR *, int *, BOOL, BOOL,
+ uint32_t, int, uint32_t *, int32_t *, uint32_t *, int32_t *,
+ branch_chain *, compile_block *, size_t *);
@@ -94,60 +96,197 @@ static BOOL
* 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)
+/* This value specifies the size of stack workspace, which is used in different
+ways in the different pattern scans. The group-identifying pre-scan uses it to
+handle nesting, and needs it to be 16-bit aligned.
-/* This value determines the size of the initial vector that is used for
-remembering named groups during the pre-compile. It is allocated on the stack,
-but if it is too small, it is expanded using malloc(), in a similar way to the
-workspace. The value is the number of slots in the list. */
+During the first compiling phase, when determining how much memory is required,
+the regex is partly compiled into this space, but the compiled parts are
+discarded as soon as they can be, so that hopefully there will never be an
+overrun. The code does, however, check for an overrun, which can occur for
+pathological patterns. The size of the workspace depends on LINK_SIZE because
+the length of compiled items varies with this.
-#define NAMED_GROUP_LIST_SIZE 20
+In the real compile phase, the workspace is used for remembering data about
+numbered groups, provided there are not too many of them (if there are, extra
+memory is acquired). For this phase the memory must be 32-bit aligned. Having
+defined the size in code units, we set up C32_WORK_SIZE as the number of
+elements in the 32-bit vector. */
+
+#define COMPILE_WORK_SIZE (2048*LINK_SIZE) /* Size in code units */
+
+#define C32_WORK_SIZE \
+ ((COMPILE_WORK_SIZE * sizeof(PCRE2_UCHAR))/sizeof(uint32_t))
/* 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. */
+/* This value determines the size of the initial vector that is used for
+remembering named groups during the pre-compile. It is allocated on the stack,
+but if it is too small, it is expanded, in a similar way to the workspace. The
+value is the number of slots in the list. */
+
+#define NAMED_GROUP_LIST_SIZE 20
+
+/* The original PCRE required patterns to be zero-terminated, and it simplifies
+the compiling code if it is guaranteed that there is a zero code unit at the
+end of the pattern, because this means that tests for coding sequences such as
+(*SKIP) or even just (?<= can check a sequence of code units without having to
+keep checking for the end of the pattern. The new PCRE2 API allows zero code
+units within patterns if a positive length is given, but in order to keep most
+of the compiling code as it was, we copy such patterns and add a zero on the
+end. This value determines the size of space on the stack that is used if the
+pattern fits; if not, heap memory is used. */
+
+#define COPIED_PATTERN_SIZE 1024
+
+/* Maximum length value to check against when making sure that the variable
+that holds the compiled pattern length does not overflow. We make it a bit less
+than INT_MAX to allow for adding in group terminating bytes, so that we don't
+have to check them every time. */
+
+#define OFLOW_MAX (INT_MAX - 20)
+
+/* Macro for setting individual bits in class bitmaps. It took some
+experimenting to figure out how to stop gcc 5.3.0 from warning with
+-Wconversion. This version gets a warning:
+
+ #define SETBIT(a,b) a[(b)/8] |= (uint8_t)(1 << ((b)&7))
+
+Let's hope the apparently less efficient version isn't actually so bad if the
+compiler is clever with identical subexpressions. */
+
+#define SETBIT(a,b) a[(b)/8] = (uint8_t)(a[(b)/8] | (1 << ((b)&7)))
+
+/* Private flags added to firstcu and reqcu. */
#define REQ_CASELESS (1 << 0) /* Indicates caselessness */
-#define REQ_VARY (1 << 1) /* Reqchar followed non-literal item */
-/* Negative values for the firstchar and reqchar flags */
-#define REQ_UNSET (-2)
-#define REQ_NONE (-1)
+#define REQ_VARY (1 << 1) /* reqcu followed non-literal item */
+/* Negative values for the firstcu and reqcu flags */
+#define REQ_UNSET (-2) /* Not yet found anything */
+#define REQ_NONE (-1) /* Found not fixed char */
+
+/* These flags are used in the groupinfo vector. */
+
+#define GI_SET_COULD_BE_EMPTY 0x80000000u
+#define GI_COULD_BE_EMPTY 0x40000000u
+#define GI_NOT_FIXED_LENGTH 0x20000000u
+#define GI_SET_FIXED_LENGTH 0x10000000u
+#define GI_FIXED_LENGTH_MASK 0x0000ffffu
-/* Repeated character flags. */
+/* This bit (which is greater than any UTF value) is used to indicate that a
+variable contains a number of code units instead of an actual code point. */
-#define UTF_LENGTH 0x10000000l /* The char contains its length. */
+#define UTF_LENGTH 0x10000000l
-/* 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. */
+/* This simple test for a decimal digit works for both ASCII/Unicode and EBCDIC
+and is fast (a good compiler can turn it into a subtraction and unsigned
+comparison). */
+
+#define IS_DIGIT(x) ((x) >= CHAR_0 && (x) <= CHAR_9)
+
+/* Table to identify hex digits. The tables in chartables are dependent on the
+locale, and may mark arbitrary characters as digits. We want to recognize only
+0-9, a-z, and A-Z as hex digits, which is why we have a private table here. It
+costs 256 bytes, but it is a lot faster than doing character value tests (at
+least in some simple cases I timed), and in some applications one wants PCRE to
+compile efficiently as well as match efficiently. The value in the table is
+the binary hex digit value, or 0xff for non-hex digits. */
+
+/* This is the "normal" case, for ASCII systems, and EBCDIC systems running in
+UTF-8 mode. */
#ifndef EBCDIC
+static const uint8_t xdigitab[] =
+ {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0- 7 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 8- 15 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 16- 23 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 24- 31 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* - ' */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* ( - / */
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 0 - 7 */
+ 0x08,0x09,0xff,0xff,0xff,0xff,0xff,0xff, /* 8 - ? */
+ 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* @ - G */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* H - O */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* P - W */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* X - _ */
+ 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* ` - g */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* h - o */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* p - w */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* x -127 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 128-135 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 136-143 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 144-151 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 152-159 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 160-167 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 168-175 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 176-183 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 184-191 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 192-199 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 2ff-207 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 208-215 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 216-223 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 224-231 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 232-239 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 240-247 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};/* 248-255 */
+
+#else
+
+/* This is the "abnormal" case, for EBCDIC systems not running in UTF-8 mode. */
+
+static const uint8_t xdigitab[] =
+ {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0- 7 0 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 8- 15 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 16- 23 10 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 24- 31 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 32- 39 20 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 40- 47 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 48- 55 30 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 56- 63 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* - 71 40 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 72- | */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* & - 87 50 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 88- 95 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* - -103 60 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 104- ? */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 112-119 70 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 120- " */
+ 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* 128- g 80 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* h -143 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 144- p 90 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* q -159 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 160- x A0 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* y -175 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* ^ -183 B0 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 184-191 */
+ 0xff,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xff, /* { - G C0 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* H -207 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* } - P D0 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* Q -223 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* \ - X E0 */
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* Y -239 */
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 0 - 7 F0 */
+ 0x08,0x09,0xff,0xff,0xff,0xff,0xff,0xff};/* 8 -255 */
+#endif /* EBCDIC */
+
+
+/* Table for handling alphanumeric escaped characters. Positive returns are
+simple data values; negative values are for special things like \d and so on.
+Zero means further processing is needed (for things like \x), or the escape is
+invalid. */
/* This is the "normal" table for ASCII systems or for EBCDIC systems running
-in UTF-8 mode. */
+in UTF-8 mode. It runs from '0' to 'z'. */
+
+#ifndef EBCDIC
+#define ESCAPES_FIRST CHAR_0
+#define ESCAPES_LAST CHAR_z
+#define UPPER_CASE(c) (c-32)
static const short int escapes[] = {
0, 0,
@@ -192,17 +331,23 @@ static const short int escapes[] = {
#else
-/* This is the "abnormal" table for EBCDIC systems without UTF-8 support. */
+/* This is the "abnormal" table for EBCDIC systems without UTF-8 support.
+It runs from 'a' to '9'. For some minimal testing of EBCDIC features, the code
+is sometimes compiled on an ASCII system. In this case, we must not use CHAR_a
+because it is defined as 'a', which of course picks up the ASCII value. */
+
+#if 'a' == 0x81 /* Check for a real EBCDIC environment */
+#define ESCAPES_FIRST CHAR_a
+#define ESCAPES_LAST CHAR_9
+#define UPPER_CASE(c) (c+64)
+#else /* Testing in an ASCII environment */
+#define ESCAPES_FIRST ((unsigned char)'\x81') /* EBCDIC 'a' */
+#define ESCAPES_LAST ((unsigned char)'\xf9') /* EBCDIC '9' */
+#define UPPER_CASE(c) (c-32)
+#endif
static const short int escapes[] = {
-/* 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, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0,
+/* 80 */ ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0,
/* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0,
/* 90 */ 0, 0, -ESC_k, 0, 0, ESC_n, 0, -ESC_p,
/* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0,
@@ -217,7 +362,7 @@ static const short int escapes[] = {
/* 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
+/* F8 */ 0, 0
};
/* We also need a table of characters that may follow \c in an EBCDIC
@@ -225,7 +370,7 @@ environment for characters 0-31. */
static unsigned char ebcdic_escape_c[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
-#endif
+#endif /* EBCDIC */
/* Table of special "verbs" like (*PRUNE). This is a short table, so it is
@@ -269,11 +414,11 @@ static const int verbcount = sizeof(verbs)/sizeof(verbitem);
/* Substitutes for [[:<:]] and [[:>:]], which mean start and end of word in
another regex library. */
-static const pcre_uchar sub_start_of_word[] = {
+static const PCRE2_UCHAR sub_start_of_word[] = {
CHAR_BACKSLASH, CHAR_b, CHAR_LEFT_PARENTHESIS, CHAR_QUESTION_MARK,
CHAR_EQUALS_SIGN, CHAR_BACKSLASH, CHAR_w, CHAR_RIGHT_PARENTHESIS, '\0' };
-static const pcre_uchar sub_end_of_word[] = {
+static const PCRE2_UCHAR sub_end_of_word[] = {
CHAR_BACKSLASH, CHAR_b, CHAR_LEFT_PARENTHESIS, CHAR_QUESTION_MARK,
CHAR_LESS_THAN_SIGN, CHAR_EQUALS_SIGN, CHAR_BACKSLASH, CHAR_w,
CHAR_RIGHT_PARENTHESIS, '\0' };
@@ -292,7 +437,7 @@ static const char posix_names[] =
STRING_graph0 STRING_print0 STRING_punct0 STRING_space0
STRING_word0 STRING_xdigit;
-static const pcre_uint8 posix_name_lengths[] = {
+static const uint8_t posix_name_lengths[] = {
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };
#define PC_GRAPH 8
@@ -327,30 +472,30 @@ static const int posix_class_maps[] = {
cbit_xdigit,-1, 0 /* xdigit */
};
-/* Table of substitutes for \d etc when PCRE_UCP is set. They are replaced by
+/* Table of substitutes for \d etc when PCRE2_UCP is set. They are replaced by
Unicode property escapes. */
-#ifdef SUPPORT_UCP
-static const pcre_uchar string_PNd[] = {
+#ifdef SUPPORT_UNICODE
+static const PCRE2_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[] = {
+static const PCRE2_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[] = {
+static const PCRE2_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[] = {
+static const PCRE2_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[] = {
+static const PCRE2_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[] = {
+static const PCRE2_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[] = {
+static PCRE2_SPTR substitutes[] = {
string_PNd, /* \D */
string_pNd, /* \d */
string_PXsp, /* \S */ /* Xsp is Perl space, but from 8.34, Perl */
@@ -365,49 +510,55 @@ general substitute of a Unicode property escape (\p or \P). However, for some
POSIX classes (e.g. graph, print, punct) a special property code is compiled
directly. */
-static const pcre_uchar string_pL[] = {
+static const PCRE2_UCHAR string_pCc[] = {
+ CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_C, CHAR_c, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const PCRE2_UCHAR string_pL[] = {
CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
CHAR_L, CHAR_RIGHT_CURLY_BRACKET, '\0' };
-static const pcre_uchar string_pLl[] = {
+static const PCRE2_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[] = {
+static const PCRE2_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[] = {
+static const PCRE2_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[] = {
+static const PCRE2_UCHAR string_h[] = {
CHAR_BACKSLASH, CHAR_h, '\0' };
-static const pcre_uchar string_pXps[] = {
+static const PCRE2_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[] = {
+static const PCRE2_UCHAR string_PCc[] = {
+ CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
+ CHAR_C, CHAR_c, CHAR_RIGHT_CURLY_BRACKET, '\0' };
+static const PCRE2_UCHAR string_PL[] = {
CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
CHAR_L, CHAR_RIGHT_CURLY_BRACKET, '\0' };
-static const pcre_uchar string_PLl[] = {
+static const PCRE2_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[] = {
+static const PCRE2_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[] = {
+static const PCRE2_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[] = {
+static const PCRE2_UCHAR string_H[] = {
CHAR_BACKSLASH, CHAR_H, '\0' };
-static const pcre_uchar string_PXps[] = {
+static const PCRE2_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[] = {
+static PCRE2_SPTR posix_substitutes[] = {
string_pL, /* alpha */
string_pLl, /* lower */
string_pLu, /* upper */
string_pXan, /* alnum */
NULL, /* ascii */
string_h, /* blank */
- NULL, /* cntrl */
+ string_pCc, /* cntrl */
string_pNd, /* digit */
NULL, /* graph */
NULL, /* print */
@@ -422,7 +573,7 @@ static const pcre_uchar *posix_substitutes[] = {
string_PXan, /* ^alnum */
NULL, /* ^ascii */
string_H, /* ^blank */
- NULL, /* ^cntrl */
+ string_PCc, /* ^cntrl */
string_PNd, /* ^digit */
NULL, /* ^graph */
NULL, /* ^print */
@@ -431,391 +582,91 @@ static const pcre_uchar *posix_substitutes[] = {
string_PXwd, /* ^word */ /* Perl and POSIX space are the same */
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 */
- "internal error: invalid forward reference offset\0"
- "internal error: unexpected repeat\0"
- "unrecognized character after (? or (?-\0"
- "POSIX named classes are supported only within a class\0"
- "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 (?( or (?(?C)\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{} or \\o{} 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 or malformed\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"
-#ifndef EBCDIC
- "\\c must be followed by an ASCII character\0"
-#else
- "\\c must be followed by a letter or one of [\\]^_?\0"
-#endif
- "\\k is not followed by a braced, angle-bracketed, or quoted name\0"
- /* 70 */
- "internal error: unknown opcode in find_fixedlength()\0"
- "\\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"
- /* 75 */
- "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)\0"
- "character value in \\u.... sequence is too large\0"
- "invalid UTF-32 string\0"
- "setting UTF is disabled by the application\0"
- "non-hex character in \\x{} (closing brace missing?)\0"
- /* 80 */
- "non-octal character in \\o{} (closing brace missing?)\0"
- "missing opening brace after \\o\0"
- "parentheses are too deeply nested\0"
- "invalid range in character class\0"
- "group name must start with a non-digit\0"
- /* 85 */
- "parentheses are too deeply nested (stack check)\0"
- "digits missing in \\x{} or \\o{}\0"
- "regular expression is too complicated\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[] =
+#define POSIX_SUBSIZE (sizeof(posix_substitutes) / sizeof(PCRE2_UCHAR *))
+#endif /* SUPPORT_UNICODE */
+
+/* Masks for checking option settings. */
+
+#define PUBLIC_COMPILE_OPTIONS \
+ (PCRE2_ANCHORED|PCRE2_ALLOW_EMPTY_CLASS|PCRE2_ALT_BSUX|PCRE2_ALT_CIRCUMFLEX| \
+ PCRE2_ALT_VERBNAMES|PCRE2_AUTO_CALLOUT|PCRE2_CASELESS|PCRE2_DOLLAR_ENDONLY| \
+ PCRE2_DOTALL|PCRE2_DUPNAMES|PCRE2_EXTENDED|PCRE2_FIRSTLINE| \
+ PCRE2_MATCH_UNSET_BACKREF|PCRE2_MULTILINE|PCRE2_NEVER_BACKSLASH_C| \
+ PCRE2_NEVER_UCP|PCRE2_NEVER_UTF|PCRE2_NO_AUTO_CAPTURE| \
+ PCRE2_NO_AUTO_POSSESS|PCRE2_NO_DOTSTAR_ANCHOR|PCRE2_NO_START_OPTIMIZE| \
+ PCRE2_NO_UTF_CHECK|PCRE2_UCP|PCRE2_UNGREEDY|PCRE2_USE_OFFSET_LIMIT| \
+ PCRE2_UTF)
+
+/* Compile time error code numbers. They are given names so that they can more
+easily be tracked. When a new number is added, the tables called eint1 and
+eint2 in pcre2posix.c may need to be updated, and a new error text must be
+added to compile_error_texts in pcre2_error.c. */
+
+enum { ERR0 = COMPILE_ERROR_BASE,
+ ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10,
+ ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20,
+ ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, ERR30,
+ ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, ERR40,
+ ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49, ERR50,
+ ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59, ERR60,
+ ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70,
+ ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, ERR80,
+ ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88 };
+
+/* Error codes that correspond to negative error codes returned by
+find_fixedlength(). */
+
+static int fixed_length_errors[] =
{
- 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
-
-
-/* This table is used to check whether auto-possessification is possible
-between adjacent character-type opcodes. The left-hand (repeated) opcode is
-used to select the row, and the right-hand opcode is use to select the column.
-A value of 1 means that auto-possessification is OK. For example, the second
-value in the first row means that \D+\d can be turned into \D++\d.
-
-The Unicode property types (\P and \p) have to be present to fill out the table
-because of what their opcode values are, but the table values should always be
-zero because property types are handled separately in the code. The last four
-columns apply to items that cannot be repeated, so there is no need to have
-rows for them. Note that OP_DIGIT etc. are generated only when PCRE_UCP is
-*not* set. When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */
-
-#define APTROWS (LAST_AUTOTAB_LEFT_OP - FIRST_AUTOTAB_OP + 1)
-#define APTCOLS (LAST_AUTOTAB_RIGHT_OP - FIRST_AUTOTAB_OP + 1)
-
-static const pcre_uint8 autoposstab[APTROWS][APTCOLS] = {
-/* \D \d \S \s \W \w . .+ \C \P \p \R \H \h \V \v \X \Z \z $ $M */
- { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \D */
- { 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \d */
- { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \S */
- { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \s */
- { 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \W */
- { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, /* \w */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* . */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* .+ */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, /* \C */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* \P */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* \p */
- { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, /* \R */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, /* \H */
- { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0 }, /* \h */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0 }, /* \V */
- { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0 }, /* \v */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 } /* \X */
-};
-
-
-/* This table is used to check whether auto-possessification is possible
-between adjacent Unicode property opcodes (OP_PROP and OP_NOTPROP). The
-left-hand (repeated) opcode is used to select the row, and the right-hand
-opcode is used to select the column. The values are as follows:
-
- 0 Always return FALSE (never auto-possessify)
- 1 Character groups are distinct (possessify if both are OP_PROP)
- 2 Check character categories in the same group (general or particular)
- 3 TRUE if the two opcodes are not the same (PROP vs NOTPROP)
-
- 4 Check left general category vs right particular category
- 5 Check right general category vs left particular category
-
- 6 Left alphanum vs right general category
- 7 Left space vs right general category
- 8 Left word vs right general category
-
- 9 Right alphanum vs left general category
- 10 Right space vs left general category
- 11 Right word vs left general category
-
- 12 Left alphanum vs right particular category
- 13 Left space vs right particular category
- 14 Left word vs right particular category
-
- 15 Right alphanum vs left particular category
- 16 Right space vs left particular category
- 17 Right word vs left particular category
-*/
-
-static const pcre_uint8 propposstab[PT_TABSIZE][PT_TABSIZE] = {
-/* ANY LAMP GC PC SC ALNUM SPACE PXSPACE WORD CLIST UCNC */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_ANY */
- { 0, 3, 0, 0, 0, 3, 1, 1, 0, 0, 0 }, /* PT_LAMP */
- { 0, 0, 2, 4, 0, 9, 10, 10, 11, 0, 0 }, /* PT_GC */
- { 0, 0, 5, 2, 0, 15, 16, 16, 17, 0, 0 }, /* PT_PC */
- { 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 }, /* PT_SC */
- { 0, 3, 6, 12, 0, 3, 1, 1, 0, 0, 0 }, /* PT_ALNUM */
- { 0, 1, 7, 13, 0, 1, 3, 3, 1, 0, 0 }, /* PT_SPACE */
- { 0, 1, 7, 13, 0, 1, 3, 3, 1, 0, 0 }, /* PT_PXSPACE */
- { 0, 0, 8, 14, 0, 0, 1, 1, 3, 0, 0 }, /* PT_WORD */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 } /* PT_UCNC */
-};
-
-/* This table is used to check whether auto-possessification is possible
-between adjacent Unicode property opcodes (OP_PROP and OP_NOTPROP) when one
-specifies a general category and the other specifies a particular category. The
-row is selected by the general category and the column by the particular
-category. The value is 1 if the particular category is not part of the general
-category. */
-
-static const pcre_uint8 catposstab[7][30] = {
-/* Cc Cf Cn Co Cs Ll Lm Lo Lt Lu Mc Me Mn Nd Nl No Pc Pd Pe Pf Pi Po Ps Sc Sk Sm So Zl Zp Zs */
- { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* C */
- { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* L */
- { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* M */
- { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* N */
- { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 }, /* P */
- { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1 }, /* S */
- { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 } /* Z */
-};
-
-/* This table is used when checking ALNUM, (PX)SPACE, SPACE, and WORD against
-a general or particular category. The properties in each row are those
-that apply to the character set in question. Duplication means that a little
-unnecessary work is done when checking, but this keeps things much simpler
-because they can all use the same code. For more details see the comment where
-this table is used.
-
-Note: SPACE and PXSPACE used to be different because Perl excluded VT from
-"space", but from Perl 5.18 it's included, so both categories are treated the
-same here. */
-
-static const pcre_uint8 posspropstab[3][4] = {
- { ucp_L, ucp_N, ucp_N, ucp_Nl }, /* ALNUM, 3rd and 4th values redundant */
- { ucp_Z, ucp_Z, ucp_C, ucp_Cc }, /* SPACE and PXSPACE, 2nd value redundant */
- { ucp_L, ucp_N, ucp_P, ucp_Po } /* WORD */
+ ERR0, /* Not an error */
+ ERR0, /* Not an error; -1 is used for "process later" */
+ ERR25, /* Lookbehind is not fixed length */
+ ERR36, /* \C in lookbehind is not allowed */
+ ERR87, /* Lookbehind is too long */
+ ERR86, /* Pattern too complicated */
+ ERR70 /* Internal error: unknown opcode encountered */
+ };
+
+/* This is a table of start-of-pattern options such as (*UTF) and settings such
+as (*LIMIT_MATCH=nnnn) and (*CRLF). For completeness and backward
+compatibility, (*UTFn) is supported in the relevant libraries, but (*UTF) is
+generic and always supported. */
+
+enum { PSO_OPT, /* Value is an option bit */
+ PSO_FLG, /* Value is a flag bit */
+ PSO_NL, /* Value is a newline type */
+ PSO_BSR, /* Value is a \R type */
+ PSO_LIMM, /* Read integer value for match limit */
+ PSO_LIMR }; /* Read integer value for recursion limit */
+
+typedef struct pso {
+ const uint8_t *name;
+ uint16_t length;
+ uint16_t type;
+ uint32_t value;
+} pso;
+
+/* NB: STRING_UTFn_RIGHTPAR contains the length as well */
+
+static pso pso_list[] = {
+ { (uint8_t *)STRING_UTFn_RIGHTPAR, PSO_OPT, PCRE2_UTF },
+ { (uint8_t *)STRING_UTF_RIGHTPAR, 4, PSO_OPT, PCRE2_UTF },
+ { (uint8_t *)STRING_UCP_RIGHTPAR, 4, PSO_OPT, PCRE2_UCP },
+ { (uint8_t *)STRING_NOTEMPTY_RIGHTPAR, 9, PSO_FLG, PCRE2_NOTEMPTY_SET },
+ { (uint8_t *)STRING_NOTEMPTY_ATSTART_RIGHTPAR, 17, PSO_FLG, PCRE2_NE_ATST_SET },
+ { (uint8_t *)STRING_NO_AUTO_POSSESS_RIGHTPAR, 16, PSO_OPT, PCRE2_NO_AUTO_POSSESS },
+ { (uint8_t *)STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR, 18, PSO_OPT, PCRE2_NO_DOTSTAR_ANCHOR },
+ { (uint8_t *)STRING_NO_JIT_RIGHTPAR, 7, PSO_FLG, PCRE2_NOJIT },
+ { (uint8_t *)STRING_NO_START_OPT_RIGHTPAR, 13, PSO_OPT, PCRE2_NO_START_OPTIMIZE },
+ { (uint8_t *)STRING_LIMIT_MATCH_EQ, 12, PSO_LIMM, 0 },
+ { (uint8_t *)STRING_LIMIT_RECURSION_EQ, 16, PSO_LIMR, 0 },
+ { (uint8_t *)STRING_CR_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_CR },
+ { (uint8_t *)STRING_LF_RIGHTPAR, 3, PSO_NL, PCRE2_NEWLINE_LF },
+ { (uint8_t *)STRING_CRLF_RIGHTPAR, 5, PSO_NL, PCRE2_NEWLINE_CRLF },
+ { (uint8_t *)STRING_ANY_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_ANY },
+ { (uint8_t *)STRING_ANYCRLF_RIGHTPAR, 8, PSO_NL, PCRE2_NEWLINE_ANYCRLF },
+ { (uint8_t *)STRING_BSR_ANYCRLF_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_ANYCRLF },
+ { (uint8_t *)STRING_BSR_UNICODE_RIGHTPAR, 12, PSO_BSR, PCRE2_BSR_UNICODE }
};
/* This table is used when converting repeating opcodes into possessified
@@ -824,7 +675,7 @@ value means there is no possessified version - in those cases the item in
question must be wrapped in ONCE brackets. The table is truncated at OP_CALLOUT
because all relevant opcodes are less than that. */
-static const pcre_uint8 opcode_possessify[] = {
+static const uint8_t opcode_possessify[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - 15 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16 - 31 */
@@ -879,827 +730,122 @@ static const pcre_uint8 opcode_possessify[] = {
/*************************************************
-* 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++ != CHAR_NULL) {};
- if (*s == CHAR_NULL) return "Error text not found (please report)";
- }
-return s;
-}
-
-
-
-/*************************************************
-* Expand the workspace *
+* Copy compiled code *
*************************************************/
-/* 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.
+/* Compiled JIT code cannot be copied, so the new compiled block has no
+associated JIT data. */
-Argument: pointer to the compile data block
-Returns: 0 if all went well, else an error number
-*/
-
-static int
-expand_workspace(compile_data *cd)
+PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION
+pcre2_code_copy(const pcre2_code *code)
{
-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;
-}
-
+PCRE2_SIZE* ref_count;
+pcre2_code *newcode;
+if (code == NULL) return NULL;
+newcode = code->memctl.malloc(code->blocksize, code->memctl.memory_data);
+if (newcode == NULL) return NULL;
+memcpy(newcode, code, code->blocksize);
+newcode->executable_jit = NULL;
-/*************************************************
-* 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
-*/
+/* If the code is one that has been deserialized, increment the reference count
+in the decoded tables. */
-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++;
+if ((code->flags & PCRE2_DEREF_TABLES) != 0)
+ {
+ ref_count = (PCRE2_SIZE *)(code->tables + tables_length);
+ (*ref_count)++;
+ }
-return (*p == CHAR_RIGHT_CURLY_BRACKET);
+return newcode;
}
/*************************************************
-* Handle escapes *
+* Free compiled code *
*************************************************/
-/* This function is called when a \ has been encountered. It either returns a
-positive value for a simple escape such as \n, or 0 for a data character which
-will be placed in chptr. A backreference to group n is returned as negative n.
-When UTF-8 is enabled, a positive value greater than 255 may be returned in
-chptr. 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
- chptr points to a returned data character
- 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 => a data character
- positive => a special escape sequence
- negative => a back reference
- on error, errorcodeptr is set
-*/
-
-static int
-check_escape(const pcre_uchar **ptrptr, pcre_uint32 *chptr, int *errorcodeptr,
- int bracount, int options, BOOL isclass)
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_code_free(pcre2_code *code)
{
-/* PCRE_UTF16 has the same value as PCRE_UTF8. */
-BOOL utf = (options & PCRE_UTF8) != 0;
-const pcre_uchar *ptr = *ptrptr + 1;
-pcre_uint32 c;
-int escape = 0;
-int i;
+PCRE2_SIZE* ref_count;
-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 == CHAR_NULL) *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)
- { if (i > 0) c = (pcre_uint32)i; else escape = -i; }
-
-#else /* EBCDIC coding */
-/* Not alphanumeric */
-else if (c < CHAR_a || (!MAX_255(c) || (ebcdic_chartab[c] & 0x0E) == 0)) {}
-else if ((i = escapes[c - 0x48]) != 0) { if (i > 0) c = (pcre_uint32)i; else escape = -i; }
-#endif
-
-/* Escapes that need further processing, or are illegal. */
-
-else
+if (code != NULL)
{
- const pcre_uchar *oldptr;
- BOOL braced, negated, overflow;
- int s;
+ if (code->executable_jit != NULL)
+ PRIV(jit_free)(code->executable_jit, &code->memctl);
- switch (c)
+ if ((code->flags & PCRE2_DEREF_TABLES) != 0)
{
- /* 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 pcre_uint32 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
- }
-
-#if defined COMPILE_PCRE8
- if (c > (utf ? 0x10ffffU : 0xffU))
-#elif defined COMPILE_PCRE16
- if (c > (utf ? 0x10ffffU : 0xffffU))
-#elif defined COMPILE_PCRE32
- if (utf && c > 0x10ffffU)
-#endif
- {
- *errorcodeptr = ERR76;
- }
- else if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
- }
- }
- 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)
- {
- escape = ESC_g;
- break;
- }
-
- /* Handle the Perl-compatible cases */
-
- if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
- {
- const pcre_uchar *p;
- for (p = ptr+2; *p != CHAR_NULL && *p != CHAR_RIGHT_CURLY_BRACKET; p++)
- if (*p != CHAR_MINUS && !IS_DIGIT(*p)) break;
- if (*p != CHAR_NULL && *p != CHAR_RIGHT_CURLY_BRACKET)
- {
- escape = 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. */
- s = 0;
- overflow = FALSE;
- while (IS_DIGIT(ptr[1]))
- {
- if (s > INT_MAX / 10 - 1) /* Integer overflow */
- {
- overflow = TRUE;
- break;
- }
- s = s * 10 + (int)(*(++ptr) - CHAR_0);
- }
- if (overflow) /* Integer overflow */
- {
- while (IS_DIGIT(ptr[1]))
- ptr++;
- *errorcodeptr = ERR61;
- break;
- }
-
- if (braced && *(++ptr) != CHAR_RIGHT_CURLY_BRACKET)
- {
- *errorcodeptr = ERR57;
- break;
- }
-
- if (s == 0)
- {
- *errorcodeptr = ERR58;
- break;
- }
-
- if (negated)
- {
- if (s > bracount)
- {
- *errorcodeptr = ERR15;
- break;
- }
- s = bracount - (s - 1);
- }
-
- escape = -s;
- break;
-
- /* The handling of escape sequences consisting of a string of digits
- starting with one that is not zero is not straightforward. Perl has changed
- over the years. Nowadays \g{} for backreferences and \o{} for octal are
- recommended to avoid the ambiguities in the old syntax.
-
- Outside a character class, the digits are read as a decimal number. If the
- number is less than 8 (used to be 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. \8 and \9 are treated as the literal characters 8 and 9.
-
- Inside a character class, \ followed by a digit is always either a literal
- 8 or 9 or an octal number. */
-
- case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: case CHAR_5:
- case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:
-
- if (!isclass)
- {
- oldptr = ptr;
- /* The integer range is limited by the machine's int representation. */
- s = (int)(c -CHAR_0);
- overflow = FALSE;
- while (IS_DIGIT(ptr[1]))
- {
- if (s > INT_MAX / 10 - 1) /* Integer overflow */
- {
- overflow = TRUE;
- break;
- }
- s = s * 10 + (int)(*(++ptr) - CHAR_0);
- }
- if (overflow) /* Integer overflow */
- {
- while (IS_DIGIT(ptr[1]))
- ptr++;
- *errorcodeptr = ERR61;
- break;
- }
- if (s < 8 || s <= bracount) /* Check for back reference */
- {
- escape = -s;
- break;
- }
- ptr = oldptr; /* Put the pointer back and fall through */
- }
-
- /* Handle a digit following \ when the number is not a back reference. If
- the first digit is 8 or 9, Perl used to generate a binary zero byte and
- then treat the digit as a following literal. At least by Perl 5.18 this
- changed so as not to insert the binary zero. */
-
- if ((c = *ptr) >= CHAR_8) break;
-
- /* Fall through with a digit less than 8 */
-
- /* \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;
-
- /* \o is a relatively new Perl feature, supporting a more general way of
- specifying character codes in octal. The only supported form is \o{ddd}. */
-
- case CHAR_o:
- if (ptr[1] != CHAR_LEFT_CURLY_BRACKET) *errorcodeptr = ERR81; else
- if (ptr[2] == CHAR_RIGHT_CURLY_BRACKET) *errorcodeptr = ERR86; else
- {
- ptr += 2;
- c = 0;
- overflow = FALSE;
- while (*ptr >= CHAR_0 && *ptr <= CHAR_7)
- {
- register pcre_uint32 cc = *ptr++;
- if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */
-#ifdef COMPILE_PCRE32
- if (c >= 0x20000000l) { overflow = TRUE; break; }
-#endif
- c = (c << 3) + cc - CHAR_0 ;
-#if defined COMPILE_PCRE8
- if (c > (utf ? 0x10ffffU : 0xffU)) { overflow = TRUE; break; }
-#elif defined COMPILE_PCRE16
- if (c > (utf ? 0x10ffffU : 0xffffU)) { overflow = TRUE; break; }
-#elif defined COMPILE_PCRE32
- if (utf && c > 0x10ffffU) { overflow = TRUE; break; }
-#endif
- }
- if (overflow)
- {
- while (*ptr >= CHAR_0 && *ptr <= CHAR_7) ptr++;
- *errorcodeptr = ERR34;
- }
- else if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
- {
- if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
- }
- else *errorcodeptr = ERR80;
- }
- break;
-
- /* \x is complicated. In JavaScript, \x must be followed by two hexadecimal
- numbers. Otherwise it is a lowercase x letter. */
-
- case CHAR_x:
- if ((options & PCRE_JAVASCRIPT_COMPAT) != 0)
- {
- 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 pcre_uint32 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
- }
- }
- } /* End JavaScript handling */
-
- /* Handle \x in Perl's style. \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, { used to be treated as a data character. However, Perl
- seems to read hex digits up to the first non-such, and ignore the rest, so
- that, for example \x{zz} matches a binary zero. This seems crazy, so PCRE
- now gives an error. */
+ /* Decoded tables belong to the codes after deserialization, and they must
+ be freed when there are no more reference to them. The *ref_count should
+ always be > 0. */
- else
+ ref_count = (PCRE2_SIZE *)(code->tables + tables_length);
+ if (*ref_count > 0)
{
- if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
- {
- ptr += 2;
- if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
- {
- *errorcodeptr = ERR86;
- break;
- }
- c = 0;
- overflow = FALSE;
- while (MAX_255(*ptr) && (digitab[*ptr] & ctype_xdigit) != 0)
- {
- register pcre_uint32 cc = *ptr++;
- if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */
-
-#ifdef COMPILE_PCRE32
- if (c >= 0x10000000l) { overflow = TRUE; break; }
-#endif
-
-#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
-
-#if defined COMPILE_PCRE8
- if (c > (utf ? 0x10ffffU : 0xffU)) { overflow = TRUE; break; }
-#elif defined COMPILE_PCRE16
- if (c > (utf ? 0x10ffffU : 0xffffU)) { overflow = TRUE; break; }
-#elif defined COMPILE_PCRE32
- if (utf && c > 0x10ffffU) { overflow = TRUE; break; }
-#endif
- }
-
- if (overflow)
- {
- while (MAX_255(*ptr) && (digitab[*ptr] & ctype_xdigit) != 0) ptr++;
- *errorcodeptr = ERR34;
- }
-
- else if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
- {
- if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
- }
-
- /* If the sequence of hex digits does not end with '}', give an error.
- We used just to recognize this construct and fall through to the normal
- \x handling, but nowadays Perl gives an error, which seems much more
- sensible, so we do too. */
-
- else *errorcodeptr = ERR79;
- } /* End of \x{} processing */
-
- /* Read a single-byte hex-defined char (up to two hex digits after \x) */
-
- else
- {
- c = 0;
- while (i++ < 2 && MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0)
- {
- pcre_uint32 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
- }
- } /* End of \xdd handling */
- } /* End of Perl-style \x handling */
- 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 == CHAR_NULL)
- {
- *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;
- if (c == CHAR_QUESTION_MARK)
- c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff;
- else
- {
- for (i = 0; i < 32; i++)
- {
- if (c == ebcdic_escape_c[i]) break;
- }
- if (i < 32) c = i; else *errorcodeptr = ERR68;
+ (*ref_count)--;
+ if (*ref_count == 0)
+ code->memctl.free((void *)code->tables, code->memctl.memory_data);
}
-#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 (escape == 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 && escape >= ESC_D && escape <= ESC_w)
- escape += (ESC_DU - ESC_D);
-
-/* Set the pointer to the final character before returning. */
-
-*ptrptr = ptr;
-*chptr = c;
-return escape;
-}
-
-
-
-#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
- ptypeptr points to an unsigned int that is set to the type value
- pdataptr points to an unsigned int that is set to the detailed property value
- errorcodeptr points to the error code variable
-
-Returns: TRUE if the type value was found, or FALSE for an invalid type
-*/
-
-static BOOL
-get_ucp(const pcre_uchar **ptrptr, BOOL *negptr, unsigned int *ptypeptr,
- unsigned int *pdataptr, int *errorcodeptr)
-{
-pcre_uchar c;
-int i, bot, top;
-const pcre_uchar *ptr = *ptrptr;
-pcre_uchar name[32];
-
-c = *(++ptr);
-if (c == CHAR_NULL) 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 == CHAR_NULL) 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)
- {
- int r;
- i = (bot + top) >> 1;
- r = STRCMP_UC_C8(name, PRIV(utt_names) + PRIV(utt)[i].name_offset);
- if (r == 0)
- {
- *ptypeptr = PRIV(utt)[i].type;
- *pdataptr = PRIV(utt)[i].value;
- return TRUE;
- }
- if (r > 0) bot = i + 1; else top = i;
+ code->memctl.free(code, code->memctl.memory_data);
}
-
-*errorcodeptr = ERR47;
-*ptrptr = ptr;
-return FALSE;
-
-ERROR_RETURN:
-*errorcodeptr = ERR46;
-*ptrptr = ptr;
-return FALSE;
}
-#endif
/*************************************************
-* Read repeat counts *
+* Insert an automatic callout point *
*************************************************/
-/* 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.
+/* This function is called when the PCRE2_AUTO_CALLOUT option is set, to insert
+callout points before each pattern item.
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
+ code current code pointer
+ ptr current pattern pointer
+ cb general compile-time data
-Returns: pointer to '}' on success;
- current ptr on error, with errorcodeptr set non-zero
+Returns: new code pointer
*/
-static const pcre_uchar *
-read_repeat_counts(const pcre_uchar *p, int *minp, int *maxp, int *errorcodeptr)
+static PCRE2_UCHAR *
+auto_callout(PCRE2_UCHAR *code, PCRE2_SPTR ptr, compile_block *cb)
{
-int min = 0;
-int max = -1;
-
-while (IS_DIGIT(*p))
- {
- min = min * 10 + (int)(*p++ - CHAR_0);
- if (min > 65535)
- {
- *errorcodeptr = ERR5;
- return p;
- }
- }
-
-if (*p == CHAR_RIGHT_CURLY_BRACKET) max = min; else
- {
- if (*(++p) != CHAR_RIGHT_CURLY_BRACKET)
- {
- max = 0;
- while(IS_DIGIT(*p))
- {
- max = max * 10 + (int)(*p++ - CHAR_0);
- if (max > 65535)
- {
- *errorcodeptr = ERR5;
- return p;
- }
- }
- if (max < min)
- {
- *errorcodeptr = ERR4;
- return p;
- }
- }
- }
-
-*minp = min;
-*maxp = max;
-return p;
+code[0] = OP_CALLOUT;
+PUT(code, 1, ptr - cb->start_pattern); /* Pattern offset */
+PUT(code, 1 + LINK_SIZE, 0); /* Default length */
+code[1 + 2*LINK_SIZE] = 255;
+return code + PRIV(OP_lengths)[OP_CALLOUT];
}
/*************************************************
-* Find first significant op code *
+* Complete a callout item *
*************************************************/
-/* 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.
+/* 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:
- code pointer to the start of the group
- skipassert TRUE if certain assertions are to be skipped
+ previous_callout points to previous callout item
+ ptr current pattern pointer
+ cb general compile-time data
-Returns: pointer to the first significant opcode
+Returns: nothing
*/
-static const pcre_uchar*
-first_significant_code(const pcre_uchar *code, BOOL skipassert)
+static void
+complete_callout(PCRE2_UCHAR *previous_callout, PCRE2_SPTR ptr,
+ compile_block *cb)
{
-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_DNCREF:
- case OP_RREF:
- case OP_DNRREF:
- case OP_DEF:
- code += PRIV(OP_lengths)[*code];
- break;
-
- default:
- return code;
- }
- }
-/* Control never reaches here */
+size_t length = (size_t)(ptr - cb->start_pattern - GET(previous_callout, 1));
+PUT(previous_callout, 1 + LINK_SIZE, length);
}
@@ -1708,39 +854,77 @@ for (;;)
* 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
+/* 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 lookbehind assertions. In
+UTF mode, the result is in code units 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.
+This function is called when a lookbehind 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.
+Lookbehind lengths are held in 16-bit fields and the maximum value is defined
+as LOOKBEHIND_MAX.
+
Arguments:
- code points to the start of the pattern (the bracket)
- utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
- atend TRUE if called when the pattern is complete
- cd the "compile data" structure
+ code points to the start of the pattern (the bracket)
+ utf TRUE in UTF mode
+ atend TRUE if called when the pattern is complete
+ cb the "compile data" structure
recurses chain of recurse_check to catch mutual recursion
-
-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)
+ countptr pointer to counter, to catch over-complexity
+
+Returns: if non-negative, the fixed length,
+ or -1 if an OP_RECURSE item was encountered and atend is FALSE
+ or -2 if there is no fixed length,
+ or -3 if \C was encountered (in UTF mode only)
+ or -4 if length is too long
+ or -5 if regex is too complicated
+ or -6 if an unknown opcode was encountered (internal error)
*/
+#define FFL_LATER (-1)
+#define FFL_NOTFIXED (-2)
+#define FFL_BACKSLASHC (-3)
+#define FFL_TOOLONG (-4)
+#define FFL_TOOCOMPLICATED (-5)
+#define FFL_UNKNOWNOP (-6)
+
static int
-find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd,
- recurse_check *recurses)
+find_fixedlength(PCRE2_UCHAR *code, BOOL utf, BOOL atend, compile_block *cb,
+ recurse_check *recurses, int *countptr)
{
-int length = -1;
+uint32_t length = 0xffffffffu; /* Unset */
+uint32_t group = 0;
+uint32_t groupinfo = 0;
recurse_check this_recurse;
-register int branchlength = 0;
-register pcre_uchar *cc = code + 1 + LINK_SIZE;
+register uint32_t branchlength = 0;
+register PCRE2_UCHAR *cc = code + 1 + LINK_SIZE;
+
+/* If this is a capturing group, we may have the answer cached, but we can only
+use this information if there are no (?| groups in the pattern, because
+otherwise group numbers are not unique. */
+
+if (*code == OP_CBRA || *code == OP_CBRAPOS || *code == OP_SCBRA ||
+ *code == OP_SCBRAPOS)
+ {
+ group = GET2(cc, 0);
+ cc += IMM2_SIZE;
+ groupinfo = cb->groupinfo[group];
+ if ((cb->external_flags & PCRE2_DUPCAPUSED) == 0)
+ {
+ if ((groupinfo & GI_NOT_FIXED_LENGTH) != 0) return FFL_NOTFIXED;
+ if ((groupinfo & GI_SET_FIXED_LENGTH) != 0)
+ return groupinfo & GI_FIXED_LENGTH_MASK;
+ }
+ }
+
+/* A large and/or complex regex can take too long to process. This can happen
+more often when (?| groups are present in the pattern. */
+
+if ((*countptr)++ > 2000) return FFL_TOOCOMPLICATED;
/* 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. */
@@ -1748,8 +932,10 @@ branch, check the length against that of the other branches. */
for (;;)
{
int d;
- pcre_uchar *ce, *cs;
- register pcre_uchar op = *cc;
+ PCRE2_UCHAR *ce, *cs;
+ register PCRE2_UCHAR op = *cc;
+
+ if (branchlength > LOOKBEHIND_MAX) return FFL_TOOLONG;
switch (op)
{
@@ -1763,10 +949,9 @@ for (;;)
case OP_ONCE:
case OP_ONCE_NC:
case OP_COND:
- d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd,
- recurses);
+ d = find_fixedlength(cc, utf, atend, cb, recurses, countptr);
if (d < 0) return d;
- branchlength += d;
+ branchlength += (uint32_t)d;
do cc += GET(cc, 1); while (*cc == OP_ALT);
cc += 1 + LINK_SIZE;
break;
@@ -1782,37 +967,49 @@ for (;;)
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;
+ if (length == 0xffffffffu) length = branchlength;
+ else if (length != branchlength) goto ISNOTFIXED;
+ if (*cc != OP_ALT)
+ {
+ if (group > 0)
+ {
+ groupinfo |= (uint32_t)(GI_SET_FIXED_LENGTH | length);
+ cb->groupinfo[group] = groupinfo;
+ }
+ return (int)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. */
+ it until the end of the pattern, so return FFL_LATER. */
case OP_RECURSE:
- if (!atend) return -3;
- cs = ce = (pcre_uchar *)cd->start_code + GET(cc, 1); /* Start subpattern */
+ if (!atend) return FFL_LATER;
+ cs = ce = (PCRE2_UCHAR *)cb->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 */
+ if (cc > cs && cc < ce) goto ISNOTFIXED; /* Recursion */
else /* Check for mutual recursion */
{
recurse_check *r = recurses;
for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
- if (r != NULL) return -1; /* Mutual recursion */
+ if (r != NULL) goto ISNOTFIXED; /* Mutual recursion */
}
this_recurse.prev = recurses;
this_recurse.group = cs;
- d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd, &this_recurse);
+ d = find_fixedlength(cs, utf, atend, cb, &this_recurse, countptr);
if (d < 0) return d;
- branchlength += d;
+ branchlength += (uint32_t)d;
cc += 1 + LINK_SIZE;
break;
- /* Skip over assertive subpatterns */
+ /* Skip over assertive subpatterns. Note that we must increment cc by
+ 1 + LINK_SIZE at the end, not by OP_length[*cc] because in a recursive
+ situation this assertion may be the one that is ultimately being checked
+ for having a fixed length, in which case its terminating OP_KET will have
+ been temporarily replaced by OP_END. */
case OP_ASSERT:
case OP_ASSERT_NOT:
@@ -1837,7 +1034,8 @@ for (;;)
case OP_CLOSE:
case OP_COMMIT:
case OP_CREF:
- case OP_DEF:
+ case OP_FALSE:
+ case OP_TRUE:
case OP_DNCREF:
case OP_DNRREF:
case OP_DOLL:
@@ -1858,6 +1056,10 @@ for (;;)
cc += PRIV(OP_lengths)[*cc];
break;
+ case OP_CALLOUT_STR:
+ cc += GET(cc, 1 + 2*LINK_SIZE);
+ break;
+
/* Handle literal characters */
case OP_CHAR:
@@ -1866,7 +1068,7 @@ for (;;)
case OP_NOTI:
branchlength++;
cc += 2;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
break;
@@ -1878,9 +1080,9 @@ for (;;)
case OP_EXACTI:
case OP_NOTEXACT:
case OP_NOTEXACTI:
- branchlength += (int)GET2(cc,1);
+ branchlength += GET2(cc,1);
cc += 2 + IMM2_SIZE;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
break;
@@ -1915,17 +1117,17 @@ for (;;)
cc++;
break;
- /* The single-byte matcher isn't allowed. This only happens in UTF-8 mode;
- otherwise \C is coded as OP_ALLANY. */
+ /* The single-byte matcher isn't allowed. This only happens in UTF-8 or
+ UTF-16 mode; otherwise \C is coded as OP_ALLANY. */
case OP_ANYBYTE:
- return -2;
+ return FFL_BACKSLASHC;
/* Check a class for variable quantification */
case OP_CLASS:
case OP_NCLASS:
-#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
/* The original code caused an unsigned overflow in 64 bit systems,
so now we use a conditional statement. */
@@ -1948,13 +1150,13 @@ for (;;)
case OP_CRPOSSTAR:
case OP_CRPOSPLUS:
case OP_CRPOSQUERY:
- return -1;
+ goto ISNOTFIXED;
case OP_CRRANGE:
case OP_CRMINRANGE:
case OP_CRPOSRANGE:
- if (GET2(cc,1) != GET2(cc,1+IMM2_SIZE)) return -1;
- branchlength += (int)GET2(cc,1);
+ if (GET2(cc,1) != GET2(cc,1+IMM2_SIZE)) goto ISNOTFIXED;
+ branchlength += GET2(cc,1);
cc += 1 + 2 * IMM2_SIZE;
break;
@@ -2045,328 +1247,84 @@ for (;;)
case OP_TYPEUPTO:
case OP_UPTO:
case OP_UPTOI:
- return -1;
+ goto ISNOTFIXED;
/* Catch unrecognized opcodes so that when new ones are added they
are not forgotten, as has happened in the past. */
default:
- return -4;
+ return FFL_UNKNOWNOP;
}
}
-/* 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.
+/* Control never gets here except by goto. */
-Arguments:
- code points to start of expression
- utf TRUE in UTF-8 / UTF-16 / UTF-32 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 (;;)
+ISNOTFIXED:
+if (group > 0)
{
- register pcre_uchar c = *code;
-
- if (c == OP_END) return NULL;
-
- /* XCLASS is used for classes that cannot be represented just by a bit
- map. This includes negated single high-valued characters. 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 = (int)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:
- 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. */
-
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
- if (utf) switch(c)
- {
- case OP_CHAR:
- case OP_CHARI:
- case OP_NOT:
- case OP_NOTI:
- case OP_EXACT:
- case OP_EXACTI:
- case OP_NOTEXACT:
- case OP_NOTEXACTI:
- case OP_UPTO:
- case OP_UPTOI:
- case OP_NOTUPTO:
- case OP_NOTUPTOI:
- case OP_MINUPTO:
- case OP_MINUPTOI:
- case OP_NOTMINUPTO:
- case OP_NOTMINUPTOI:
- case OP_POSUPTO:
- case OP_POSUPTOI:
- case OP_NOTPOSUPTO:
- case OP_NOTPOSUPTOI:
- case OP_STAR:
- case OP_STARI:
- case OP_NOTSTAR:
- case OP_NOTSTARI:
- case OP_MINSTAR:
- case OP_MINSTARI:
- case OP_NOTMINSTAR:
- case OP_NOTMINSTARI:
- case OP_POSSTAR:
- case OP_POSSTARI:
- case OP_NOTPOSSTAR:
- case OP_NOTPOSSTARI:
- case OP_PLUS:
- case OP_PLUSI:
- case OP_NOTPLUS:
- case OP_NOTPLUSI:
- case OP_MINPLUS:
- case OP_MINPLUSI:
- case OP_NOTMINPLUS:
- case OP_NOTMINPLUSI:
- case OP_POSPLUS:
- case OP_POSPLUSI:
- case OP_NOTPOSPLUS:
- case OP_NOTPOSPLUSI:
- case OP_QUERY:
- case OP_QUERYI:
- case OP_NOTQUERY:
- case OP_NOTQUERYI:
- case OP_MINQUERY:
- case OP_MINQUERYI:
- case OP_NOTMINQUERY:
- case OP_NOTMINQUERYI:
- case OP_POSQUERY:
- case OP_POSQUERYI:
- case OP_NOTPOSQUERY:
- case OP_NOTPOSQUERYI:
- if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);
- break;
- }
-#else
- (void)(utf); /* Keep compiler happy by referencing function argument */
-#endif
- }
+ groupinfo |= GI_NOT_FIXED_LENGTH;
+ cb->groupinfo[group] = groupinfo;
}
+return FFL_NOTFIXED;
}
/*************************************************
-* Scan compiled regex for recursion reference *
+* Find first significant op code *
*************************************************/
-/* This little function scans through a compiled pattern until it finds an
-instance of OP_RECURSE.
+/* 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 points to start of expression
- utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
+ code pointer to the start of the group
+ skipassert TRUE if certain assertions are to be skipped
-Returns: pointer to the opcode for OP_RECURSE, or NULL if not found
+Returns: pointer to the first significant opcode
*/
-static const pcre_uchar *
-find_recurse(const pcre_uchar *code, BOOL utf)
+static const PCRE2_UCHAR*
+first_significant_code(PCRE2_SPTR code, BOOL skipassert)
{
for (;;)
{
- register pcre_uchar c = *code;
- if (c == OP_END) return NULL;
- if (c == OP_RECURSE) return code;
-
- /* XCLASS is used for classes that cannot be represented just by a bit
- map. This includes negated single high-valued characters. 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 ((int)*code)
{
- 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:
- case OP_THEN_ARG:
- code += code[1];
- break;
- }
+ 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;
- /* Add in the fixed length from the table */
+ case OP_WORD_BOUNDARY:
+ case OP_NOT_WORD_BOUNDARY:
+ if (!skipassert) return code;
+ /* Fall through */
- code += PRIV(OP_lengths)[c];
+ case OP_CALLOUT:
+ case OP_CREF:
+ case OP_DNCREF:
+ case OP_RREF:
+ case OP_DNRREF:
+ case OP_FALSE:
+ case OP_TRUE:
+ code += PRIV(OP_lengths)[*code];
+ break;
- /* 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. */
+ case OP_CALLOUT_STR:
+ code += GET(code, 1 + 2*LINK_SIZE);
+ break;
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
- if (utf) switch(c)
- {
- case OP_CHAR:
- case OP_CHARI:
- case OP_NOT:
- case OP_NOTI:
- case OP_EXACT:
- case OP_EXACTI:
- case OP_NOTEXACT:
- case OP_NOTEXACTI:
- case OP_UPTO:
- case OP_UPTOI:
- case OP_NOTUPTO:
- case OP_NOTUPTOI:
- case OP_MINUPTO:
- case OP_MINUPTOI:
- case OP_NOTMINUPTO:
- case OP_NOTMINUPTOI:
- case OP_POSUPTO:
- case OP_POSUPTOI:
- case OP_NOTPOSUPTO:
- case OP_NOTPOSUPTOI:
- case OP_STAR:
- case OP_STARI:
- case OP_NOTSTAR:
- case OP_NOTSTARI:
- case OP_MINSTAR:
- case OP_MINSTARI:
- case OP_NOTMINSTAR:
- case OP_NOTMINSTARI:
- case OP_POSSTAR:
- case OP_POSSTARI:
- case OP_NOTPOSSTAR:
- case OP_NOTPOSSTARI:
- case OP_PLUS:
- case OP_PLUSI:
- case OP_NOTPLUS:
- case OP_NOTPLUSI:
- case OP_MINPLUS:
- case OP_MINPLUSI:
- case OP_NOTMINPLUS:
- case OP_NOTMINPLUSI:
- case OP_POSPLUS:
- case OP_POSPLUSI:
- case OP_NOTPOSPLUS:
- case OP_NOTPOSPLUSI:
- case OP_QUERY:
- case OP_QUERYI:
- case OP_NOTQUERY:
- case OP_NOTQUERYI:
- case OP_MINQUERY:
- case OP_MINQUERYI:
- case OP_NOTMINQUERY:
- case OP_NOTMINQUERYI:
- case OP_POSQUERY:
- case OP_POSQUERYI:
- case OP_NOTPOSQUERY:
- case OP_NOTPOSQUERYI:
- if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);
- break;
- }
-#else
- (void)(utf); /* Keep compiler happy by referencing function argument */
-#endif
+ default:
+ return code;
}
}
+/* Control never reaches here */
}
@@ -2376,35 +1334,77 @@ for (;;)
*************************************************/
/* 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.
+can match the empty string. It is called at the end of compiling to check the
+entire pattern, and from compile_branch() when checking for an unlimited repeat
+of a group that can match nothing. In the latter case it is called only when
+doing the real compile, not during the pre-compile that measures the size of
+the compiled pattern.
+
+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 / UTF-32 mode
- cd contains pointers to tables etc.
+ utf TRUE if in UTF mode
+ cb compile data
+ atend TRUE if being called to check an entire pattern
recurses chain of recurse_check to catch mutual recursion
+ countptr pointer to count to catch over-complicated pattern
-Returns: TRUE if what is matched could be empty
+Returns: 0 if what is matched cannot be empty
+ 1 if what is matched could be empty
+ -1 if the pattern is too complicated
*/
-static BOOL
-could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode,
- BOOL utf, compile_data *cd, recurse_check *recurses)
+#define CBE_NOTEMPTY 0
+#define CBE_EMPTY 1
+#define CBE_TOOCOMPLICATED (-1)
+
+
+static int
+could_be_empty_branch(PCRE2_SPTR code, PCRE2_SPTR endcode, BOOL utf,
+ compile_block *cb, BOOL atend, recurse_check *recurses, int *countptr)
{
-register pcre_uchar c;
+uint32_t group = 0;
+uint32_t groupinfo = 0;
+register PCRE2_UCHAR c;
recurse_check this_recurse;
+/* If what we are checking has already been set as "could be empty", we know
+the answer. */
+
+if (*code >= OP_SBRA && *code <= OP_SCOND) return CBE_EMPTY;
+
+/* If this is a capturing group, we may have the answer cached, but we can only
+use this information if there are no (?| groups in the pattern, because
+otherwise group numbers are not unique. */
+
+if ((cb->external_flags & PCRE2_DUPCAPUSED) == 0 &&
+ (*code == OP_CBRA || *code == OP_CBRAPOS))
+ {
+ group = GET2(code, 1 + LINK_SIZE);
+ groupinfo = cb->groupinfo[group];
+ if ((groupinfo & GI_SET_COULD_BE_EMPTY) != 0)
+ return ((groupinfo & GI_COULD_BE_EMPTY) != 0)? CBE_EMPTY : CBE_NOTEMPTY;
+ }
+
+/* A large and/or complex regex can take too long to process. We have to assume
+it can match an empty string. This can happen more often when (?| groups are
+present in the pattern and the caching is disabled. Setting the cap at 1100
+allows the test for more than 1023 capturing patterns to work. */
+
+if ((*countptr)++ > 1100) return CBE_TOOCOMPLICATED;
+
+/* Scan the opcodes for this branch. */
+
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;
+ PCRE2_SPTR ccode;
c = *code;
@@ -2418,35 +1418,27 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
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. */
+ /* For a recursion/subroutine call we can scan the recursion when this
+ function is called at the end, to check a complete pattern. Before then,
+ recursions just have the group number as their argument and in any case may
+ be forward references. In that situation, we return CBE_EMPTY, just in case.
+ It means that unlimited repeats of groups that contain recursions are always
+ treated as "could be empty" - which just adds a bit more processing time
+ because of the runtime check. */
if (c == OP_RECURSE)
{
- const pcre_uchar *scode = cd->start_code + GET(code, 1);
- const pcre_uchar *endgroup = scode;
+ PCRE2_SPTR scode, endgroup;
BOOL empty_branch;
- /* Test for forward reference or uncompleted reference. This is disabled
- when called to scan a completed pattern by setting cd->start_workspace to
- NULL. */
-
- if (cd->start_workspace != NULL)
- {
- const pcre_uchar *tcode;
- for (tcode = cd->start_workspace; tcode < cd->hwm; tcode += LINK_SIZE)
- if ((int)GET(tcode, 0) == (int)(code + 1 - cd->start_code)) return TRUE;
- if (GET(scode, 1) == 0) return TRUE; /* Unclosed */
- }
+ if (!atend) goto ISTRUE;
+ scode = cb->start_code + GET(code, 1);
+ endgroup = scode;
- /* If the reference is to a completed group, we need to detect whether this
- is a recursive call, as otherwise there will be an infinite loop. If it is
- a recursion, just skip over it. Simple recursions are easily detected. For
- mutual recursions we keep a chain on the stack. */
+ /* We need to detect whether this is a recursive call, as otherwise there
+ will be an infinite loop. If it is a recursion, just skip over it. Simple
+ recursions are easily detected. For mutual recursions we keep a chain on
+ the stack. */
do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT);
if (code >= scode && code <= endgroup) continue; /* Simple recursion */
@@ -2458,8 +1450,8 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
if (r != NULL) continue; /* Mutual recursion */
}
- /* Completed reference; scan the referenced group, remembering it on the
- stack chain to detect mutual recursions. */
+ /* Scan the referenced group, remembering it on the stack chain to detect
+ mutual recursions. */
empty_branch = FALSE;
this_recurse.prev = recurses;
@@ -2467,7 +1459,10 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
do
{
- if (could_be_empty_branch(scode, endcode, utf, cd, &this_recurse))
+ int rc = could_be_empty_branch(scode, endcode, utf, cb, atend,
+ &this_recurse, countptr);
+ if (rc < 0) return rc;
+ if (rc > 0)
{
empty_branch = TRUE;
break;
@@ -2476,7 +1471,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
}
while (*scode == OP_ALT);
- if (!empty_branch) return FALSE; /* All branches are non-empty */
+ if (!empty_branch) goto ISFALSE; /* All branches are non-empty */
continue;
}
@@ -2510,7 +1505,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
c == OP_COND || c == OP_SCOND)
{
BOOL empty_branch;
- if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */
+ if (GET(code, 1) == 0) goto ISTRUE; /* 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.
@@ -2523,12 +1518,17 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
empty_branch = FALSE;
do
{
- if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd,
- recurses)) empty_branch = TRUE;
+ if (!empty_branch)
+ {
+ int rc = could_be_empty_branch(code, endcode, utf, cb, atend,
+ recurses, countptr);
+ if (rc < 0) return rc;
+ if (rc > 0) empty_branch = TRUE;
+ }
code += GET(code, 1);
}
while (*code == OP_ALT);
- if (!empty_branch) return FALSE; /* All branches are non-empty */
+ if (!empty_branch) goto ISFALSE; /* All branches are non-empty */
}
c = *code;
@@ -2545,7 +1545,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
actual length is stored in the compiled code, so we must update "code"
here. */
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
case OP_XCLASS:
ccode = code += GET(code, 1);
goto CHECK_CLASS_REPEAT;
@@ -2555,7 +1555,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
case OP_NCLASS:
ccode = code + PRIV(OP_lengths)[OP_CLASS];
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
CHECK_CLASS_REPEAT:
#endif
@@ -2573,12 +1573,12 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
case OP_CRPLUS: /* These repeats aren't empty */
case OP_CRMINPLUS:
case OP_CRPOSPLUS:
- return FALSE;
+ goto ISFALSE;
case OP_CRRANGE:
case OP_CRMINRANGE:
case OP_CRPOSRANGE:
- if (GET2(ccode, 1) > 0) return FALSE; /* Minimum > 0 */
+ if (GET2(ccode, 1) > 0) goto ISFALSE; /* Minimum > 0 */
break;
}
break;
@@ -2635,8 +1635,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
case OP_TYPEMINPLUS:
case OP_TYPEPOSPLUS:
case OP_TYPEEXACT:
-
- return FALSE;
+ goto ISFALSE;
/* These are going to continue, as they may be empty, but we have to
fudge the length for the \p and \P cases. */
@@ -2666,13 +1665,13 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
case OP_KETRMIN:
case OP_KETRPOS:
case OP_ALT:
- return TRUE;
+ goto ISTRUE;
- /* In UTF-8 mode, STAR, MINSTAR, POSSTAR, QUERY, MINQUERY, POSQUERY, UPTO,
- MINUPTO, and POSUPTO and their caseless and negative versions may be
- followed by a multibyte character. */
+ /* In UTF-8 or UTF-16 mode, STAR, MINSTAR, POSSTAR, QUERY, MINQUERY,
+ POSQUERY, UPTO, MINUPTO, and POSUPTO and their caseless and negative
+ versions may be followed by a multibyte character. */
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#ifdef MAYBE_UTF_MULTI
case OP_STAR:
case OP_STARI:
case OP_NOTSTAR:
@@ -2702,7 +1701,6 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
case OP_POSQUERYI:
case OP_NOTPOSQUERY:
case OP_NOTPOSQUERYI:
-
if (utf && HAS_EXTRALEN(code[1])) code += GET_EXTRALEN(code[1]);
break;
@@ -2720,10 +1718,9 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
case OP_POSUPTOI:
case OP_NOTPOSUPTO:
case OP_NOTPOSUPTOI:
-
if (utf && HAS_EXTRALEN(code[1 + IMM2_SIZE])) code += GET_EXTRALEN(code[1 + IMM2_SIZE]);
break;
-#endif
+#endif /* MAYBE_UTF_MULTI */
/* MARK, and PRUNE/SKIP/THEN with an argument must skip over the argument
string. */
@@ -2742,1147 +1739,869 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
}
}
-return TRUE;
+ISTRUE:
+groupinfo |= GI_COULD_BE_EMPTY;
+
+ISFALSE:
+if (group > 0) cb->groupinfo[group] = groupinfo | GI_SET_COULD_BE_EMPTY;
+
+return ((groupinfo & GI_COULD_BE_EMPTY) != 0)? CBE_EMPTY : CBE_NOTEMPTY;
}
/*************************************************
-* Scan compiled regex for non-emptiness *
+* Check for counted repeat *
*************************************************/
-/* 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 / UTF-32 mode
- cd pointers to tables etc
+/* 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, that
+is, one of the forms {ddd} {ddd,} or {ddd,ddd} where the ddds are digits.
-Returns: TRUE if what is matched could be empty
+Argument: pointer to the first char after '{'
+Returns: TRUE or FALSE
*/
static BOOL
-could_be_empty(const pcre_uchar *code, const pcre_uchar *endcode,
- branch_chain *bcptr, BOOL utf, compile_data *cd)
+is_counted_repeat(PCRE2_SPTR p)
{
-while (bcptr != NULL && bcptr->current_branch >= code)
- {
- if (!could_be_empty_branch(bcptr->current_branch, endcode, utf, cd, NULL))
- return FALSE;
- bcptr = bcptr->outer;
- }
-return TRUE;
-}
-
-
-
-/*************************************************
-* Base opcode of repeated opcodes *
-*************************************************/
+if (!IS_DIGIT(*p)) return FALSE;
+p++;
+while (IS_DIGIT(*p)) p++;
+if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE;
-/* Returns the base opcode for repeated single character type opcodes. If the
-opcode is not a repeated character type, it returns with the original value.
+if (*p++ != CHAR_COMMA) return FALSE;
+if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE;
-Arguments: c opcode
-Returns: base opcode for the type
-*/
+if (!IS_DIGIT(*p)) return FALSE;
+p++;
+while (IS_DIGIT(*p)) p++;
-static pcre_uchar
-get_repeat_base(pcre_uchar c)
-{
-return (c > OP_TYPEPOSUPTO)? c :
- (c >= OP_TYPESTAR)? OP_TYPESTAR :
- (c >= OP_NOTSTARI)? OP_NOTSTARI :
- (c >= OP_NOTSTAR)? OP_NOTSTAR :
- (c >= OP_STARI)? OP_STARI :
- OP_STAR;
+return (*p == CHAR_RIGHT_CURLY_BRACKET);
}
-#ifdef SUPPORT_UCP
/*************************************************
-* Check a character and a property *
+* Handle escapes *
*************************************************/
-/* This function is called by check_auto_possessive() when a property item
-is adjacent to a fixed character.
+/* This function is called when a \ has been encountered. It either returns a
+positive value for a simple escape such as \d, or 0 for a data character, which
+is placed in chptr. A backreference to group n is returned as negative n. On
+entry, ptr is pointing at the \. On exit, it points the final code unit of the
+escape sequence.
+
+This function is also called from pcre2_substitute() to handle escape sequences
+in replacement strings. In this case, the cb argument is NULL, and only
+sequences that define a data character are recognised. The isclass argument is
+not relevant, but the options argument is the final value of the compiled
+pattern's options.
+
+There is one "trick" case: when a sequence such as [[:>:]] or \s in UCP mode is
+processed, it is replaced by a nested alternative sequence. If this contains a
+backslash (which is usually does), ptrend does not point to its end - it still
+points to the end of the whole pattern. However, we can detect this case
+because cb->nestptr[0] will be non-NULL. The nested sequences are all zero-
+terminated and there are only ever two levels of nesting.
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{^)
+ ptrptr points to the input position pointer
+ ptrend points to the end of the input
+ chptr points to a returned data character
+ errorcodeptr points to the errorcode variable (containing zero)
+ options the current options bits
+ isclass TRUE if inside a character class
+ cb compile data block
-Returns: TRUE if auto-possessifying is OK
+Returns: zero => a data character
+ positive => a special escape sequence
+ negative => a back reference
+ on error, errorcodeptr is set non-zero
*/
-static BOOL
-check_char_prop(pcre_uint32 c, unsigned int ptype, unsigned int pdata,
- BOOL negated)
+int
+PRIV(check_escape)(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t *chptr,
+ int *errorcodeptr, uint32_t options, BOOL isclass, compile_block *cb)
{
-const pcre_uint32 *p;
-const ucd_record *prop = GET_UCD(c);
-
-switch(ptype)
- {
- case PT_LAMP:
- return (prop->chartype == ucp_Lu ||
- prop->chartype == ucp_Ll ||
- prop->chartype == ucp_Lt) == negated;
-
- case PT_GC:
- return (pdata == PRIV(ucp_gentype)[prop->chartype]) == negated;
-
- case PT_PC:
- return (pdata == prop->chartype) == negated;
-
- case PT_SC:
- return (pdata == prop->script) == negated;
-
- /* These are specials */
-
- case PT_ALNUM:
- return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
- PRIV(ucp_gentype)[prop->chartype] == ucp_N) == negated;
-
- /* Perl space used to exclude VT, but from Perl 5.18 it is included, which
- means that Perl space and POSIX space are now identical. PCRE was changed
- at release 8.34. */
+BOOL utf = (options & PCRE2_UTF) != 0;
+PCRE2_SPTR ptr = *ptrptr + 1;
+register uint32_t c, cc;
+int escape = 0;
+int i;
- case PT_SPACE: /* Perl space */
- case PT_PXSPACE: /* POSIX space */
- switch(c)
- {
- HSPACE_CASES:
- VSPACE_CASES:
- return negated;
+/* Find the end of a nested insert. */
- default:
- return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated;
- }
- break; /* Control never reaches here */
+if (cb != NULL && cb->nestptr[0] != NULL)
+ ptrend = ptr + PRIV(strlen)(ptr);
- case PT_WORD:
- return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
- PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
- c == CHAR_UNDERSCORE) == negated;
+/* If backslash is at the end of the string, it's an error. */
- case PT_CLIST:
- p = PRIV(ucd_caseless_sets) + prop->caseset;
- for (;;)
- {
- if (c < *p) return !negated;
- if (c == *p++) return negated;
- }
- break; /* Control never reaches here */
+if (ptr >= ptrend)
+ {
+ *errorcodeptr = ERR1;
+ return 0;
}
-return FALSE;
-}
-#endif /* SUPPORT_UCP */
-
-
-
-/*************************************************
-* Fill the character property list *
-*************************************************/
-
-/* Checks whether the code points to an opcode that can take part in auto-
-possessification, and if so, fills a list with its properties.
-
-Arguments:
- code points to start of expression
- utf TRUE if in UTF-8 / UTF-16 / UTF-32 mode
- fcc points to case-flipping table
- list points to output list
- list[0] will be filled with the opcode
- list[1] will be non-zero if this opcode
- can match an empty character string
- list[2..7] depends on the opcode
-
-Returns: points to the start of the next opcode if *code is accepted
- NULL if *code is not accepted
-*/
+GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */
+ptr--; /* Set pointer back to the last code unit */
-static const pcre_uchar *
-get_chr_property_list(const pcre_uchar *code, BOOL utf,
- const pcre_uint8 *fcc, pcre_uint32 *list)
-{
-pcre_uchar c = *code;
-pcre_uchar base;
-const pcre_uchar *end;
-pcre_uint32 chr;
-
-#ifdef SUPPORT_UCP
-pcre_uint32 *clist_dest;
-const pcre_uint32 *clist_src;
-#else
-utf = utf; /* Suppress "unused parameter" compiler warning */
-#endif
+/* Non-alphanumerics are literals, so we just leave the value in c. An initial
+value test saves a memory lookup for code points outside the alphanumeric
+range. Otherwise, do a table lookup. A non-zero result is something that can be
+returned immediately. Otherwise further processing is required. */
-list[0] = c;
-list[1] = FALSE;
-code++;
+if (c < ESCAPES_FIRST || c > ESCAPES_LAST) {} /* Definitely literal */
-if (c >= OP_STAR && c <= OP_TYPEPOSUPTO)
+else if ((i = escapes[c - ESCAPES_FIRST]) != 0)
{
- base = get_repeat_base(c);
- c -= (base - OP_STAR);
-
- if (c == OP_UPTO || c == OP_MINUPTO || c == OP_EXACT || c == OP_POSUPTO)
- code += IMM2_SIZE;
-
- list[1] = (c != OP_PLUS && c != OP_MINPLUS && c != OP_EXACT && c != OP_POSPLUS);
-
- switch(base)
+ if (i > 0) c = (uint32_t)i; else /* Positive is a data character */
{
- case OP_STAR:
- list[0] = OP_CHAR;
- break;
-
- case OP_STARI:
- list[0] = OP_CHARI;
- break;
-
- case OP_NOTSTAR:
- list[0] = OP_NOT;
- break;
-
- case OP_NOTSTARI:
- list[0] = OP_NOTI;
- break;
-
- case OP_TYPESTAR:
- list[0] = *code;
- code++;
- break;
+ escape = -i; /* Else return a special escape */
+ if (escape == ESC_P || escape == ESC_p || escape == ESC_X)
+ cb->external_flags |= PCRE2_HASBKPORX; /* Note \P, \p, or \X */
}
- c = list[0];
}
-switch(c)
- {
- case OP_NOT_DIGIT:
- case OP_DIGIT:
- case OP_NOT_WHITESPACE:
- case OP_WHITESPACE:
- case OP_NOT_WORDCHAR:
- case OP_WORDCHAR:
- case OP_ANY:
- case OP_ALLANY:
- case OP_ANYNL:
- case OP_NOT_HSPACE:
- case OP_HSPACE:
- case OP_NOT_VSPACE:
- case OP_VSPACE:
- case OP_EXTUNI:
- case OP_EODN:
- case OP_EOD:
- case OP_DOLL:
- case OP_DOLLM:
- return code;
-
- case OP_CHAR:
- case OP_NOT:
- GETCHARINCTEST(chr, code);
- list[2] = chr;
- list[3] = NOTACHAR;
- return code;
-
- case OP_CHARI:
- case OP_NOTI:
- list[0] = (c == OP_CHARI) ? OP_CHAR : OP_NOT;
- GETCHARINCTEST(chr, code);
- list[2] = chr;
-
-#ifdef SUPPORT_UCP
- if (chr < 128 || (chr < 256 && !utf))
- list[3] = fcc[chr];
- else
- list[3] = UCD_OTHERCASE(chr);
-#elif defined SUPPORT_UTF || !defined COMPILE_PCRE8
- list[3] = (chr < 256) ? fcc[chr] : chr;
-#else
- list[3] = fcc[chr];
-#endif
+/* Escapes that need further processing, including those that are unknown.
+When called from pcre2_substitute(), only \c, \o, and \x are recognized (and \u
+when BSUX is set). */
- /* The othercase might be the same value. */
+else
+ {
+ PCRE2_SPTR oldptr;
+ BOOL braced, negated, overflow;
+ unsigned int s;
- if (chr == list[3])
- list[3] = NOTACHAR;
- else
- list[4] = NOTACHAR;
- return code;
+ /* Filter calls from pcre2_substitute(). */
-#ifdef SUPPORT_UCP
- case OP_PROP:
- case OP_NOTPROP:
- if (code[0] != PT_CLIST)
+ if (cb == NULL && c != CHAR_c && c != CHAR_o && c != CHAR_x &&
+ (c != CHAR_u || (options & PCRE2_ALT_BSUX) != 0))
{
- list[2] = code[0];
- list[3] = code[1];
- return code + 2;
+ *errorcodeptr = ERR3;
+ return 0;
}
- /* Convert only if we have enough space. */
-
- clist_src = PRIV(ucd_caseless_sets) + code[1];
- clist_dest = list + 2;
- code += 2;
-
- do {
- if (clist_dest >= list + 8)
- {
- /* Early return if there is not enough space. This should never
- happen, since all clists are shorter than 5 character now. */
- list[2] = code[0];
- list[3] = code[1];
- return code;
- }
- *clist_dest++ = *clist_src;
- }
- while(*clist_src++ != NOTACHAR);
-
- /* All characters are stored. The terminating NOTACHAR
- is copied form the clist itself. */
-
- list[0] = (c == OP_PROP) ? OP_CHAR : OP_NOT;
- return code;
-#endif
-
- case OP_NCLASS:
- case OP_CLASS:
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
- case OP_XCLASS:
- if (c == OP_XCLASS)
- end = code + GET(code, 0) - 1;
- else
-#endif
- end = code + 32 / sizeof(pcre_uchar);
-
- switch(*end)
+ switch (c)
{
- case OP_CRSTAR:
- case OP_CRMINSTAR:
- case OP_CRQUERY:
- case OP_CRMINQUERY:
- case OP_CRPOSSTAR:
- case OP_CRPOSQUERY:
- list[1] = TRUE;
- end++;
- break;
-
- case OP_CRPLUS:
- case OP_CRMINPLUS:
- case OP_CRPOSPLUS:
- end++;
- break;
+ /* A number of Perl escapes are not handled by PCRE. We give an explicit
+ error. */
- case OP_CRRANGE:
- case OP_CRMINRANGE:
- case OP_CRPOSRANGE:
- list[1] = (GET2(end, 1) == 0);
- end += 1 + 2 * IMM2_SIZE;
+ case CHAR_l:
+ case CHAR_L:
+ *errorcodeptr = ERR37;
break;
- }
- list[2] = (pcre_uint32)(end - code);
- return end;
- }
-return NULL; /* Opcode not accepted */
-}
-
-
-
-/*************************************************
-* Scan further character sets for match *
-*************************************************/
-/* Checks whether the base and the current opcode have a common character, in
-which case the base cannot be possessified.
+ /* \u is unrecognized when PCRE2_ALT_BSUX is not set. When it is treated
+ specially, \u must be followed by four hex digits. Otherwise it is a
+ lowercase u letter. */
-Arguments:
- code points to the byte code
- utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
- cd static compile data
- base_list the data list of the base opcode
-
-Returns: TRUE if the auto-possessification is possible
-*/
-
-static BOOL
-compare_opcodes(const pcre_uchar *code, BOOL utf, const compile_data *cd,
- const pcre_uint32 *base_list, const pcre_uchar *base_end, int *rec_limit)
-{
-pcre_uchar c;
-pcre_uint32 list[8];
-const pcre_uint32 *chr_ptr;
-const pcre_uint32 *ochr_ptr;
-const pcre_uint32 *list_ptr;
-const pcre_uchar *next_code;
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
-const pcre_uchar *xclass_flags;
-#endif
-const pcre_uint8 *class_bitset;
-const pcre_uint8 *set1, *set2, *set_end;
-pcre_uint32 chr;
-BOOL accepted, invert_bits;
-BOOL entered_a_group = FALSE;
-
-if (*rec_limit == 0) return FALSE;
---(*rec_limit);
-
-/* Note: the base_list[1] contains whether the current opcode has greedy
-(represented by a non-zero value) quantifier. This is a different from
-other character type lists, which stores here that the character iterator
-matches to an empty string (also represented by a non-zero value). */
-
-for(;;)
- {
- /* All operations move the code pointer forward.
- Therefore infinite recursions are not possible. */
-
- c = *code;
-
- /* Skip over callouts */
-
- if (c == OP_CALLOUT)
- {
- code += PRIV(OP_lengths)[c];
- continue;
- }
+ case CHAR_u:
+ if ((options & PCRE2_ALT_BSUX) == 0) *errorcodeptr = ERR37; else
+ {
+ uint32_t xc;
+ if ((cc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */
+ if ((xc = XDIGIT(ptr[2])) == 0xff) break; /* Not a hex digit */
+ cc = (cc << 4) | xc;
+ if ((xc = XDIGIT(ptr[3])) == 0xff) break; /* Not a hex digit */
+ cc = (cc << 4) | xc;
+ if ((xc = XDIGIT(ptr[4])) == 0xff) break; /* Not a hex digit */
+ c = (cc << 4) | xc;
+ ptr += 4;
+ if (utf)
+ {
+ if (c > 0x10ffffU) *errorcodeptr = ERR77;
+ else if (c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
+ }
+ else if (c > MAX_NON_UTF_CHAR) *errorcodeptr = ERR77;
+ }
+ break;
- if (c == OP_ALT)
- {
- do code += GET(code, 1); while (*code == OP_ALT);
- c = *code;
- }
+ case CHAR_U:
+ /* \U is unrecognized unless PCRE2_ALT_BSUX is set, in which case it is an
+ upper case letter. */
+ if ((options & PCRE2_ALT_BSUX) == 0) *errorcodeptr = ERR37;
+ break;
- switch(c)
- {
- case OP_END:
- case OP_KETRPOS:
- /* TRUE only in greedy case. The non-greedy case could be replaced by
- an OP_EXACT, but it is probably not worth it. (And note that OP_EXACT
- uses more memory, which we cannot get at this stage.) */
+ /* 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:
- return base_list[1] != 0;
+ (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.
- case OP_KET:
- /* If the bracket is capturing, and referenced by an OP_RECURSE, or
- it is an atomic sub-pattern (assert, once, etc.) the non-greedy case
- cannot be converted to a possessive form. */
+ (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.
- if (base_list[1] == 0) return FALSE;
+ (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). */
- switch(*(code - GET(code, 1)))
+ case CHAR_g:
+ if (isclass) break;
+ if (ptr[1] == CHAR_LESS_THAN_SIGN || ptr[1] == CHAR_APOSTROPHE)
{
- case OP_ASSERT:
- case OP_ASSERT_NOT:
- case OP_ASSERTBACK:
- case OP_ASSERTBACK_NOT:
- case OP_ONCE:
- case OP_ONCE_NC:
- /* Atomic sub-patterns and assertions can always auto-possessify their
- last iterator. However, if the group was entered as a result of checking
- a previous iterator, this is not possible. */
-
- return !entered_a_group;
+ escape = ESC_g;
+ break;
}
- code += PRIV(OP_lengths)[c];
- continue;
-
- case OP_ONCE:
- case OP_ONCE_NC:
- case OP_BRA:
- case OP_CBRA:
- next_code = code + GET(code, 1);
- code += PRIV(OP_lengths)[c];
+ /* Handle the Perl-compatible cases */
- while (*next_code == OP_ALT)
+ if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
{
- if (!compare_opcodes(code, utf, cd, base_list, base_end, rec_limit))
- return FALSE;
- code = next_code + 1 + LINK_SIZE;
- next_code += GET(next_code, 1);
+ PCRE2_SPTR p;
+ for (p = ptr+2; *p != CHAR_NULL && *p != CHAR_RIGHT_CURLY_BRACKET; p++)
+ if (*p != CHAR_MINUS && !IS_DIGIT(*p)) break;
+ if (*p != CHAR_NULL && *p != CHAR_RIGHT_CURLY_BRACKET)
+ {
+ escape = ESC_k;
+ break;
+ }
+ braced = TRUE;
+ ptr++;
}
+ else braced = FALSE;
- entered_a_group = TRUE;
- continue;
-
- case OP_BRAZERO:
- case OP_BRAMINZERO:
-
- next_code = code + 1;
- if (*next_code != OP_BRA && *next_code != OP_CBRA
- && *next_code != OP_ONCE && *next_code != OP_ONCE_NC) return FALSE;
-
- do next_code += GET(next_code, 1); while (*next_code == OP_ALT);
-
- /* The bracket content will be checked by the
- OP_BRA/OP_CBRA case above. */
- next_code += 1 + LINK_SIZE;
- if (!compare_opcodes(next_code, utf, cd, base_list, base_end, rec_limit))
- return FALSE;
-
- code += PRIV(OP_lengths)[c];
- continue;
-
- default:
- break;
- }
-
- /* Check for a supported opcode, and load its properties. */
-
- code = get_chr_property_list(code, utf, cd->fcc, list);
- if (code == NULL) return FALSE; /* Unsupported */
-
- /* If either opcode is a small character list, set pointers for comparing
- characters from that list with another list, or with a property. */
-
- if (base_list[0] == OP_CHAR)
- {
- chr_ptr = base_list + 2;
- list_ptr = list;
- }
- else if (list[0] == OP_CHAR)
- {
- chr_ptr = list + 2;
- list_ptr = base_list;
- }
-
- /* Character bitsets can also be compared to certain opcodes. */
-
- else if (base_list[0] == OP_CLASS || list[0] == OP_CLASS
-#ifdef COMPILE_PCRE8
- /* In 8 bit, non-UTF mode, OP_CLASS and OP_NCLASS are the same. */
- || (!utf && (base_list[0] == OP_NCLASS || list[0] == OP_NCLASS))
-#endif
- )
- {
-#ifdef COMPILE_PCRE8
- if (base_list[0] == OP_CLASS || (!utf && base_list[0] == OP_NCLASS))
-#else
- if (base_list[0] == OP_CLASS)
-#endif
- {
- set1 = (pcre_uint8 *)(base_end - base_list[2]);
- list_ptr = list;
- }
- else
+ if (ptr[1] == CHAR_MINUS)
{
- set1 = (pcre_uint8 *)(code - list[2]);
- list_ptr = base_list;
+ negated = TRUE;
+ ptr++;
}
+ else negated = FALSE;
- invert_bits = FALSE;
- switch(list_ptr[0])
+ /* The integer range is limited by the machine's int representation. */
+ s = 0;
+ overflow = FALSE;
+ while (IS_DIGIT(ptr[1]))
{
- case OP_CLASS:
- case OP_NCLASS:
- set2 = (pcre_uint8 *)
- ((list_ptr == list ? code : base_end) - list_ptr[2]);
- break;
-
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
- case OP_XCLASS:
- xclass_flags = (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE;
- if ((*xclass_flags & XCL_HASPROP) != 0) return FALSE;
- if ((*xclass_flags & XCL_MAP) == 0)
+ if (s > INT_MAX / 10 - 1) /* Integer overflow */
{
- /* No bits are set for characters < 256. */
- if (list[1] == 0) return TRUE;
- /* Might be an empty repeat. */
- continue;
+ overflow = TRUE;
+ break;
}
- set2 = (pcre_uint8 *)(xclass_flags + 1);
- break;
-#endif
-
- case OP_NOT_DIGIT:
- invert_bits = TRUE;
- /* Fall through */
- case OP_DIGIT:
- set2 = (pcre_uint8 *)(cd->cbits + cbit_digit);
- break;
-
- case OP_NOT_WHITESPACE:
- invert_bits = TRUE;
- /* Fall through */
- case OP_WHITESPACE:
- set2 = (pcre_uint8 *)(cd->cbits + cbit_space);
+ s = s * 10 + (unsigned int)(*(++ptr) - CHAR_0);
+ }
+ if (overflow) /* Integer overflow */
+ {
+ while (IS_DIGIT(ptr[1])) ptr++;
+ *errorcodeptr = ERR61;
break;
+ }
- case OP_NOT_WORDCHAR:
- invert_bits = TRUE;
- /* Fall through */
- case OP_WORDCHAR:
- set2 = (pcre_uint8 *)(cd->cbits + cbit_word);
+ if (braced && *(++ptr) != CHAR_RIGHT_CURLY_BRACKET)
+ {
+ *errorcodeptr = ERR57;
break;
-
- default:
- return FALSE;
}
- /* Because the sets are unaligned, we need
- to perform byte comparison here. */
- set_end = set1 + 32;
- if (invert_bits)
+ if (s == 0)
{
- do
- {
- if ((*set1++ & ~(*set2++)) != 0) return FALSE;
- }
- while (set1 < set_end);
+ *errorcodeptr = ERR58;
+ break;
}
- else
+
+ if (negated)
{
- do
+ if (s > cb->bracount)
{
- if ((*set1++ & *set2++) != 0) return FALSE;
+ *errorcodeptr = ERR15;
+ break;
}
- while (set1 < set_end);
+ s = cb->bracount - (s - 1);
}
- if (list[1] == 0) return TRUE;
- /* Might be an empty repeat. */
- continue;
- }
+ escape = -(int)s;
+ break;
- /* Some property combinations also acceptable. Unicode property opcodes are
- processed specially; the rest can be handled with a lookup table. */
+ /* The handling of escape sequences consisting of a string of digits
+ starting with one that is not zero is not straightforward. Perl has changed
+ over the years. Nowadays \g{} for backreferences and \o{} for octal are
+ recommended to avoid the ambiguities in the old syntax.
- else
- {
- pcre_uint32 leftop, rightop;
+ Outside a character class, the digits are read as a decimal number. If the
+ number is less than 10, or if there are that many previous extracting left
+ brackets, it is a back reference. Otherwise, up to three octal digits are
+ read to form an escaped character code. Thus \123 is likely to be octal 123
+ (cf \0123, which is octal 012 followed by the literal 3).
- leftop = base_list[0];
- rightop = list[0];
+ Inside a character class, \ followed by a digit is always either a literal
+ 8 or 9 or an octal number. */
+
+ case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: case CHAR_5:
+ case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:
-#ifdef SUPPORT_UCP
- accepted = FALSE; /* Always set in non-unicode case. */
- if (leftop == OP_PROP || leftop == OP_NOTPROP)
+ if (!isclass)
{
- if (rightop == OP_EOD)
- accepted = TRUE;
- else if (rightop == OP_PROP || rightop == OP_NOTPROP)
+ oldptr = ptr;
+ /* The integer range is limited by the machine's int representation. */
+ s = c - CHAR_0;
+ overflow = FALSE;
+ while (IS_DIGIT(ptr[1]))
{
- int n;
- const pcre_uint8 *p;
- BOOL same = leftop == rightop;
- BOOL lisprop = leftop == OP_PROP;
- BOOL risprop = rightop == OP_PROP;
- BOOL bothprop = lisprop && risprop;
-
- /* There's a table that specifies how each combination is to be
- processed:
- 0 Always return FALSE (never auto-possessify)
- 1 Character groups are distinct (possessify if both are OP_PROP)
- 2 Check character categories in the same group (general or particular)
- 3 Return TRUE if the two opcodes are not the same
- ... see comments below
- */
-
- n = propposstab[base_list[2]][list[2]];
- switch(n)
+ if (s > INT_MAX / 10 - 1) /* Integer overflow */
{
- case 0: break;
- case 1: accepted = bothprop; break;
- case 2: accepted = (base_list[3] == list[3]) != same; break;
- case 3: accepted = !same; break;
-
- case 4: /* Left general category, right particular category */
- accepted = risprop && catposstab[base_list[3]][list[3]] == same;
- break;
-
- case 5: /* Right general category, left particular category */
- accepted = lisprop && catposstab[list[3]][base_list[3]] == same;
- break;
-
- /* This code is logically tricky. Think hard before fiddling with it.
- The posspropstab table has four entries per row. Each row relates to
- one of PCRE's special properties such as ALNUM or SPACE or WORD.
- Only WORD actually needs all four entries, but using repeats for the
- others means they can all use the same code below.
-
- The first two entries in each row are Unicode general categories, and
- apply always, because all the characters they include are part of the
- PCRE character set. The third and fourth entries are a general and a
- particular category, respectively, that include one or more relevant
- characters. One or the other is used, depending on whether the check
- is for a general or a particular category. However, in both cases the
- category contains more characters than the specials that are defined
- for the property being tested against. Therefore, it cannot be used
- in a NOTPROP case.
-
- Example: the row for WORD contains ucp_L, ucp_N, ucp_P, ucp_Po.
- Underscore is covered by ucp_P or ucp_Po. */
-
- case 6: /* Left alphanum vs right general category */
- case 7: /* Left space vs right general category */
- case 8: /* Left word vs right general category */
- p = posspropstab[n-6];
- accepted = risprop && lisprop ==
- (list[3] != p[0] &&
- list[3] != p[1] &&
- (list[3] != p[2] || !lisprop));
- break;
-
- case 9: /* Right alphanum vs left general category */
- case 10: /* Right space vs left general category */
- case 11: /* Right word vs left general category */
- p = posspropstab[n-9];
- accepted = lisprop && risprop ==
- (base_list[3] != p[0] &&
- base_list[3] != p[1] &&
- (base_list[3] != p[2] || !risprop));
+ overflow = TRUE;
break;
+ }
+ s = s * 10 + (unsigned int)(*(++ptr) - CHAR_0);
+ }
+ if (overflow) /* Integer overflow */
+ {
+ while (IS_DIGIT(ptr[1])) ptr++;
+ *errorcodeptr = ERR61;
+ break;
+ }
- case 12: /* Left alphanum vs right particular category */
- case 13: /* Left space vs right particular category */
- case 14: /* Left word vs right particular category */
- p = posspropstab[n-12];
- accepted = risprop && lisprop ==
- (catposstab[p[0]][list[3]] &&
- catposstab[p[1]][list[3]] &&
- (list[3] != p[3] || !lisprop));
- break;
+ /* \1 to \9 are always back references. \8x and \9x are too; \1x to \7x
+ are octal escapes if there are not that many previous captures. */
- case 15: /* Right alphanum vs left particular category */
- case 16: /* Right space vs left particular category */
- case 17: /* Right word vs left particular category */
- p = posspropstab[n-15];
- accepted = lisprop && risprop ==
- (catposstab[p[0]][base_list[3]] &&
- catposstab[p[1]][base_list[3]] &&
- (base_list[3] != p[3] || !risprop));
- break;
- }
+ if (s < 10 || *oldptr >= CHAR_8 || s <= cb->bracount)
+ {
+ escape = -(int)s; /* Indicates a back reference */
+ break;
}
+ ptr = oldptr; /* Put the pointer back and fall through */
}
- else
-#endif /* SUPPORT_UCP */
+ /* Handle a digit following \ when the number is not a back reference, or
+ we are within a character class. If the first digit is 8 or 9, Perl used to
+ generate a binary zero byte and then treat the digit as a following
+ literal. At least by Perl 5.18 this changed so as not to insert the binary
+ zero. */
- accepted = leftop >= FIRST_AUTOTAB_OP && leftop <= LAST_AUTOTAB_LEFT_OP &&
- rightop >= FIRST_AUTOTAB_OP && rightop <= LAST_AUTOTAB_RIGHT_OP &&
- autoposstab[leftop - FIRST_AUTOTAB_OP][rightop - FIRST_AUTOTAB_OP];
+ if ((c = *ptr) >= CHAR_8) break;
- if (!accepted) return FALSE;
+ /* Fall through with a digit less than 8 */
- if (list[1] == 0) return TRUE;
- /* Might be an empty repeat. */
- continue;
- }
+ /* \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. */
- /* Control reaches here only if one of the items is a small character list.
- All characters are checked against the other side. */
+ case CHAR_0:
+ c -= CHAR_0;
+ while(i++ < 2 && ptr[1] >= CHAR_0 && ptr[1] <= CHAR_7)
+ c = c * 8 + *(++ptr) - CHAR_0;
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (!utf && c > 0xff) *errorcodeptr = ERR51;
+#endif
+ break;
- do
- {
- chr = *chr_ptr;
+ /* \o is a relatively new Perl feature, supporting a more general way of
+ specifying character codes in octal. The only supported form is \o{ddd}. */
- switch(list_ptr[0])
+ case CHAR_o:
+ if (ptr[1] != CHAR_LEFT_CURLY_BRACKET) *errorcodeptr = ERR55; else
+ if (ptr[2] == CHAR_RIGHT_CURLY_BRACKET) *errorcodeptr = ERR78; else
{
- case OP_CHAR:
- ochr_ptr = list_ptr + 2;
- do
+ ptr += 2;
+ c = 0;
+ overflow = FALSE;
+ while (*ptr >= CHAR_0 && *ptr <= CHAR_7)
{
- if (chr == *ochr_ptr) return FALSE;
- ochr_ptr++;
+ cc = *ptr++;
+ if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */
+#if PCRE2_CODE_UNIT_WIDTH == 32
+ if (c >= 0x20000000l) { overflow = TRUE; break; }
+#endif
+ c = (c << 3) + (cc - CHAR_0);
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (c > (utf ? 0x10ffffU : 0xffU)) { overflow = TRUE; break; }
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+ if (c > (utf ? 0x10ffffU : 0xffffU)) { overflow = TRUE; break; }
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+ if (utf && c > 0x10ffffU) { overflow = TRUE; break; }
+#endif
}
- while(*ochr_ptr != NOTACHAR);
- break;
-
- case OP_NOT:
- ochr_ptr = list_ptr + 2;
- do
+ if (overflow)
{
- if (chr == *ochr_ptr)
- break;
- ochr_ptr++;
+ while (*ptr >= CHAR_0 && *ptr <= CHAR_7) ptr++;
+ *errorcodeptr = ERR34;
}
- while(*ochr_ptr != NOTACHAR);
- if (*ochr_ptr == NOTACHAR) return FALSE; /* Not found */
- break;
+ else if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
+ {
+ if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
+ }
+ else *errorcodeptr = ERR64;
+ }
+ break;
- /* 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. */
+ /* \x is complicated. When PCRE2_ALT_BSUX is set, \x must be followed by
+ two hexadecimal digits. Otherwise it is a lowercase x letter. */
- case OP_DIGIT:
- if (chr < 256 && (cd->ctypes[chr] & ctype_digit) != 0) return FALSE;
- break;
+ case CHAR_x:
+ if ((options & PCRE2_ALT_BSUX) != 0)
+ {
+ uint32_t xc;
+ if ((cc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */
+ if ((xc = XDIGIT(ptr[2])) == 0xff) break; /* Not a hex digit */
+ c = (cc << 4) | xc;
+ ptr += 2;
+ } /* End PCRE2_ALT_BSUX handling */
- case OP_NOT_DIGIT:
- if (chr > 255 || (cd->ctypes[chr] & ctype_digit) == 0) return FALSE;
- break;
+ /* Handle \x in Perl's style. \x{ddd} is a character number which can be
+ greater than 0xff in UTF-8 or non-8bit mode, but only if the ddd are hex
+ digits. If not, { used to be treated as a data character. However, Perl
+ seems to read hex digits up to the first non-such, and ignore the rest, so
+ that, for example \x{zz} matches a binary zero. This seems crazy, so PCRE
+ now gives an error. */
- case OP_WHITESPACE:
- if (chr < 256 && (cd->ctypes[chr] & ctype_space) != 0) return FALSE;
- break;
+ else
+ {
+ if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
+ {
+ ptr += 2;
+ if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
+ {
+ *errorcodeptr = ERR78;
+ break;
+ }
+ c = 0;
+ overflow = FALSE;
- case OP_NOT_WHITESPACE:
- if (chr > 255 || (cd->ctypes[chr] & ctype_space) == 0) return FALSE;
- break;
+ while ((cc = XDIGIT(*ptr)) != 0xff)
+ {
+ ptr++;
+ if (c == 0 && cc == 0) continue; /* Leading zeroes */
+#if PCRE2_CODE_UNIT_WIDTH == 32
+ if (c >= 0x10000000l) { overflow = TRUE; break; }
+#endif
+ c = (c << 4) | cc;
+ if ((utf && c > 0x10ffffU) || (!utf && c > MAX_NON_UTF_CHAR))
+ {
+ overflow = TRUE;
+ break;
+ }
+ }
- case OP_WORDCHAR:
- if (chr < 255 && (cd->ctypes[chr] & ctype_word) != 0) return FALSE;
- break;
+ if (overflow)
+ {
+ while (XDIGIT(*ptr) != 0xff) ptr++;
+ *errorcodeptr = ERR34;
+ }
+ else if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
+ {
+ if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
+ }
- case OP_NOT_WORDCHAR:
- if (chr > 255 || (cd->ctypes[chr] & ctype_word) == 0) return FALSE;
- break;
+ /* If the sequence of hex digits does not end with '}', give an error.
+ We used just to recognize this construct and fall through to the normal
+ \x handling, but nowadays Perl gives an error, which seems much more
+ sensible, so we do too. */
- case OP_HSPACE:
- switch(chr)
- {
- HSPACE_CASES: return FALSE;
- default: break;
- }
- break;
+ else *errorcodeptr = ERR67;
+ } /* End of \x{} processing */
- case OP_NOT_HSPACE:
- switch(chr)
- {
- HSPACE_CASES: break;
- default: return FALSE;
- }
- break;
+ /* Read a single-byte hex-defined char (up to two hex digits after \x) */
- case OP_ANYNL:
- case OP_VSPACE:
- switch(chr)
+ else
{
- VSPACE_CASES: return FALSE;
- default: break;
- }
- break;
+ c = 0;
+ if ((cc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */
+ ptr++;
+ c = cc;
+ if ((cc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */
+ ptr++;
+ c = (c << 4) | cc;
+ } /* End of \xdd handling */
+ } /* End of Perl-style \x handling */
+ break;
- case OP_NOT_VSPACE:
- switch(chr)
- {
- VSPACE_CASES: break;
- default: return FALSE;
- }
- break;
+ /* The handling of \c is different in ASCII and EBCDIC environments. In an
+ ASCII (or Unicode) environment, an error is given if the character
+ following \c is not a printable ASCII character. Otherwise, the following
+ character is upper-cased if it is a letter, and after that the 0x40 bit is
+ flipped. The result is the value of the escape.
- case OP_DOLL:
- case OP_EODN:
- switch (chr)
- {
- case CHAR_CR:
- case CHAR_LF:
- case CHAR_VT:
- case CHAR_FF:
- case CHAR_NEL:
-#ifndef EBCDIC
- case 0x2028:
- case 0x2029:
-#endif /* Not EBCDIC */
- return FALSE;
- }
- break;
+ In an EBCDIC environment the handling of \c is compatible with the
+ specification in the perlebcdic document. The following character must be
+ a letter or one of small number of special characters. These provide a
+ means of defining the character values 0-31.
- case OP_EOD: /* Can always possessify before \z */
- break;
+ For testing the EBCDIC handling of \c in an ASCII environment, recognize
+ the EBCDIC value of 'c' explicitly. */
-#ifdef SUPPORT_UCP
- case OP_PROP:
- case OP_NOTPROP:
- if (!check_char_prop(chr, list_ptr[2], list_ptr[3],
- list_ptr[0] == OP_NOTPROP))
- return FALSE;
- break;
+#if defined EBCDIC && 'a' != 0x81
+ case 0x83:
+#else
+ case CHAR_c:
#endif
- case OP_NCLASS:
- if (chr > 255) return FALSE;
- /* Fall through */
-
- case OP_CLASS:
- if (chr > 255) break;
- class_bitset = (pcre_uint8 *)
- ((list_ptr == list ? code : base_end) - list_ptr[2]);
- if ((class_bitset[chr >> 3] & (1 << (chr & 7))) != 0) return FALSE;
+ c = *(++ptr);
+ if (c >= CHAR_a && c <= CHAR_z) c = UPPER_CASE(c);
+ if (c == CHAR_NULL && ptr >= ptrend)
+ {
+ *errorcodeptr = ERR2;
break;
+ }
+
+ /* Handle \c in an ASCII/Unicode environment. */
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
- case OP_XCLASS:
- if (PRIV(xclass)(chr, (list_ptr == list ? code : base_end) -
- list_ptr[2] + LINK_SIZE, utf)) return FALSE;
+#ifndef EBCDIC /* ASCII/UTF-8 coding */
+ if (c < 32 || c > 126) /* Excludes all non-printable ASCII */
+ {
+ *errorcodeptr = ERR68;
break;
-#endif
+ }
+ c ^= 0x40;
- default:
- return FALSE;
+ /* Handle \c in an EBCDIC environment. The special case \c? is converted to
+ 255 (0xff) or 95 (0x5f) if other character suggest we are using th POSIX-BC
+ encoding. (This is the way Perl indicates that it handles \c?.) The other
+ valid sequences correspond to a list of specific characters. */
+
+#else
+ if (c == CHAR_QUESTION_MARK)
+ c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff;
+ else
+ {
+ for (i = 0; i < 32; i++)
+ {
+ if (c == ebcdic_escape_c[i]) break;
+ }
+ if (i < 32) c = i; else *errorcodeptr = ERR68;
}
+#endif /* EBCDIC */
- chr_ptr++;
- }
- while(*chr_ptr != NOTACHAR);
+ break;
- /* At least one character must be matched from this opcode. */
+ /* Any other alphanumeric following \ is an error. Perl gives an error only
+ if in warning mode, but PCRE doesn't have a warning mode. */
- if (list[1] == 0) return TRUE;
+ default:
+ *errorcodeptr = ERR3;
+ break;
+ }
}
-/* Control never reaches here. There used to be a fail-save return FALSE; here,
-but some compilers complain about an unreachable statement. */
+/* 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 (escape == ESC_N && ptr[1] == CHAR_LEFT_CURLY_BRACKET &&
+ !is_counted_repeat(ptr+2))
+ *errorcodeptr = ERR37;
+
+/* If PCRE2_UCP is set, we change the values for \d etc. */
+
+if ((options & PCRE2_UCP) != 0 && escape >= ESC_D && escape <= ESC_w)
+ escape += (ESC_DU - ESC_D);
+/* Set the pointer to the final character before returning. */
+
+*ptrptr = ptr;
+*chptr = c;
+return escape;
}
+#ifdef SUPPORT_UNICODE
/*************************************************
-* Scan compiled regex for auto-possession *
+* Handle \P and \p *
*************************************************/
-/* Replaces single character iterations with their possessive alternatives
-if appropriate. This function modifies the compiled opcode!
+/* This function is called after \P or \p has been encountered, provided that
+PCRE2 is compiled with support for UTF and Unicode properties. On entry, the
+contents of ptrptr are pointing at the P or p. On exit, it is left pointing at
+the final code unit of the escape sequence.
Arguments:
- code points to start of the byte code
- utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
- cd static compile data
+ ptrptr the pattern position pointer
+ negptr a boolean that is set TRUE for negation else FALSE
+ ptypeptr an unsigned int that is set to the type value
+ pdataptr an unsigned int that is set to the detailed property value
+ errorcodeptr the error code variable
+ cb the compile data
-Returns: nothing
+Returns: TRUE if the type value was found, or FALSE for an invalid type
*/
-static void
-auto_possessify(pcre_uchar *code, BOOL utf, const compile_data *cd)
+static BOOL
+get_ucp(PCRE2_SPTR *ptrptr, BOOL *negptr, unsigned int *ptypeptr,
+ unsigned int *pdataptr, int *errorcodeptr, compile_block *cb)
{
-register pcre_uchar c;
-const pcre_uchar *end;
-pcre_uchar *repeat_opcode;
-pcre_uint32 list[8];
-int rec_limit;
+register PCRE2_UCHAR c;
+size_t i, bot, top;
+PCRE2_SPTR ptr = *ptrptr;
+PCRE2_UCHAR name[32];
-for (;;)
+*negptr = FALSE;
+c = *(++ptr);
+
+/* \P or \p can be followed by a name in {}, optionally preceded by ^ for
+negation. */
+
+if (c == CHAR_LEFT_CURLY_BRACKET)
{
- c = *code;
+ if (ptr[1] == CHAR_CIRCUMFLEX_ACCENT)
+ {
+ *negptr = TRUE;
+ ptr++;
+ }
+ for (i = 0; i < (int)(sizeof(name) / sizeof(PCRE2_UCHAR)) - 1; i++)
+ {
+ c = *(++ptr);
+ if (c == CHAR_NULL) 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;
+ }
- /* When a pattern with bad UTF-8 encoding is compiled with NO_UTF_CHECK,
- it may compile without complaining, but may get into a loop here if the code
- pointer points to a bad value. This is, of course a documentated possibility,
- when NO_UTF_CHECK is set, so it isn't a bug, but we can detect this case and
- just give up on this optimization. */
+/* Otherwise there is just one following character, which must be an ASCII
+letter. */
- if (c >= OP_TABLE_LENGTH) return;
+else if (MAX_255(c) && (cb->ctypes[c] & ctype_letter) != 0)
+ {
+ name[0] = c;
+ name[1] = 0;
+ }
+else goto ERROR_RETURN;
+
+*ptrptr = ptr;
+
+/* Search for a recognized property name using binary chop. */
- if (c >= OP_STAR && c <= OP_TYPEPOSUPTO)
+bot = 0;
+top = PRIV(utt_size);
+
+while (bot < top)
+ {
+ int r;
+ i = (bot + top) >> 1;
+ r = PRIV(strcmp_c8)(name, PRIV(utt_names) + PRIV(utt)[i].name_offset);
+ if (r == 0)
{
- c -= get_repeat_base(c) - OP_STAR;
- end = (c <= OP_MINUPTO) ?
- get_chr_property_list(code, utf, cd->fcc, list) : NULL;
- list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO;
+ *ptypeptr = PRIV(utt)[i].type;
+ *pdataptr = PRIV(utt)[i].value;
+ return TRUE;
+ }
+ if (r > 0) bot = i + 1; else top = i;
+ }
+*errorcodeptr = ERR47; /* Unrecognized name */
+return FALSE;
- rec_limit = 1000;
- if (end != NULL && compare_opcodes(end, utf, cd, list, end, &rec_limit))
- {
- switch(c)
- {
- case OP_STAR:
- *code += OP_POSSTAR - OP_STAR;
- break;
+ERROR_RETURN: /* Malformed \P or \p */
+*errorcodeptr = ERR46;
+*ptrptr = ptr;
+return FALSE;
+}
+#endif
- case OP_MINSTAR:
- *code += OP_POSSTAR - OP_MINSTAR;
- break;
- case OP_PLUS:
- *code += OP_POSPLUS - OP_PLUS;
- break;
- case OP_MINPLUS:
- *code += OP_POSPLUS - OP_MINPLUS;
- break;
+/*************************************************
+* Read repeat counts *
+*************************************************/
- case OP_QUERY:
- *code += OP_POSQUERY - OP_QUERY;
- break;
+/* 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.
- case OP_MINQUERY:
- *code += OP_POSQUERY - OP_MINQUERY;
- break;
+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
- case OP_UPTO:
- *code += OP_POSUPTO - OP_UPTO;
- break;
+Returns: pointer to '}' on success;
+ current ptr on error, with errorcodeptr set non-zero
+*/
- case OP_MINUPTO:
- *code += OP_POSUPTO - OP_MINUPTO;
- break;
+static PCRE2_SPTR
+read_repeat_counts(PCRE2_SPTR p, int *minp, int *maxp, int *errorcodeptr)
+{
+int min = 0;
+int max = -1;
+
+while (IS_DIGIT(*p))
+ {
+ min = min * 10 + (int)(*p++ - CHAR_0);
+ if (min > 65535)
+ {
+ *errorcodeptr = ERR5;
+ return p;
+ }
+ }
+
+if (*p == CHAR_RIGHT_CURLY_BRACKET) max = min; else
+ {
+ if (*(++p) != CHAR_RIGHT_CURLY_BRACKET)
+ {
+ max = 0;
+ while(IS_DIGIT(*p))
+ {
+ max = max * 10 + (int)(*p++ - CHAR_0);
+ if (max > 65535)
+ {
+ *errorcodeptr = ERR5;
+ return p;
}
}
- c = *code;
+ if (max < min)
+ {
+ *errorcodeptr = ERR4;
+ return p;
+ }
}
- else if (c == OP_CLASS || c == OP_NCLASS || c == OP_XCLASS)
- {
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
- if (c == OP_XCLASS)
- repeat_opcode = code + GET(code, 1);
- else
-#endif
- repeat_opcode = code + 1 + (32 / sizeof(pcre_uchar));
+ }
- c = *repeat_opcode;
- if (c >= OP_CRSTAR && c <= OP_CRMINRANGE)
- {
- /* end must not be NULL. */
- end = get_chr_property_list(code, utf, cd->fcc, list);
+*minp = min;
+*maxp = max;
+return p;
+}
- list[1] = (c & 1) == 0;
- rec_limit = 1000;
- if (compare_opcodes(end, utf, cd, list, end, &rec_limit))
- {
- switch (c)
- {
- case OP_CRSTAR:
- case OP_CRMINSTAR:
- *repeat_opcode = OP_CRPOSSTAR;
- break;
- case OP_CRPLUS:
- case OP_CRMINPLUS:
- *repeat_opcode = OP_CRPOSPLUS;
- break;
+/*************************************************
+* Scan compiled regex for recursion reference *
+*************************************************/
- case OP_CRQUERY:
- case OP_CRMINQUERY:
- *repeat_opcode = OP_CRPOSQUERY;
- break;
+/* This function scans through a compiled pattern until it finds an instance of
+OP_RECURSE.
- case OP_CRRANGE:
- case OP_CRMINRANGE:
- *repeat_opcode = OP_CRPOSRANGE;
- break;
- }
- }
- }
- c = *code;
- }
+Arguments:
+ code points to start of expression
+ utf TRUE in UTF mode
- switch(c)
- {
- case OP_END:
- return;
+Returns: pointer to the opcode for OP_RECURSE, or NULL if not found
+*/
- 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;
+static PCRE2_SPTR
+find_recurse(PCRE2_SPTR code, BOOL utf)
+{
+for (;;)
+ {
+ register PCRE2_UCHAR c = *code;
+ if (c == OP_END) return NULL;
+ if (c == OP_RECURSE) return code;
- 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;
+ /* XCLASS is used for classes that cannot be represented just by a bit map.
+ This includes negated single high-valued characters. CALLOUT_STR is used for
+ callouts with string arguments. In both cases the length in the table is
+ zero; the actual length is stored in the compiled code. */
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
- case OP_XCLASS:
- code += GET(code, 1);
- break;
-#endif
+ if (c == OP_XCLASS) code += GET(code, 1);
+ else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE);
- case OP_MARK:
- case OP_PRUNE_ARG:
- case OP_SKIP_ARG:
- case OP_THEN_ARG:
- code += code[1];
- break;
- }
+ /* 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. */
- /* Add in the fixed length from the table */
+ 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;
- code += PRIV(OP_lengths)[c];
+ 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;
- /* 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. */
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ code += code[1];
+ break;
+ }
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
- if (utf) switch(c)
- {
- case OP_CHAR:
- case OP_CHARI:
- case OP_NOT:
- case OP_NOTI:
- case OP_STAR:
- case OP_MINSTAR:
- case OP_PLUS:
- case OP_MINPLUS:
- case OP_QUERY:
- case OP_MINQUERY:
- case OP_UPTO:
- case OP_MINUPTO:
- case OP_EXACT:
- case OP_POSSTAR:
- case OP_POSPLUS:
- case OP_POSQUERY:
- case OP_POSUPTO:
- case OP_STARI:
- case OP_MINSTARI:
- case OP_PLUSI:
- case OP_MINPLUSI:
- case OP_QUERYI:
- case OP_MINQUERYI:
- case OP_UPTOI:
- case OP_MINUPTOI:
- case OP_EXACTI:
- case OP_POSSTARI:
- case OP_POSPLUSI:
- case OP_POSQUERYI:
- case OP_POSUPTOI:
- case OP_NOTSTAR:
- case OP_NOTMINSTAR:
- case OP_NOTPLUS:
- case OP_NOTMINPLUS:
- case OP_NOTQUERY:
- case OP_NOTMINQUERY:
- case OP_NOTUPTO:
- case OP_NOTMINUPTO:
- case OP_NOTEXACT:
- case OP_NOTPOSSTAR:
- case OP_NOTPOSPLUS:
- case OP_NOTPOSQUERY:
- case OP_NOTPOSUPTO:
- case OP_NOTSTARI:
- case OP_NOTMINSTARI:
- case OP_NOTPLUSI:
- case OP_NOTMINPLUSI:
- case OP_NOTQUERYI:
- case OP_NOTMINQUERYI:
- case OP_NOTUPTOI:
- case OP_NOTMINUPTOI:
- case OP_NOTEXACTI:
- case OP_NOTPOSSTARI:
- case OP_NOTPOSPLUSI:
- case OP_NOTPOSQUERYI:
- case OP_NOTPOSUPTOI:
- if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);
- break;
- }
+ /* Add in the fixed length from the table */
+
+ code += PRIV(OP_lengths)[c];
+
+ /* In UTF-8 and UTF-16 modes, opcodes that are followed by a character may
+ be followed by a multi-unit character. The length in the table is a
+ minimum, so we have to arrange to skip the extra units. */
+
+#ifdef MAYBE_UTF_MULTI
+ if (utf) switch(c)
+ {
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+ case OP_EXACT:
+ case OP_EXACTI:
+ case OP_NOTEXACT:
+ case OP_NOTEXACTI:
+ case OP_UPTO:
+ case OP_UPTOI:
+ case OP_NOTUPTO:
+ case OP_NOTUPTOI:
+ case OP_MINUPTO:
+ case OP_MINUPTOI:
+ case OP_NOTMINUPTO:
+ case OP_NOTMINUPTOI:
+ case OP_POSUPTO:
+ case OP_POSUPTOI:
+ case OP_NOTPOSUPTO:
+ case OP_NOTPOSUPTOI:
+ case OP_STAR:
+ case OP_STARI:
+ case OP_NOTSTAR:
+ case OP_NOTSTARI:
+ case OP_MINSTAR:
+ case OP_MINSTARI:
+ case OP_NOTMINSTAR:
+ case OP_NOTMINSTARI:
+ case OP_POSSTAR:
+ case OP_POSSTARI:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSSTARI:
+ case OP_PLUS:
+ case OP_PLUSI:
+ case OP_NOTPLUS:
+ case OP_NOTPLUSI:
+ case OP_MINPLUS:
+ case OP_MINPLUSI:
+ case OP_NOTMINPLUS:
+ case OP_NOTMINPLUSI:
+ case OP_POSPLUS:
+ case OP_POSPLUSI:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSPLUSI:
+ case OP_QUERY:
+ case OP_QUERYI:
+ case OP_NOTQUERY:
+ case OP_NOTQUERYI:
+ case OP_MINQUERY:
+ case OP_MINQUERYI:
+ case OP_NOTMINQUERY:
+ case OP_NOTMINQUERYI:
+ case OP_POSQUERY:
+ case OP_POSQUERYI:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSQUERYI:
+ if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);
+ break;
+ }
#else
- (void)(utf); /* Keep compiler happy by referencing function argument */
-#endif
+ (void)(utf); /* Keep compiler happy by referencing function argument */
+#endif /* MAYBE_UTF_MULTI */
+ }
}
}
@@ -3915,7 +2634,9 @@ 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.
+a digit. This is handled by returning FALSE if the start of a new group with
+the same terminator is encountered, since the next closing sequence must close
+the nested group, not the outer one.
In Perl, unescaped square brackets may also appear as part of class names. For
example, [:a[:abc]b:] gives unknown POSIX class "[:abc]b:]". However, for
@@ -3925,21 +2646,21 @@ names.
Arguments:
ptr pointer to the initial [
- endptr where to return the end pointer
+ endptr where to return a pointer to the terminating ':', '.', or '='
Returns: TRUE or FALSE
*/
static BOOL
-check_posix_syntax(const pcre_uchar *ptr, const pcre_uchar **endptr)
+check_posix_syntax(PCRE2_SPTR ptr, PCRE2_SPTR *endptr)
{
-pcre_uchar terminator; /* Don't combine these lines; the Solaris cc */
+PCRE2_UCHAR terminator; /* Don't combine these lines; the Solaris cc */
terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */
+
for (++ptr; *ptr != CHAR_NULL; ptr++)
{
if (*ptr == CHAR_BACKSLASH &&
- (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET ||
- ptr[1] == CHAR_BACKSLASH))
+ (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET || ptr[1] == CHAR_BACKSLASH))
ptr++;
else if ((*ptr == CHAR_LEFT_SQUARE_BRACKET && ptr[1] == terminator) ||
*ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE;
@@ -3949,12 +2670,12 @@ for (++ptr; *ptr != CHAR_NULL; ptr++)
return TRUE;
}
}
+
return FALSE;
}
-
/*************************************************
* Check POSIX class name *
*************************************************/
@@ -3970,14 +2691,14 @@ Returns: a value representing the name, or -1 if unknown
*/
static int
-check_posix_name(const pcre_uchar *ptr, int len)
+check_posix_name(PCRE2_SPTR 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, (unsigned int)len) == 0) return yield;
+ PRIV(strncmp_c8)(ptr, pn, (unsigned int)len) == 0) return yield;
pn += posix_name_lengths[yield] + 1;
yield++;
}
@@ -3985,141 +2706,16 @@ 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 to cope with forward references for recursions
-and subroutine calls. It must check the list of such references for the
-group we are dealing with. If it finds that one of the recursions in the
-current group is on this list, it does not adjust the value in the reference
-(which is a group number). After the group has been scanned, all the offsets in
-the forward reference list for the group are adjusted.
-
-Arguments:
- group points to the start of the group
- adjust the amount by which the group is to be moved
- utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
- cd contains pointers to tables etc.
- save_hwm_offset the hwm forward reference offset at the start of the group
-
-Returns: nothing
-*/
-
-static void
-adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd,
- size_t save_hwm_offset)
-{
-int offset;
-pcre_uchar *hc;
-pcre_uchar *ptr = group;
-
-while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL)
- {
- for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm;
- hc += LINK_SIZE)
- {
- offset = (int)GET(hc, 0);
- if (cd->start_code + offset == ptr + 1) break;
- }
-
- /* If we have not found this recursion on the forward reference list, adjust
- the recursion's offset if it's after the start of this group. */
-
- if (hc >= cd->hwm)
- {
- offset = (int)GET(ptr, 1);
- if (cd->start_code + offset >= group) PUT(ptr, 1, offset + adjust);
- }
-
- ptr += 1 + LINK_SIZE;
- }
-
-/* Now adjust all forward reference offsets for the group. */
-
-for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm;
- hc += LINK_SIZE)
- {
- offset = (int)GET(hc, 0);
- PUT(hc, 0, offset + adjust);
- }
-}
-
-
-
-/*************************************************
-* 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
+#ifdef SUPPORT_UNICODE
/*************************************************
* 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 ranges of
-characters in the "other" case. Each call returns the next one, updating the
-start address. A character with multiple other cases is returned on its own
-with a special return value.
+/* This function is passed the start and end of a class range in UCT mode. It
+searches up the characters, looking for ranges of characters in the "other"
+case. Each call returns the next one, updating the start address. A character
+with multiple other cases is returned on its own with a special return value.
Arguments:
cptr points to starting character value; updated
@@ -4134,10 +2730,10 @@ Yield: -1 when no more
*/
static int
-get_othercase_range(pcre_uint32 *cptr, pcre_uint32 d, pcre_uint32 *ocptr,
- pcre_uint32 *odptr)
+get_othercase_range(uint32_t *cptr, uint32_t d, uint32_t *ocptr,
+ uint32_t *odptr)
{
-pcre_uint32 c, othercase, next;
+uint32_t c, othercase, next;
unsigned int co;
/* Find the first character that has an other case. If it has multiple other
@@ -4173,7 +2769,7 @@ for (++c; c <= d; c++)
*cptr = c; /* Rest of input range */
return 0;
}
-#endif /* SUPPORT_UCP */
+#endif /* SUPPORT_UNICODE */
@@ -4190,7 +2786,7 @@ Arguments:
classbits the bit map for characters < 256
uchardptr points to the pointer for extra data
options the options word
- cd contains pointers to tables etc.
+ cb compile data
start start of range character
end end of range character
@@ -4198,35 +2794,35 @@ Returns: the number of < 256 characters added
the pointer to extra data is updated
*/
-static int
-add_to_class(pcre_uint8 *classbits, pcre_uchar **uchardptr, int options,
- compile_data *cd, pcre_uint32 start, pcre_uint32 end)
+static unsigned int
+add_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, uint32_t options,
+ compile_block *cb, uint32_t start, uint32_t end)
{
-pcre_uint32 c;
-pcre_uint32 classbits_end = (end <= 0xff ? end : 0xff);
-int n8 = 0;
+uint32_t c;
+uint32_t classbits_end = (end <= 0xff ? end : 0xff);
+unsigned int n8 = 0;
/* If caseless matching is required, scan the range and process alternate
cases. In Unicode, there are 8-bit characters that have alternate cases that
are greater than 255 and vice-versa. Sometimes we can just extend the original
range. */
-if ((options & PCRE_CASELESS) != 0)
+if ((options & PCRE2_CASELESS) != 0)
{
-#ifdef SUPPORT_UCP
- if ((options & PCRE_UTF8) != 0)
+#ifdef SUPPORT_UNICODE
+ if ((options & PCRE2_UTF) != 0)
{
int rc;
- pcre_uint32 oc, od;
+ uint32_t oc, od;
- options &= ~PCRE_CASELESS; /* Remove for recursive calls */
+ options &= ~PCRE2_CASELESS; /* Remove for recursive calls */
c = start;
while ((rc = get_othercase_range(&c, end, &oc, &od)) >= 0)
{
/* Handle a single character that has more than one other case. */
- if (rc > 0) n8 += add_list_to_class(classbits, uchardptr, options, cd,
+ if (rc > 0) n8 += add_list_to_class(classbits, uchardptr, options, cb,
PRIV(ucd_caseless_sets) + rc, oc);
/* Do nothing if the other case range is within the original range. */
@@ -4243,17 +2839,17 @@ if ((options & PCRE_CASELESS) != 0)
end = od; /* Extend upwards */
if (end > classbits_end) classbits_end = (end <= 0xff ? end : 0xff);
}
- else n8 += add_to_class(classbits, uchardptr, options, cd, oc, od);
+ else n8 += add_to_class(classbits, uchardptr, options, cb, oc, od);
}
}
else
-#endif /* SUPPORT_UCP */
+#endif /* SUPPORT_UNICODE */
- /* Not UTF-mode, or no UCP */
+ /* Not UTF mode */
for (c = start; c <= classbits_end; c++)
{
- SETBIT(classbits, cd->fcc[c]);
+ SETBIT(classbits, cb->fcc[c]);
n8++;
}
}
@@ -4262,19 +2858,8 @@ if ((options & PCRE_CASELESS) != 0)
length - this means that the same lists of (e.g.) horizontal spaces can be used
in all cases. */
-#if defined COMPILE_PCRE8
-#ifdef SUPPORT_UTF
- if ((options & PCRE_UTF8) == 0)
-#endif
- if (end > 0xff) end = 0xff;
-
-#elif defined COMPILE_PCRE16
-#ifdef SUPPORT_UTF
- if ((options & PCRE_UTF16) == 0)
-#endif
- if (end > 0xffff) end = 0xffff;
-
-#endif /* COMPILE_PCRE[8|16] */
+if ((options & PCRE2_UTF) == 0 && end > MAX_NON_UTF_CHAR)
+ end = MAX_NON_UTF_CHAR;
/* Use the bitmap for characters < 256. Otherwise use extra data.*/
@@ -4285,14 +2870,15 @@ for (c = start; c <= classbits_end; c++)
n8++;
}
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#ifdef SUPPORT_WIDE_CHARS
if (start <= 0xff) start = 0xff + 1;
if (end >= start)
{
- pcre_uchar *uchardata = *uchardptr;
-#ifdef SUPPORT_UTF
- if ((options & PCRE_UTF8) != 0) /* All UTFs use the same flag bit */
+ PCRE2_UCHAR *uchardata = *uchardptr;
+
+#ifdef SUPPORT_UNICODE
+ if ((options & PCRE2_UTF) != 0)
{
if (start < end)
{
@@ -4307,12 +2893,12 @@ if (end >= start)
}
}
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
/* Without UTF support, character values are constrained by the bit length,
and can only be > 256 for 16-bit and 32-bit libraries. */
-#ifdef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
{}
#else
if (start < end)
@@ -4327,17 +2913,17 @@ if (end >= start)
*uchardata++ = start;
}
#endif
-
*uchardptr = uchardata; /* Updata extra data pointer */
}
-#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
+#else
+ (void)uchardptr; /* Avoid compiler warning */
+#endif /* SUPPORT_WIDE_CHARS */
return n8; /* Number of 8-bit characters */
}
-
/*************************************************
* Add a list of characters to a class *
*************************************************/
@@ -4352,7 +2938,7 @@ Arguments:
classbits the bit map for characters < 256
uchardptr points to the pointer for extra data
options the options word
- cd contains pointers to tables etc.
+ cb contains pointers to tables etc.
p points to row of 32-bit values, terminated by NOTACHAR
except character to omit; this is used when adding lists of
case-equivalent characters to avoid including the one we
@@ -4362,18 +2948,18 @@ Returns: the number of < 256 characters added
the pointer to extra data is updated
*/
-static int
-add_list_to_class(pcre_uint8 *classbits, pcre_uchar **uchardptr, int options,
- compile_data *cd, const pcre_uint32 *p, unsigned int except)
+static unsigned int
+add_list_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, uint32_t options,
+ compile_block *cb, const uint32_t *p, unsigned int except)
{
-int n8 = 0;
+unsigned int n8 = 0;
while (p[0] < NOTACHAR)
{
- int n = 0;
+ unsigned int n = 0;
if (p[0] != except)
{
while(p[n+1] == p[0] + n + 1) n++;
- n8 += add_to_class(classbits, uchardptr, options, cd, p[0], p[n]);
+ n8 += add_to_class(classbits, uchardptr, options, cb, p[0], p[n]);
}
p += n + 1;
}
@@ -4393,25 +2979,25 @@ Arguments:
classbits the bit map for characters < 256
uchardptr points to the pointer for extra data
options the options word
- cd contains pointers to tables etc.
+ cb contains pointers to tables etc.
p points to row of 32-bit values, terminated by NOTACHAR
Returns: the number of < 256 characters added
the pointer to extra data is updated
*/
-static int
-add_not_list_to_class(pcre_uint8 *classbits, pcre_uchar **uchardptr,
- int options, compile_data *cd, const pcre_uint32 *p)
+static unsigned int
+add_not_list_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr,
+ uint32_t options, compile_block *cb, const uint32_t *p)
{
-BOOL utf = (options & PCRE_UTF8) != 0;
-int n8 = 0;
+BOOL utf = (options & PCRE2_UTF) != 0;
+unsigned int n8 = 0;
if (p[0] > 0)
- n8 += add_to_class(classbits, uchardptr, options, cd, 0, p[0] - 1);
+ n8 += add_to_class(classbits, uchardptr, options, cb, 0, p[0] - 1);
while (p[0] < NOTACHAR)
{
while (p[1] == p[0] + 1) p++;
- n8 += add_to_class(classbits, uchardptr, options, cd, p[0] + 1,
+ n8 += add_to_class(classbits, uchardptr, options, cb, p[0] + 1,
(p[1] == NOTACHAR) ? (utf ? 0x10ffffu : 0xffffffffu) : p[1] - 1);
p++;
}
@@ -4421,6 +3007,822 @@ return n8;
/*************************************************
+* Process (*VERB) name for escapes *
+*************************************************/
+
+/* This function is called when the PCRE2_ALT_VERBNAMES option is set, to
+process the characters in a verb's name argument. It is called twice, once with
+codeptr == NULL, to find out the length of the processed name, and again to put
+the name into memory.
+
+Arguments:
+ ptrptr pointer to the input pointer
+ codeptr pointer to the compiled code pointer
+ errorcodeptr pointer to the error code
+ options the options bits
+ utf TRUE if processing UTF
+ cb compile data block
+
+Returns: length of the processed name, or < 0 on error
+*/
+
+static int
+process_verb_name(PCRE2_SPTR *ptrptr, PCRE2_UCHAR **codeptr, int *errorcodeptr,
+ uint32_t options, BOOL utf, compile_block *cb)
+{
+int32_t arglen = 0;
+BOOL inescq = FALSE;
+PCRE2_SPTR ptr = *ptrptr;
+PCRE2_UCHAR *code = (codeptr == NULL)? NULL : *codeptr;
+
+for (; ptr < cb->end_pattern; ptr++)
+ {
+ uint32_t x = *ptr;
+
+ /* Skip over literals */
+
+ if (inescq)
+ {
+ if (x == CHAR_BACKSLASH && ptr[1] == CHAR_E)
+ {
+ inescq = FALSE;
+ ptr++;;
+ continue;
+ }
+ }
+
+ else /* Not a literal character */
+ {
+ if (x == CHAR_RIGHT_PARENTHESIS) break;
+
+ /* Skip over comments and whitespace in extended mode. */
+
+ if ((options & PCRE2_EXTENDED) != 0)
+ {
+ PCRE2_SPTR wscptr = ptr;
+ while (MAX_255(x) && (cb->ctypes[x] & ctype_space) != 0) x = *(++ptr);
+ if (x == CHAR_NUMBER_SIGN)
+ {
+ ptr++;
+ while (*ptr != CHAR_NULL || ptr < cb->end_pattern)
+ {
+ if (IS_NEWLINE(ptr)) /* For non-fixed-length newline cases, */
+ { /* IS_NEWLINE sets cb->nllen. */
+ ptr += cb->nllen;
+ break;
+ }
+ ptr++;
+#ifdef SUPPORT_UNICODE
+ if (utf) FORWARDCHAR(ptr);
+#endif
+ }
+ }
+
+ /* If we have skipped any characters, restart the loop. */
+
+ if (ptr > wscptr)
+ {
+ ptr--;
+ continue;
+ }
+ }
+
+ /* Process escapes */
+
+ if (x == '\\')
+ {
+ int rc;
+ *errorcodeptr = 0;
+ rc = PRIV(check_escape)(&ptr, cb->end_pattern, &x, errorcodeptr, options,
+ FALSE, cb);
+ *ptrptr = ptr; /* For possible error */
+ if (*errorcodeptr != 0) return -1;
+ if (rc != 0)
+ {
+ if (rc == ESC_Q)
+ {
+ inescq = TRUE;
+ continue;
+ }
+ if (rc == ESC_E) continue;
+ *errorcodeptr = ERR40;
+ return -1;
+ }
+ }
+ }
+
+ /* We have the next character in the name. */
+
+#ifdef SUPPORT_UNICODE
+ if (utf)
+ {
+ if (code == NULL) /* Just want the length */
+ {
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ int i;
+ for (i = 0; i < PRIV(utf8_table1_size); i++)
+ if ((int)x <= PRIV(utf8_table1)[i]) break;
+ arglen += i;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+ if (x > 0xffff) arglen++;
+#endif
+ }
+ else
+ {
+ PCRE2_UCHAR cbuff[8];
+ x = PRIV(ord2utf)(x, cbuff);
+ memcpy(code, cbuff, CU2BYTES(x));
+ code += x;
+ }
+ }
+ else
+#endif /* SUPPORT_UNICODE */
+
+ /* Not UTF */
+ {
+ if (code != NULL) *code++ = (PCRE2_UCHAR)x;
+ }
+
+ arglen++;
+
+ if ((unsigned int)arglen > MAX_MARK)
+ {
+ *errorcodeptr = ERR76;
+ *ptrptr = ptr;
+ return -1;
+ }
+ }
+
+/* Update the pointers before returning. */
+
+*ptrptr = ptr;
+if (codeptr != NULL) *codeptr = code;
+return arglen;
+}
+
+
+
+/*************************************************
+* Macro for the next two functions *
+*************************************************/
+
+/* Both scan_for_captures() and compile_branch() use this macro to generate a
+fragment of code that reads the characters of a name and sets its length
+(checking for not being too long). Count the characters dynamically, to avoid
+the possibility of integer overflow. The same macro is used for reading *VERB
+names. */
+
+#define READ_NAME(ctype, errno, errset) \
+ namelen = 0; \
+ while (MAX_255(*ptr) && (cb->ctypes[*ptr] & ctype) != 0) \
+ { \
+ ptr++; \
+ namelen++; \
+ if (namelen > MAX_NAME_SIZE) \
+ { \
+ errset = errno; \
+ goto FAILED; \
+ } \
+ }
+
+
+
+/*************************************************
+* Scan regex to identify named groups *
+*************************************************/
+
+/* This function is called first of all, to scan for named capturing groups so
+that information about them is fully available to both the compiling scans.
+It skips over everything except parenthesized items.
+
+Arguments:
+ ptrptr points to pointer to the start of the pattern
+ options compiling dynamic options
+ cb pointer to the compile data block
+
+Returns: zero on success or a non-zero error code, with pointer updated
+*/
+
+typedef struct nest_save {
+ uint16_t nest_depth;
+ uint16_t reset_group;
+ uint16_t max_group;
+ uint16_t flags;
+} nest_save;
+
+#define NSF_RESET 0x0001u
+#define NSF_EXTENDED 0x0002u
+#define NSF_DUPNAMES 0x0004u
+
+static int scan_for_captures(PCRE2_SPTR *ptrptr, uint32_t options,
+ compile_block *cb)
+{
+uint32_t c;
+uint32_t delimiter;
+uint32_t set, unset, *optset;
+uint32_t skiptoket = 0;
+uint16_t nest_depth = 0;
+int errorcode = 0;
+int escape;
+int namelen;
+int i;
+BOOL inescq = FALSE;
+BOOL isdupname;
+BOOL utf = (options & PCRE2_UTF) != 0;
+BOOL negate_class;
+PCRE2_SPTR name;
+PCRE2_SPTR start;
+PCRE2_SPTR ptr = *ptrptr;
+named_group *ng;
+nest_save *top_nest = NULL;
+nest_save *end_nests = (nest_save *)(cb->start_workspace + cb->workspace_size);
+
+/* The size of the nest_save structure might not be a factor of the size of the
+workspace. Therefore we must round down end_nests so as to correctly avoid
+creating a nest_save that spans the end of the workspace. */
+
+end_nests = (nest_save *)((char *)end_nests -
+ ((cb->workspace_size * sizeof(PCRE2_UCHAR)) % sizeof(nest_save)));
+
+/* Now scan the pattern */
+
+for (; ptr < cb->end_pattern; ptr++)
+ {
+ c = *ptr;
+
+ /* Parenthesized groups set skiptoket when all following characters up to the
+ next closing parenthesis must be ignored. The parenthesis itself must be
+ processed (to end the nested parenthesized item). */
+
+ if (skiptoket != 0)
+ {
+ if (c != CHAR_RIGHT_PARENTHESIS) continue;
+ skiptoket = 0;
+ }
+
+ /* Skip over literals */
+
+ if (inescq)
+ {
+ if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E)
+ {
+ inescq = FALSE;
+ ptr++;
+ }
+ continue;
+ }
+
+ /* Skip over # comments and whitespace in extended mode. */
+
+ if ((options & PCRE2_EXTENDED) != 0)
+ {
+ PCRE2_SPTR wscptr = ptr;
+ while (MAX_255(c) && (cb->ctypes[c] & ctype_space) != 0) c = *(++ptr);
+ if (c == CHAR_NUMBER_SIGN)
+ {
+ ptr++;
+ while (ptr < cb->end_pattern)
+ {
+ if (IS_NEWLINE(ptr)) /* For non-fixed-length newline cases, */
+ { /* IS_NEWLINE sets cb->nllen. */
+ ptr += cb->nllen;
+ break;
+ }
+ ptr++;
+#ifdef SUPPORT_UNICODE
+ if (utf) FORWARDCHAR(ptr);
+#endif
+ }
+ }
+
+ /* If we skipped any characters, restart the loop. Otherwise, we didn't see
+ a comment. */
+
+ if (ptr > wscptr)
+ {
+ ptr--;
+ continue;
+ }
+ }
+
+ /* Process the next pattern item. */
+
+ switch(c)
+ {
+ default: /* Most characters are just skipped */
+ break;
+
+ /* Skip escapes except for \Q */
+
+ case CHAR_BACKSLASH:
+ errorcode = 0;
+ escape = PRIV(check_escape)(&ptr, cb->end_pattern, &c, &errorcode, options,
+ FALSE, cb);
+ if (errorcode != 0) goto FAILED;
+ if (escape == ESC_Q) inescq = TRUE;
+ break;
+
+ /* Skip a character class. The syntax is complicated so we have to
+ replicate some of what happens when a class is processed for real. */
+
+ case CHAR_LEFT_SQUARE_BRACKET:
+ if (PRIV(strncmp_c8)(ptr+1, STRING_WEIRD_STARTWORD, 6) == 0 ||
+ PRIV(strncmp_c8)(ptr+1, STRING_WEIRD_ENDWORD, 6) == 0)
+ {
+ ptr += 6;
+ break;
+ }
+
+ /* If the first character is '^', set the negation flag (not actually used
+ here, except to recognize only one ^) and skip it. 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); /* First character in class */
+ if (c == CHAR_BACKSLASH)
+ {
+ if (ptr[1] == CHAR_E)
+ ptr++;
+ else if (PRIV(strncmp_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;
+ }
+
+ if (c == CHAR_RIGHT_SQUARE_BRACKET &&
+ (cb->external_options & PCRE2_ALLOW_EMPTY_CLASS) != 0)
+ break;
+
+ /* Loop for the contents of the class */
+
+ for (;;)
+ {
+ PCRE2_SPTR tempptr;
+
+ if (c == CHAR_NULL && ptr >= cb->end_pattern)
+ {
+ errorcode = ERR6; /* Missing terminating ']' */
+ goto FAILED;
+ }
+
+#ifdef SUPPORT_UNICODE
+ if (utf && HAS_EXTRALEN(c))
+ { /* Braces are required because the */
+ GETCHARLEN(c, ptr, ptr); /* macro generates multiple statements */
+ }
+#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' */
+ }
+ goto CONTINUE_CLASS;
+ }
+
+ /* Skip POSIX class names. */
+ if (c == CHAR_LEFT_SQUARE_BRACKET &&
+ (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
+ ptr[1] == CHAR_EQUALS_SIGN) && check_posix_syntax(ptr, &tempptr))
+ {
+ ptr = tempptr + 1;
+ }
+ else if (c == CHAR_BACKSLASH)
+ {
+ errorcode = 0;
+ escape = PRIV(check_escape)(&ptr, cb->end_pattern, &c, &errorcode,
+ options, TRUE, cb);
+ if (errorcode != 0) goto FAILED;
+ if (escape == ESC_Q) inescq = TRUE;
+ }
+
+ CONTINUE_CLASS:
+ c = *(++ptr);
+ if (c == CHAR_RIGHT_SQUARE_BRACKET && !inescq) break;
+ } /* End of class-processing loop */
+ break;
+
+ /* This is the real work of this function - handling parentheses. */
+
+ case CHAR_LEFT_PARENTHESIS:
+ nest_depth++;
+
+ if (ptr[1] != CHAR_QUESTION_MARK)
+ {
+ if (ptr[1] != CHAR_ASTERISK)
+ {
+ if ((options & PCRE2_NO_AUTO_CAPTURE) == 0) cb->bracount++;
+ }
+
+ /* (*something) - skip over a name, and then just skip to closing ket
+ unless PCRE2_ALT_VERBNAMES is set, in which case we have to process
+ escapes in the string after a verb name terminated by a colon. */
+
+ else
+ {
+ ptr += 2;
+ while (MAX_255(*ptr) && (cb->ctypes[*ptr] & ctype_word) != 0) ptr++;
+ if (*ptr == CHAR_COLON && (options & PCRE2_ALT_VERBNAMES) != 0)
+ {
+ ptr++;
+ if (process_verb_name(&ptr, NULL, &errorcode, options, utf, cb) < 0)
+ goto FAILED;
+ }
+ else
+ {
+ while (ptr < cb->end_pattern && *ptr != CHAR_RIGHT_PARENTHESIS)
+ ptr++;
+ }
+ nest_depth--;
+ }
+ }
+
+ /* Handle (?...) groups */
+
+ else switch(ptr[2])
+ {
+ default:
+ ptr += 2;
+ if (ptr[0] == CHAR_R || /* (?R) */
+ ptr[0] == CHAR_NUMBER_SIGN || /* (?#) */
+ IS_DIGIT(ptr[0]) || /* (?n) */
+ (ptr[0] == CHAR_MINUS && IS_DIGIT(ptr[1]))) /* (?-n) */
+ {
+ skiptoket = ptr[0];
+ break;
+ }
+
+ /* Handle (?| and (?imsxJU: which are the only other valid forms. Both
+ need a new block on the nest stack. */
+
+ if (top_nest == NULL) top_nest = (nest_save *)(cb->start_workspace);
+ else if (++top_nest >= end_nests)
+ {
+ errorcode = ERR84;
+ goto FAILED;
+ }
+ top_nest->nest_depth = nest_depth;
+ top_nest->flags = 0;
+ if ((options & PCRE2_EXTENDED) != 0) top_nest->flags |= NSF_EXTENDED;
+ if ((options & PCRE2_DUPNAMES) != 0) top_nest->flags |= NSF_DUPNAMES;
+
+ if (*ptr == CHAR_VERTICAL_LINE)
+ {
+ top_nest->reset_group = (uint16_t)cb->bracount;
+ top_nest->max_group = (uint16_t)cb->bracount;
+ top_nest->flags |= NSF_RESET;
+ cb->external_flags |= PCRE2_DUPCAPUSED;
+ break;
+ }
+
+ /* Scan options */
+
+ top_nest->reset_group = 0;
+ top_nest->max_group = 0;
+
+ set = unset = 0;
+ optset = &set;
+
+ /* Need only track (?x: and (?J: at this stage */
+
+ while (*ptr != CHAR_RIGHT_PARENTHESIS && *ptr != CHAR_COLON)
+ {
+ switch (*ptr++)
+ {
+ case CHAR_MINUS: optset = &unset; break;
+
+ case CHAR_x: *optset |= PCRE2_EXTENDED; break;
+
+ case CHAR_J:
+ *optset |= PCRE2_DUPNAMES;
+ cb->external_flags |= PCRE2_JCHANGED;
+ break;
+
+ case CHAR_i:
+ case CHAR_m:
+ case CHAR_s:
+ case CHAR_U:
+ break;
+
+ default:
+ errorcode = ERR11;
+ ptr--; /* Correct the offset */
+ goto FAILED;
+ }
+ }
+
+ options = (options | set) & (~unset);
+
+ /* If the options ended with ')' this is not the start of a nested
+ group with option changes, so the options change at this level. If the
+ previous level set up a nest block, discard the one we have just created.
+ Otherwise adjust it for the previous level. */
+
+ if (*ptr == CHAR_RIGHT_PARENTHESIS)
+ {
+ nest_depth--;
+ if (top_nest > (nest_save *)(cb->start_workspace) &&
+ (top_nest-1)->nest_depth == nest_depth) top_nest --;
+ else top_nest->nest_depth = nest_depth;
+ }
+ break;
+
+ /* Skip over a numerical or string argument for a callout. */
+
+ case CHAR_C:
+ ptr += 2;
+ if (ptr[1] == CHAR_RIGHT_PARENTHESIS) break;
+ if (IS_DIGIT(ptr[1]))
+ {
+ while (IS_DIGIT(ptr[1])) ptr++;
+ }
+
+ /* Handle a string argument */
+
+ else
+ {
+ ptr++;
+ delimiter = 0;
+ for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)
+ {
+ if (*ptr == PRIV(callout_start_delims)[i])
+ {
+ delimiter = PRIV(callout_end_delims)[i];
+ break;
+ }
+ }
+
+ if (delimiter == 0)
+ {
+ errorcode = ERR82;
+ goto FAILED;
+ }
+
+ start = ptr;
+ do
+ {
+ if (++ptr >= cb->end_pattern)
+ {
+ errorcode = ERR81;
+ ptr = start; /* To give a more useful message */
+ goto FAILED;
+ }
+ if (ptr[0] == delimiter && ptr[1] == delimiter) ptr += 2;
+ }
+ while (ptr[0] != delimiter);
+ }
+
+ /* Check terminating ) */
+
+ if (ptr[1] != CHAR_RIGHT_PARENTHESIS)
+ {
+ errorcode = ERR39;
+ ptr++;
+ goto FAILED;
+ }
+ break;
+
+ /* Conditional group */
+
+ case CHAR_LEFT_PARENTHESIS:
+ if (ptr[3] != CHAR_QUESTION_MARK) /* Not assertion or callout */
+ {
+ nest_depth++;
+ ptr += 2;
+ break;
+ }
+
+ /* Must be an assertion or a callout */
+
+ switch(ptr[4])
+ {
+ case CHAR_LESS_THAN_SIGN:
+ if (ptr[5] != CHAR_EXCLAMATION_MARK && ptr[5] != CHAR_EQUALS_SIGN)
+ goto MISSING_ASSERTION;
+ /* Fall through */
+
+ case CHAR_C:
+ case CHAR_EXCLAMATION_MARK:
+ case CHAR_EQUALS_SIGN:
+ ptr++;
+ break;
+
+ default:
+ MISSING_ASSERTION:
+ ptr += 3; /* To improve error message */
+ errorcode = ERR28;
+ goto FAILED;
+ }
+ break;
+
+ case CHAR_COLON:
+ case CHAR_GREATER_THAN_SIGN:
+ case CHAR_EQUALS_SIGN:
+ case CHAR_EXCLAMATION_MARK:
+ case CHAR_AMPERSAND:
+ case CHAR_PLUS:
+ ptr += 2;
+ break;
+
+ case CHAR_P:
+ if (ptr[3] != CHAR_LESS_THAN_SIGN)
+ {
+ ptr += 3;
+ break;
+ }
+ ptr++;
+ c = CHAR_GREATER_THAN_SIGN; /* Terminator */
+ goto DEFINE_NAME;
+
+ case CHAR_LESS_THAN_SIGN:
+ if (ptr[3] == CHAR_EQUALS_SIGN || ptr[3] == CHAR_EXCLAMATION_MARK)
+ {
+ ptr += 3;
+ break;
+ }
+ c = CHAR_GREATER_THAN_SIGN; /* Terminator */
+ goto DEFINE_NAME;
+
+ case CHAR_APOSTROPHE:
+ c = CHAR_APOSTROPHE; /* Terminator */
+
+ DEFINE_NAME:
+ name = ptr = ptr + 3;
+
+ if (*ptr == c) /* Empty name */
+ {
+ errorcode = ERR62;
+ goto FAILED;
+ }
+
+ if (IS_DIGIT(*ptr))
+ {
+ errorcode = ERR44; /* Group name must start with non-digit */
+ goto FAILED;
+ }
+
+ if (MAX_255(*ptr) && (cb->ctypes[*ptr] & ctype_word) == 0)
+ {
+ errorcode = ERR24;
+ goto FAILED;
+ }
+
+ /* Advance ptr, set namelen and check its length. */
+ READ_NAME(ctype_word, ERR48, errorcode);
+
+ if (*ptr != c)
+ {
+ errorcode = ERR42;
+ goto FAILED;
+ }
+
+ if (cb->names_found >= MAX_NAME_COUNT)
+ {
+ errorcode = ERR49;
+ goto FAILED;
+ }
+
+ if (namelen + IMM2_SIZE + 1 > cb->name_entry_size)
+ cb->name_entry_size = (uint16_t)(namelen + IMM2_SIZE + 1);
+
+ /* We have a valid name for this capturing group. */
+
+ cb->bracount++;
+
+ /* Scan the list to check for duplicates. For duplicate names, if the
+ number is the same, break the loop, which causes the name to be
+ discarded; otherwise, if DUPNAMES is not set, give an error.
+ If it is set, allow the name with a different number, but continue
+ scanning in case this is a duplicate with the same number. For
+ non-duplicate names, give an error if the number is duplicated. */
+
+ isdupname = FALSE;
+ ng = cb->named_groups;
+ for (i = 0; i < cb->names_found; i++, ng++)
+ {
+ if (namelen == ng->length &&
+ PRIV(strncmp)(name, ng->name, (size_t)namelen) == 0)
+ {
+ if (ng->number == cb->bracount) break;
+ if ((options & PCRE2_DUPNAMES) == 0)
+ {
+ errorcode = ERR43;
+ goto FAILED;
+ }
+ isdupname = ng->isdup = TRUE; /* Mark as a duplicate */
+ cb->dupnames = TRUE; /* Duplicate names exist */
+ }
+ else if (ng->number == cb->bracount)
+ {
+ errorcode = ERR65;
+ goto FAILED;
+ }
+ }
+
+ if (i < cb->names_found) break; /* Ignore duplicate with same number */
+
+ /* Increase the list size if necessary */
+
+ if (cb->names_found >= cb->named_group_list_size)
+ {
+ uint32_t newsize = cb->named_group_list_size * 2;
+ named_group *newspace =
+ cb->cx->memctl.malloc(newsize * sizeof(named_group),
+ cb->cx->memctl.memory_data);
+ if (newspace == NULL)
+ {
+ errorcode = ERR21;
+ goto FAILED;
+ }
+
+ memcpy(newspace, cb->named_groups,
+ cb->named_group_list_size * sizeof(named_group));
+ if (cb->named_group_list_size > NAMED_GROUP_LIST_SIZE)
+ cb->cx->memctl.free((void *)cb->named_groups,
+ cb->cx->memctl.memory_data);
+ cb->named_groups = newspace;
+ cb->named_group_list_size = newsize;
+ }
+
+ /* Add this name to the list */
+
+ cb->named_groups[cb->names_found].name = name;
+ cb->named_groups[cb->names_found].length = (uint16_t)namelen;
+ cb->named_groups[cb->names_found].number = cb->bracount;
+ cb->named_groups[cb->names_found].isdup = (uint16_t)isdupname;
+ cb->names_found++;
+ break;
+ } /* End of (? switch */
+ break; /* End of ( handling */
+
+ /* At an alternation, reset the capture count if we are in a (?| group. */
+
+ case CHAR_VERTICAL_LINE:
+ if (top_nest != NULL && top_nest->nest_depth == nest_depth &&
+ (top_nest->flags & NSF_RESET) != 0)
+ {
+ if (cb->bracount > top_nest->max_group)
+ top_nest->max_group = (uint16_t)cb->bracount;
+ cb->bracount = top_nest->reset_group;
+ }
+ break;
+
+ /* At a right parenthesis, reset the capture count to the maximum if we
+ are in a (?| group and/or reset the extended option. */
+
+ case CHAR_RIGHT_PARENTHESIS:
+ if (top_nest != NULL && top_nest->nest_depth == nest_depth)
+ {
+ if ((top_nest->flags & NSF_RESET) != 0 &&
+ top_nest->max_group > cb->bracount)
+ cb->bracount = top_nest->max_group;
+ if ((top_nest->flags & NSF_EXTENDED) != 0) options |= PCRE2_EXTENDED;
+ else options &= ~PCRE2_EXTENDED;
+ if ((top_nest->flags & NSF_DUPNAMES) != 0) options |= PCRE2_DUPNAMES;
+ else options &= ~PCRE2_DUPNAMES;
+ if (top_nest == (nest_save *)(cb->start_workspace)) top_nest = NULL;
+ else top_nest--;
+ }
+ if (nest_depth == 0) /* Unmatched closing parenthesis */
+ {
+ errorcode = ERR22;
+ goto FAILED;
+ }
+ nest_depth--;
+ break;
+ }
+ }
+
+if (nest_depth == 0)
+ {
+ cb->final_bracount = cb->bracount;
+ return 0;
+ }
+
+/* We give a special error for a missing closing parentheses after (?# because
+it might otherwise be hard to see where the missing character is. */
+
+errorcode = (skiptoket == CHAR_NUMBER_SIGN)? ERR18 : ERR14;
+
+FAILED:
+*ptrptr = ptr;
+return errorcode;
+}
+
+
+
+/*************************************************
* Compile one branch *
*************************************************/
@@ -4435,13 +3837,13 @@ Arguments:
codeptr points to the pointer to the current code point
ptrptr points to the current pattern pointer
errorcodeptr points to error code variable
- firstcharptr place to put the first required character
- firstcharflagsptr place to put the first character flags, or a negative number
- reqcharptr place to put the last required character
- reqcharflagsptr place to put the last required character flags, or a negative number
+ firstcuptr place to put the first required code unit
+ firstcuflagsptr place to put the first code unit flags, or a negative number
+ reqcuptr place to put the last required code unit
+ reqcuflagsptr place to put the last required code unit flags, or a negative number
bcptr points to current branch chain
cond_depth conditional nesting depth
- cd contains pointers to tables etc.
+ cb contains pointers to tables etc.
lengthptr NULL during the real compile phase
points to length accumulator during pre-compile phase
@@ -4450,52 +3852,50 @@ Returns: TRUE on success
*/
static BOOL
-compile_branch(int *optionsptr, pcre_uchar **codeptr,
- const pcre_uchar **ptrptr, int *errorcodeptr,
- pcre_uint32 *firstcharptr, pcre_int32 *firstcharflagsptr,
- pcre_uint32 *reqcharptr, pcre_int32 *reqcharflagsptr,
+compile_branch(uint32_t *optionsptr, PCRE2_UCHAR **codeptr,
+ PCRE2_SPTR *ptrptr, int *errorcodeptr,
+ uint32_t *firstcuptr, int32_t *firstcuflagsptr,
+ uint32_t *reqcuptr, int32_t *reqcuflagsptr,
branch_chain *bcptr, int cond_depth,
- compile_data *cd, int *lengthptr)
+ compile_block *cb, size_t *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_uint32 firstchar, reqchar;
-pcre_int32 firstcharflags, reqcharflags;
-pcre_uint32 zeroreqchar, zerofirstchar;
-pcre_int32 zeroreqcharflags, zerofirstcharflags;
-pcre_int32 req_caseopt, reqvary, tempreqvary;
-int options = *optionsptr; /* May change dynamically */
+uint32_t greedy_default, greedy_non_default;
+uint32_t repeat_type, op_type;
+uint32_t options = *optionsptr; /* May change dynamically */
+uint32_t firstcu, reqcu;
+int32_t firstcuflags, reqcuflags;
+uint32_t zeroreqcu, zerofirstcu;
+int32_t zeroreqcuflags, zerofirstcuflags;
+int32_t req_caseopt, reqvary, tempreqvary;
int after_manual_callout = 0;
-int length_prevgroup = 0;
-register pcre_uint32 c;
int escape;
-register pcre_uchar *code = *codeptr;
-pcre_uchar *last_code = code;
-pcre_uchar *orig_code = code;
-pcre_uchar *tempcode;
+size_t length_prevgroup = 0;
+register uint32_t c;
+register PCRE2_UCHAR *code = *codeptr;
+PCRE2_UCHAR *last_code = code;
+PCRE2_UCHAR *orig_code = code;
+PCRE2_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;
-size_t item_hwm_offset = 0;
-pcre_uint8 classbits[32];
-
-/* We can fish out the UTF-8 setting once and for all into a BOOL, but we
-must not do this for other options (e.g. PCRE_EXTENDED) because they may change
+BOOL groupsetfirstcu = FALSE;
+PCRE2_SPTR ptr = *ptrptr;
+PCRE2_SPTR tempptr;
+PCRE2_UCHAR *previous = NULL;
+PCRE2_UCHAR *previous_callout = NULL;
+uint8_t classbits[32];
+
+/* We can fish out the UTF setting once and for all into a BOOL, but we must
+not do this for other options (e.g. PCRE2_EXTENDED) because they may change
dynamically as we process the pattern. */
-#ifdef SUPPORT_UTF
-/* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */
-BOOL utf = (options & PCRE_UTF8) != 0;
-#ifndef COMPILE_PCRE32
-pcre_uchar utf_chars[6];
+#ifdef SUPPORT_UNICODE
+BOOL utf = (options & PCRE2_UTF) != 0;
+#if PCRE2_CODE_UNIT_WIDTH != 32
+PCRE2_UCHAR utf_units[6]; /* For setting up multi-cu chars */
#endif
-#else
+
+#else /* No UTF support */
BOOL utf = FALSE;
#endif
@@ -4504,41 +3904,36 @@ class_uchardata always so that it can be passed to add_to_class() always,
though it will not be used in non-UTF 8-bit cases. This avoids having to supply
alternative calls for the different cases. */
-pcre_uchar *class_uchardata;
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+PCRE2_UCHAR *class_uchardata;
+#ifdef SUPPORT_WIDE_CHARS
BOOL xclass;
-pcre_uchar *class_uchardata_base;
-#endif
-
-#ifdef PCRE_DEBUG
-if (lengthptr != NULL) DPRINTF((">> start branch\n"));
+PCRE2_UCHAR *class_uchardata_base;
#endif
/* Set up the default and non-default settings for greediness */
-greedy_default = ((options & PCRE_UNGREEDY) != 0);
+greedy_default = ((options & PCRE2_UNGREEDY) != 0);
greedy_non_default = greedy_default ^ 1;
-/* Initialize no first byte, no required byte. REQ_UNSET means "no char
+/* Initialize no first unit, no required unit. REQ_UNSET means "no char
matching encountered yet". It gets changed to REQ_NONE if we hit something that
-matches a non-fixed char first char; reqchar just remains unset if we never
-find one.
+matches a non-fixed first unit; reqcu just remains unset if we never find one.
When we hit a repeat whose minimum is zero, we may have to adjust these values
to take the zero repeat into account. This is implemented by setting them to
-zerofirstbyte and zeroreqchar when such a repeat is encountered. The individual
+zerofirstcu and zeroreqcu when such a repeat is encountered. The individual
item types that can be repeated set these backoff variables appropriately. */
-firstchar = reqchar = zerofirstchar = zeroreqchar = 0;
-firstcharflags = reqcharflags = zerofirstcharflags = zeroreqcharflags = REQ_UNSET;
+firstcu = reqcu = zerofirstcu = zeroreqcu = 0;
+firstcuflags = reqcuflags = zerofirstcuflags = zeroreqcuflags = REQ_UNSET;
-/* The variable req_caseopt contains either the REQ_CASELESS value
-or zero, according to the current setting of the caseless flag. The
-REQ_CASELESS 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. */
+/* The variable req_caseopt contains either the REQ_CASELESS value or zero,
+according to the current setting of the caseless flag. The REQ_CASELESS value
+leaves the lower 28 bit empty. It is added into the firstcu or reqcu variables
+to record the case status of the value. This is used only for ASCII characters.
+*/
-req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS:0;
+req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS:0;
/* Switch on next character until the end of the branch */
@@ -4546,28 +3941,30 @@ for (;; ptr++)
{
BOOL negate_class;
BOOL should_flip_negation;
+ BOOL match_all_or_no_wide_chars;
BOOL possessive_quantifier;
BOOL is_quantifier;
BOOL is_recurse;
+ BOOL is_dupname;
BOOL reset_bracount;
int class_has_8bitchar;
int class_one_char;
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#ifdef SUPPORT_WIDE_CHARS
BOOL xclass_has_prop;
#endif
- int newoptions;
- int recno;
- int refsign;
- int skipbytes;
- pcre_uint32 subreqchar, subfirstchar;
- pcre_int32 subreqcharflags, subfirstcharflags;
- int terminator;
+ int recno; /* Must be signed */
+ int refsign; /* Must be signed */
+ int terminator; /* Must be signed */
unsigned int mclength;
unsigned int tempbracount;
- pcre_uint32 ec;
- pcre_uchar mcbuffer[8];
+ uint32_t ec;
+ uint32_t newoptions;
+ uint32_t skipunits;
+ uint32_t subreqcu, subfirstcu;
+ int32_t subreqcuflags, subfirstcuflags; /* Must be signed */
+ PCRE2_UCHAR mcbuffer[8];
- /* Come here to restart the loop without advancing the pointer. */
+ /* Come here to restart the loop. */
REDO_LOOP:
@@ -4576,12 +3973,14 @@ for (;; ptr++)
c = *ptr;
/* If we are at the end of a nested substitution, revert to the outer level
- string. Nesting only happens one level deep. */
+ string. Nesting only happens one or two levels deep, and the inserted string
+ is always zero terminated. */
- if (c == CHAR_NULL && nestptr != NULL)
+ if (c == CHAR_NULL && cb->nestptr[0] != NULL)
{
- ptr = nestptr;
- nestptr = NULL;
+ ptr = cb->nestptr[0];
+ cb->nestptr[0] = cb->nestptr[1];
+ cb->nestptr[1] = NULL;
c = *ptr;
}
@@ -4590,14 +3989,11 @@ for (;; ptr++)
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 -
+ if (code > cb->start_workspace + cb->workspace_size -
WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */
{
- *errorcodeptr = (code >= cd->start_workspace + cd->workspace_size)?
- ERR52 : ERR87;
+ *errorcodeptr = (code >= cb->start_workspace + cb->workspace_size)?
+ ERR52 : ERR86;
goto FAILED;
}
@@ -4611,15 +4007,12 @@ for (;; ptr++)
/* Paranoid check for integer overflow */
- if (OFLOW_MAX - *lengthptr < code - last_code)
+ if (OFLOW_MAX - *lengthptr < (size_t)(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));
+ *lengthptr += (size_t)(code - last_code);
/* 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,
@@ -4629,7 +4022,7 @@ for (;; ptr++)
{
if (previous > orig_code)
{
- memmove(orig_code, previous, IN_UCHARS(code - previous));
+ memmove(orig_code, previous, (size_t)CU2BYTES(code - previous));
code -= previous - orig_code;
previous = orig_code;
}
@@ -4642,19 +4035,18 @@ for (;; ptr++)
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)
- {
- *errorcodeptr = ERR52;
- goto FAILED;
- }
+ /* Before doing anything else we must handle all the special items that do
+ nothing, and which may come between an item and its quantifier. Otherwise,
+ when auto-callouts are enabled, a callout gets incorrectly inserted before
+ the quantifier is recognized. After recognizing a "do nothing" item, restart
+ the loop in case another one follows. */
- /* If in \Q...\E, check for the end; if not, we have a literal. Otherwise an
- isolated \E is ignored. */
+ /* If c is not NULL we are not at the end of the pattern. If it is NULL, we
+ may still be in the pattern with a NULL data item. In these cases, if we are
+ in \Q...\E, check for the \E that ends the literal string; if not, we have a
+ literal character. If not in \Q...\E, an isolated \E is ignored. */
- if (c != CHAR_NULL)
+ if (c != CHAR_NULL || ptr < cb->end_pattern)
{
if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E)
{
@@ -4662,18 +4054,18 @@ for (;; ptr++)
ptr++;
continue;
}
- else if (inescq)
+ else if (inescq) /* Literal character */
{
if (previous_callout != NULL)
{
if (lengthptr == NULL) /* Don't attempt in pre-compile phase */
- complete_callout(previous_callout, ptr, cd);
+ complete_callout(previous_callout, ptr, cb);
previous_callout = NULL;
}
- if ((options & PCRE_AUTO_CALLOUT) != 0)
+ if ((options & PCRE2_AUTO_CALLOUT) != 0)
{
previous_callout = code;
- code = auto_callout(code, ptr, cd);
+ code = auto_callout(code, ptr, cb);
}
goto NORMAL_CHAR;
}
@@ -4690,24 +4082,24 @@ for (;; ptr++)
}
}
- /* In extended mode, skip white space and comments. */
+ /* In extended mode, skip white space and #-comments that end at newline. */
- if ((options & PCRE_EXTENDED) != 0)
+ if ((options & PCRE2_EXTENDED) != 0)
{
- const pcre_uchar *wscptr = ptr;
- while (MAX_255(c) && (cd->ctypes[c] & ctype_space) != 0) c = *(++ptr);
+ PCRE2_SPTR wscptr = ptr;
+ while (MAX_255(c) && (cb->ctypes[c] & ctype_space) != 0) c = *(++ptr);
if (c == CHAR_NUMBER_SIGN)
{
ptr++;
- while (*ptr != CHAR_NULL)
+ while (ptr < cb->end_pattern)
{
if (IS_NEWLINE(ptr)) /* For non-fixed-length newline cases, */
- { /* IS_NEWLINE sets cd->nllen. */
- ptr += cd->nllen;
+ { /* IS_NEWLINE sets cb->nllen. */
+ ptr += cb->nllen;
break;
}
ptr++;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf) FORWARDCHAR(ptr);
#endif
}
@@ -4719,16 +4111,14 @@ for (;; ptr++)
if (ptr > wscptr) goto REDO_LOOP;
}
- /* Skip over (?# comments. We need to do this here because we want to know if
- the next thing is a quantifier, and these comments may come between an item
- and its quantifier. */
+ /* Skip over (?# comments. */
if (c == CHAR_LEFT_PARENTHESIS && ptr[1] == CHAR_QUESTION_MARK &&
ptr[2] == CHAR_NUMBER_SIGN)
{
ptr += 3;
- while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
- if (*ptr == CHAR_NULL)
+ while (ptr < cb->end_pattern && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
+ if (*ptr != CHAR_RIGHT_PARENTHESIS)
{
*errorcodeptr = ERR18;
goto FAILED;
@@ -4736,30 +4126,31 @@ for (;; ptr++)
continue;
}
- /* See if the next thing is a quantifier. */
+ /* End of processing "do nothing" items. See if 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));
+ (c == CHAR_LEFT_CURLY_BRACKET && is_counted_repeat(ptr+1));
- /* Fill in length of a previous callout, except when the next thing is a
- quantifier or when processing a property substitution string in UCP mode. */
+ /* Fill in length of a previous callout and create an auto callout if
+ required, except when the next thing is a quantifier or when processing a
+ property substitution string for \w etc in UCP mode. */
- if (!is_quantifier && previous_callout != NULL && nestptr == NULL &&
- after_manual_callout-- <= 0)
+ if (!is_quantifier && cb->nestptr[0] == NULL)
{
- if (lengthptr == NULL) /* Don't attempt in pre-compile phase */
- complete_callout(previous_callout, ptr, cd);
- previous_callout = NULL;
- }
-
- /* Create auto callout, except for quantifiers, or while processing property
- strings that are substituted for \w etc in UCP mode. */
+ if (previous_callout != NULL && after_manual_callout-- <= 0)
+ {
+ if (lengthptr == NULL) /* Don't attempt in pre-compile phase */
+ complete_callout(previous_callout, ptr, cb);
+ previous_callout = NULL;
+ }
- if ((options & PCRE_AUTO_CALLOUT) != 0 && !is_quantifier && nestptr == NULL)
- {
- previous_callout = code;
- code = auto_callout(code, ptr, cd);
+ if ((options & PCRE2_AUTO_CALLOUT) != 0)
+ {
+ previous_callout = code;
+ code = auto_callout(code, ptr, cb);
+ }
}
/* Process the next pattern item. */
@@ -4767,24 +4158,28 @@ for (;; ptr++)
switch(c)
{
/* ===================================================================*/
- case CHAR_NULL: /* The branch terminates at string end */
- case CHAR_VERTICAL_LINE: /* or | or ) */
+ /* The branch terminates at string end or | or ) */
+
+ case CHAR_NULL:
+ if (ptr < cb->end_pattern) goto NORMAL_CHAR; /* Zero data character */
+ /* Fall through */
+
+ case CHAR_VERTICAL_LINE:
case CHAR_RIGHT_PARENTHESIS:
- *firstcharptr = firstchar;
- *firstcharflagsptr = firstcharflags;
- *reqcharptr = reqchar;
- *reqcharflagsptr = reqcharflags;
+ *firstcuptr = firstcu;
+ *firstcuflagsptr = firstcuflags;
+ *reqcuptr = reqcu;
+ *reqcuflagsptr = reqcuflags;
*codeptr = code;
*ptrptr = ptr;
if (lengthptr != NULL)
{
- if (OFLOW_MAX - *lengthptr < code - last_code)
+ if (OFLOW_MAX - *lengthptr < (size_t)(code - last_code))
{
*errorcodeptr = ERR20;
goto FAILED;
}
- *lengthptr += (int)(code - last_code); /* To include callout length */
- DPRINTF((">> end branch\n"));
+ *lengthptr += (size_t)(code - last_code); /* To include callout length */
}
return TRUE;
@@ -4795,10 +4190,10 @@ for (;; ptr++)
case CHAR_CIRCUMFLEX_ACCENT:
previous = NULL;
- if ((options & PCRE_MULTILINE) != 0)
+ if ((options & PCRE2_MULTILINE) != 0)
{
- if (firstcharflags == REQ_UNSET)
- zerofirstcharflags = firstcharflags = REQ_NONE;
+ if (firstcuflags == REQ_UNSET)
+ zerofirstcuflags = firstcuflags = REQ_NONE;
*code++ = OP_CIRCM;
}
else *code++ = OP_CIRC;
@@ -4806,21 +4201,20 @@ for (;; ptr++)
case CHAR_DOLLAR_SIGN:
previous = NULL;
- *code++ = ((options & PCRE_MULTILINE) != 0)? OP_DOLLM : OP_DOLL;
+ *code++ = ((options & PCRE2_MULTILINE) != 0)? OP_DOLLM : OP_DOLL;
break;
/* There can never be a first char if '.' is first, whatever happens about
- repeats. The value of reqchar doesn't change either. */
+ repeats. The value of reqcu doesn't change either. */
case CHAR_DOT:
- if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
- zerofirstchar = firstchar;
- zerofirstcharflags = firstcharflags;
- zeroreqchar = reqchar;
- zeroreqcharflags = reqcharflags;
+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
+ zerofirstcu = firstcu;
+ zerofirstcuflags = firstcuflags;
+ zeroreqcu = reqcu;
+ zeroreqcuflags = reqcuflags;
previous = code;
- item_hwm_offset = cd->hwm - cd->start_workspace;
- *code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY;
+ *code++ = ((options & PCRE2_DOTALL) != 0)? OP_ALLANY: OP_ANY;
break;
@@ -4836,34 +4230,31 @@ for (;; ptr++)
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. */
+ An isolated ']' character is not treated specially, so is just another data
+ character. In earlier versions of PCRE that used the original API there was
+ a "JavaScript compatibility mode" in which it gave an error. However,
+ JavaScript itself has changed in this respect so there is no longer any
+ need for this special handling.
- case CHAR_RIGHT_SQUARE_BRACKET:
- if ((cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0)
- {
- *errorcodeptr = ERR64;
- goto FAILED;
- }
- goto NORMAL_CHAR;
-
- /* In another (POSIX) regex library, the ugly syntax [[:<:]] and [[:>:]] is
+ In another (POSIX) regex library, the ugly syntax [[:<:]] and [[:>:]] is
used for "start of word" and "end of word". As these are otherwise illegal
sequences, we don't break anything by recognizing them. They are replaced
- by \b(?=\w) and \b(?<=\w) respectively. Sequences like [a[:<:]] are
- erroneous and are handled by the normal code below. */
+ by \b(?=\w) and \b(?<=\w) respectively. This can only happen at the top
+ nesting level, as no other inserted sequences will contains these oddities.
+ Sequences like [a[:<:]] are erroneous and are handled by the normal code
+ below. */
case CHAR_LEFT_SQUARE_BRACKET:
- if (STRNCMP_UC_C8(ptr+1, STRING_WEIRD_STARTWORD, 6) == 0)
+ if (PRIV(strncmp_c8)(ptr+1, STRING_WEIRD_STARTWORD, 6) == 0)
{
- nestptr = ptr + 7;
+ cb->nestptr[0] = ptr + 7;
ptr = sub_start_of_word;
goto REDO_LOOP;
}
- if (STRNCMP_UC_C8(ptr+1, STRING_WEIRD_ENDWORD, 6) == 0)
+ if (PRIV(strncmp_c8)(ptr+1, STRING_WEIRD_ENDWORD, 6) == 0)
{
- nestptr = ptr + 7;
+ cb->nestptr[0] = ptr + 7;
ptr = sub_end_of_word;
goto REDO_LOOP;
}
@@ -4871,7 +4262,6 @@ for (;; ptr++)
/* Handle a real character class. */
previous = code;
- item_hwm_offset = cd->hwm - cd->start_workspace;
/* PCRE supports POSIX class stuff inside a class. Perl gives an error if
they are encountered at the top level, so we'll do that too. */
@@ -4880,7 +4270,7 @@ for (;; ptr++)
ptr[1] == CHAR_EQUALS_SIGN) &&
check_posix_syntax(ptr, &tempptr))
{
- *errorcodeptr = (ptr[1] == CHAR_COLON)? ERR13 : ERR31;
+ *errorcodeptr = (ptr[1] == CHAR_COLON)? ERR12 : ERR13;
goto FAILED;
}
@@ -4896,7 +4286,7 @@ for (;; ptr++)
{
if (ptr[1] == CHAR_E)
ptr++;
- else if (STRNCMP_UC_C8(ptr + 1, STR_Q STR_BACKSLASH STR_E, 3) == 0)
+ else if (PRIV(strncmp_c8)(ptr + 1, STR_Q STR_BACKSLASH STR_E, 3) == 0)
ptr += 3;
else
break;
@@ -4906,86 +4296,82 @@ for (;; ptr++)
else break;
}
- /* Empty classes are allowed in JavaScript compatibility mode. Otherwise,
+ /* Empty classes are allowed if PCRE2_ALLOW_EMPTY_CLASS is set. 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. */
+ that. When empty classes are allowed, [] 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)
+ (cb->external_options & PCRE2_ALLOW_EMPTY_CLASS) != 0)
{
*code++ = negate_class? OP_ALLANY : OP_FAIL;
- if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
- zerofirstchar = firstchar;
- zerofirstcharflags = firstcharflags;
+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
+ zerofirstcu = firstcu;
+ zerofirstcuflags = firstcuflags;
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). */
+ /* If a non-extended class contains a negative special such as \S, we need
+ to flip the negation flag at the end, so that support for characters > 255
+ works correctly (they are all included in the class). An extended class may
+ need to insert specific matching or non-matching code for wide characters.
+ */
- should_flip_negation = FALSE;
+ should_flip_negation = match_all_or_no_wide_chars = FALSE;
/* Extended class (xclass) will be used when characters > 255
might match. */
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#ifdef SUPPORT_WIDE_CHARS
xclass = FALSE;
class_uchardata = code + LINK_SIZE + 2; /* For XCLASS items */
class_uchardata_base = class_uchardata; /* Save the start */
#endif
/* For optimization purposes, we track some properties of the class:
- class_has_8bitchar will be non-zero if the class contains at least one <
- 256 character; class_one_char will be 1 if the class contains just one
- character; xclass_has_prop will be TRUE if unicode property checks
- are present in the class. */
+ class_has_8bitchar will be non-zero if the class contains at least one 256
+ character with a code point less than 256; class_one_char will be 1 if the
+ class contains just one character; xclass_has_prop will be TRUE if Unicode
+ property checks are present in the class. */
class_has_8bitchar = 0;
class_one_char = 0;
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#ifdef SUPPORT_WIDE_CHARS
xclass_has_prop = FALSE;
#endif
- /* Initialize the 32-char bit map to all zeros. We build the map in a
- temporary bit of memory, in case the class contains fewer than two
+ /* Initialize the 256-bit (32-byte) bit map to all zeros. We build the map
+ in a temporary bit of memory, in case the class contains fewer than two
8-bit characters because in that case the compiled code doesn't use the bit
map. */
- memset(classbits, 0, 32 * sizeof(pcre_uint8));
+ memset(classbits, 0, 32 * sizeof(uint8_t));
- /* 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. */
+ /* Process characters until ] is reached. As the test is at the end of the
+ loop, an initial ] is taken as a data character. At the start of the loop,
+ c contains the first code unit of the character. If it is zero, check for
+ the end of the pattern, to allow binary zero as data. */
- if (c != CHAR_NULL) do
+ for(;;)
{
- const pcre_uchar *oldptr;
+ PCRE2_SPTR oldptr;
+#ifdef EBCDIC
+ BOOL range_is_literal = TRUE;
+#endif
-#ifdef SUPPORT_UTF
+ if (c == CHAR_NULL && ptr >= cb->end_pattern)
+ {
+ *errorcodeptr = ERR6; /* Missing terminating ']' */
+ goto FAILED;
+ }
+
+#ifdef SUPPORT_UNICODE
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). We have to remember that there was XCLASS data,
- however. */
-
- if (class_uchardata > class_uchardata_base) xclass = TRUE;
-
- if (lengthptr != NULL && class_uchardata > class_uchardata_base)
- {
- *lengthptr += (int)(class_uchardata - class_uchardata_base);
- class_uchardata = class_uchardata_base;
- }
-#endif
-
/* Inside \Q...\E everything is literal except \E */
if (inescq)
@@ -4994,7 +4380,7 @@ for (;; ptr++)
{
inescq = FALSE; /* Reset literal state */
ptr++; /* Skip the 'E' */
- continue; /* Carry on with next */
+ goto CONTINUE_CLASS; /* Carry on with next char */
}
goto CHECK_RANGE; /* Could be range if \E follows */
}
@@ -5011,12 +4397,12 @@ for (;; ptr++)
{
BOOL local_negate = FALSE;
int posix_class, taboffset, tabopt;
- register const pcre_uint8 *cbits = cd->cbits;
- pcre_uint8 pbits[32];
+ register const uint8_t *cbits = cb->cbits;
+ uint8_t pbits[32];
if (ptr[1] != CHAR_COLON)
{
- *errorcodeptr = ERR31;
+ *errorcodeptr = ERR13;
goto FAILED;
}
@@ -5039,28 +4425,30 @@ for (;; ptr++)
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)
+ if ((options & PCRE2_CASELESS) != 0 && posix_class <= 2)
posix_class = 0;
- /* When PCRE_UCP is set, some of the POSIX classes are converted to
+ /* When PCRE2_UCP is set, some of the POSIX classes are converted to
different escape sequences that use Unicode properties \p or \P. Others
that are not available via \p or \P generate XCL_PROP/XCL_NOTPROP
- directly. */
+ directly. UCP support is not available unless UTF support is.*/
-#ifdef SUPPORT_UCP
- if ((options & PCRE_UCP) != 0)
+#ifdef SUPPORT_UNICODE
+ if ((options & PCRE2_UCP) != 0)
{
unsigned int ptype = 0;
int pc = posix_class + ((local_negate)? POSIX_SUBSIZE/2 : 0);
/* The posix_substitutes table specifies which POSIX classes can be
- converted to \p or \P items. */
+ converted to \p or \P items. This can only happen at top nestling
+ level, as there will never be a POSIX class in a string that is
+ substituted for something else. */
if (posix_substitutes[pc] != NULL)
{
- nestptr = tempptr + 1;
+ cb->nestptr[0] = tempptr + 1;
ptr = posix_substitutes[pc] - 1;
- continue;
+ goto CONTINUE_CLASS;
}
/* There are three other classes that generate special property calls
@@ -5077,38 +4465,33 @@ for (;; ptr++)
case PC_PUNCT:
if (ptype == 0) ptype = PT_PXPUNCT;
*class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP;
- *class_uchardata++ = ptype;
+ *class_uchardata++ = (PCRE2_UCHAR)ptype;
*class_uchardata++ = 0;
xclass_has_prop = TRUE;
ptr = tempptr + 1;
- continue;
-
- /* For the other POSIX classes (ascii, cntrl, xdigit) we are going
- to fall through to the non-UCP case and build a bit map for
- characters with code points less than 256. If we are in a negated
- POSIX class, characters with code points greater than 255 must
- either all match or all not match. In the special case where we
- have not yet generated any xclass data, and this is the final item
- in the overall class, we need do nothing: later on, the opcode
- OP_NCLASS will be used to indicate that characters greater than 255
- are acceptable. If we have already seen an xclass item or one may
- follow (we have to assume that it might if this is not the end of
- the class), explicitly list all wide codepoints, which will then
- either not match or match, depending on whether the class is or is
- not negated. */
+ goto CONTINUE_CLASS;
+
+ /* For the other POSIX classes (ascii, xdigit) we are going to fall
+ through to the non-UCP case and build a bit map for characters with
+ code points less than 256. However, if we are in a negated POSIX
+ class, characters with code points greater than 255 must either all
+ match or all not match, depending on whether the whole class is not
+ or is negated. For example, for [[:^ascii:]... they must all match,
+ whereas for [^[:^xdigit:]... they must not.
+
+ In the special case where there are no xclass items, this is
+ automatically handled by the use of OP_CLASS or OP_NCLASS, but an
+ explicit range is needed for OP_XCLASS. Setting a flag here causes
+ the range to be generated later when it is known that OP_XCLASS is
+ required. */
default:
- if (local_negate &&
- (xclass || tempptr[2] != CHAR_RIGHT_SQUARE_BRACKET))
- {
- *class_uchardata++ = XCL_RANGE;
- class_uchardata += PRIV(ord2utf)(0x100, class_uchardata);
- class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata);
- }
+ match_all_or_no_wide_chars |= local_negate;
break;
}
}
-#endif
+#endif /* SUPPORT_UNICODE */
+
/* In the non-UCP case, or when UCP makes no difference, we build the
bit map for the POSIX class in a chunk of local store because we may be
adding and subtracting from it, and we don't want to subtract bits that
@@ -5120,7 +4503,7 @@ for (;; ptr++)
/* Copy in the first table (always present) */
memcpy(pbits, cbits + posix_class_maps[posix_class],
- 32 * sizeof(pcre_uint8));
+ 32 * sizeof(uint8_t));
/* If there is a second table, add or remove it as required. */
@@ -5130,9 +4513,9 @@ for (;; ptr++)
if (taboffset >= 0)
{
if (tabopt >= 0)
- for (c = 0; c < 32; c++) pbits[c] |= cbits[c + taboffset];
+ for (c = 0; c < 32; c++) pbits[c] |= cbits[(int)c + taboffset];
else
- for (c = 0; c < 32; c++) pbits[c] &= ~cbits[c + taboffset];
+ for (c = 0; c < 32; c++) pbits[c] &= ~cbits[(int)c + taboffset];
}
/* Now see if we need to remove any special characters. An option
@@ -5155,7 +4538,7 @@ for (;; ptr++)
class_has_8bitchar = 1;
/* Every class contains at least two characters. */
class_one_char = 2;
- continue; /* End of POSIX syntax handling */
+ goto CONTINUE_CLASS; /* End of POSIX syntax handling */
}
/* Backslash may introduce a single character, or it may introduce one
@@ -5163,16 +4546,20 @@ for (;; ptr++)
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_one_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. */
+ than one. Unrecognized escapes fall through and are faulted. */
if (c == CHAR_BACKSLASH)
{
- escape = check_escape(&ptr, &ec, errorcodeptr, cd->bracount, options,
- TRUE);
+ escape = PRIV(check_escape)(&ptr, cb->end_pattern, &ec, errorcodeptr,
+ options, TRUE, cb);
if (*errorcodeptr != 0) goto FAILED;
- if (escape == 0) c = ec;
+ if (escape == 0) /* Escaped single char */
+ {
+ c = ec;
+#ifdef EBCDIC
+ range_is_literal = FALSE;
+#endif
+ }
else if (escape == ESC_b) c = CHAR_BS; /* \b is backspace in a class */
else if (escape == ESC_N) /* \N is not supported in a class */
{
@@ -5186,13 +4573,13 @@ for (;; ptr++)
ptr += 2; /* avoid empty string */
}
else inescq = TRUE;
- continue;
+ goto CONTINUE_CLASS;
}
- else if (escape == ESC_E) continue; /* Ignore orphan \E */
+ else if (escape == ESC_E) goto CONTINUE_CLASS; /* Ignore orphan \E */
- else
+ else /* Handle \d-type escapes */
{
- register const pcre_uint8 *cbits = cd->cbits;
+ register const uint8_t *cbits = cb->cbits;
/* Every class contains at least two < 256 characters. */
class_has_8bitchar++;
/* Every class contains at least two characters. */
@@ -5200,35 +4587,36 @@ for (;; ptr++)
switch (escape)
{
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
case ESC_du: /* These are the values given for \d etc */
- case ESC_DU: /* when PCRE_UCP is set. We replace the */
+ case ESC_DU: /* when PCRE2_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;
+ case ESC_su: /* of the default ASCII testing. This might be */
+ case ESC_SU: /* a 2nd-level nesting for [[:<:]] or [[:>:]]. */
+ cb->nestptr[1] = cb->nestptr[0];
+ cb->nestptr[0] = ptr;
ptr = substitutes[escape - ESC_DU] - 1; /* Just before substitute */
class_has_8bitchar--; /* Undo! */
- continue;
+ break;
#endif
case ESC_d:
for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_digit];
- continue;
+ break;
case ESC_D:
should_flip_negation = TRUE;
for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_digit];
- continue;
+ break;
case ESC_w:
for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_word];
- continue;
+ break;
case ESC_W:
should_flip_negation = TRUE;
for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_word];
- continue;
+ break;
/* Perl 5.004 onwards omitted VT from \s, but restored it at Perl
5.18. Before PCRE 8.34, we had to preserve the VT bit if it was
@@ -5239,42 +4627,42 @@ for (;; ptr++)
case ESC_s:
for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_space];
- continue;
+ break;
case ESC_S:
should_flip_negation = TRUE;
for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_space];
- continue;
+ break;
/* The rest apply in both UCP and non-UCP cases. */
case ESC_h:
- (void)add_list_to_class(classbits, &class_uchardata, options, cd,
+ (void)add_list_to_class(classbits, &class_uchardata, options, cb,
PRIV(hspace_list), NOTACHAR);
- continue;
+ break;
case ESC_H:
(void)add_not_list_to_class(classbits, &class_uchardata, options,
- cd, PRIV(hspace_list));
- continue;
+ cb, PRIV(hspace_list));
+ break;
case ESC_v:
- (void)add_list_to_class(classbits, &class_uchardata, options, cd,
+ (void)add_list_to_class(classbits, &class_uchardata, options, cb,
PRIV(vspace_list), NOTACHAR);
- continue;
+ break;
case ESC_V:
(void)add_not_list_to_class(classbits, &class_uchardata, options,
- cd, PRIV(vspace_list));
- continue;
+ cb, PRIV(vspace_list));
+ break;
case ESC_p:
case ESC_P:
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
{
BOOL negated;
unsigned int ptype = 0, pdata = 0;
- if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr))
+ if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr, cb))
goto FAILED;
*class_uchardata++ = ((escape == ESC_p) != negated)?
XCL_PROP : XCL_NOTPROP;
@@ -5282,34 +4670,28 @@ for (;; ptr++)
*class_uchardata++ = pdata;
xclass_has_prop = TRUE;
class_has_8bitchar--; /* Undo! */
- continue;
}
+ break;
#else
*errorcodeptr = ERR45;
goto FAILED;
#endif
- /* Unrecognized escapes are faulted if PCRE is running in its
- strict mode. By default, for compatibility with Perl, they are
- treated as literals. */
+ /* Unrecognized escapes are faulted. */
default:
- if ((options & PCRE_EXTRA) != 0)
- {
- *errorcodeptr = ERR7;
- goto FAILED;
- }
- class_has_8bitchar--; /* Undo the speculative increase. */
- class_one_char -= 2; /* Undo the speculative increase. */
- c = *ptr; /* Get the final character and fall through */
- break;
+ *errorcodeptr = ERR7;
+ goto FAILED;
}
+
+ /* Handled \d-type escape */
+
+ goto CONTINUE_CLASS;
}
- /* Fall through if the escape just defined a single character (c >= 0).
- This may be greater than 256. */
+ /* Control gets here if the escape just defined a single character.
+ This is in c and may be greater than 256. */
escape = 0;
-
} /* End of backslash handling */
/* A character may be followed by '-' to form a range. However, Perl does
@@ -5327,13 +4709,13 @@ for (;; ptr++)
/* Remember if \r or \n were explicitly used */
- if (c == CHAR_CR || c == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF;
+ if (c == CHAR_CR || c == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF;
/* Check for range */
if (!inescq && ptr[1] == CHAR_MINUS)
{
- pcre_uint32 d;
+ uint32_t d;
ptr += 2;
while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E) ptr += 2;
@@ -5360,14 +4742,14 @@ for (;; ptr++)
/* Otherwise, we have a potential range; pick up the next character */
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{ /* Braces are required because the */
GETCHARLEN(d, ptr, ptr); /* macro generates multiple statements */
}
else
#endif
- d = *ptr; /* Not UTF-8 mode */
+ d = *ptr; /* Not UTF mode */
/* The second part of a range can be a single-character escape
sequence, but not any of the other escapes. Perl treats a hyphen as a
@@ -5380,9 +4762,12 @@ for (;; ptr++)
if (d == CHAR_BACKSLASH)
{
int descape;
- descape = check_escape(&ptr, &d, errorcodeptr, cd->bracount, options, TRUE);
+ descape = PRIV(check_escape)(&ptr, cb->end_pattern, &d,
+ errorcodeptr, options, TRUE, cb);
if (*errorcodeptr != 0) goto FAILED;
-
+#ifdef EBCDIC
+ range_is_literal = FALSE;
+#endif
/* 0 means a character was put into d; \b is backspace; any other
special causes an error. */
@@ -5390,7 +4775,7 @@ for (;; ptr++)
{
if (descape == ESC_b) d = CHAR_BS; else
{
- *errorcodeptr = ERR83;
+ *errorcodeptr = ERR50;
goto FAILED;
}
}
@@ -5403,7 +4788,7 @@ for (;; ptr++)
ptr[1] == CHAR_EQUALS_SIGN) &&
check_posix_syntax(ptr, &tempptr))
{
- *errorcodeptr = ERR83;
+ *errorcodeptr = ERR50;
goto FAILED;
}
}
@@ -5426,12 +4811,51 @@ for (;; ptr++)
/* Remember an explicit \r or \n, and add the range to the class. */
- if (d == CHAR_CR || d == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF;
+ if (d == CHAR_CR || d == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF;
- class_has_8bitchar +=
- add_to_class(classbits, &class_uchardata, options, cd, c, d);
+ /* In an EBCDIC environment, Perl treats alphabetic ranges specially
+ because there are holes in the encoding, and simply using the range A-Z
+ (for example) would include the characters in the holes. This applies
+ only to literal ranges; [\xC1-\xE9] is different to [A-Z]. */
+
+#ifdef EBCDIC
+ if (range_is_literal &&
+ (cb->ctypes[c] & ctype_letter) != 0 &&
+ (cb->ctypes[d] & ctype_letter) != 0 &&
+ (c <= CHAR_z) == (d <= CHAR_z))
+ {
+ uint32_t uc = (c <= CHAR_z)? 0 : 64;
+ uint32_t C = c - uc;
+ uint32_t D = d - uc;
+
+ if (C <= CHAR_i)
+ {
+ class_has_8bitchar +=
+ add_to_class(classbits, &class_uchardata, options, cb, C + uc,
+ ((D < CHAR_i)? D : CHAR_i) + uc);
+ C = CHAR_j;
+ }
- continue; /* Go get the next char in the class */
+ if (C <= D && C <= CHAR_r)
+ {
+ class_has_8bitchar +=
+ add_to_class(classbits, &class_uchardata, options, cb, C + uc,
+ ((D < CHAR_r)? D : CHAR_r) + uc);
+ C = CHAR_s;
+ }
+
+ if (C <= D)
+ {
+ class_has_8bitchar +=
+ add_to_class(classbits, &class_uchardata, options, cb, C + uc,
+ D + uc);
+ }
+ }
+ else
+#endif
+ class_has_8bitchar +=
+ add_to_class(classbits, &class_uchardata, options, cb, c, d);
+ goto CONTINUE_CLASS; /* Go get the next char in the class */
}
/* Handle a single character - we can get here for a normal non-escape
@@ -5443,40 +4867,40 @@ for (;; ptr++)
CLASS_SINGLE_CHARACTER:
if (class_one_char < 2) class_one_char++;
- /* If xclass_has_prop is false and class_one_char is 1, we have the first
+ /* If class_one_char is 1 and xclass_has_prop is false, we have the first
single character in the class, and there have been no prior ranges, or
XCLASS items generated by escapes. If this is the final character in the
class, we can optimize by turning the item into a 1-character OP_CHAR[I]
if it's positive, or OP_NOT[I] if it's negative. In the positive case, it
- can cause firstchar to be set. Otherwise, there can be no first char if
+ can cause firstcu 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. */
+ reqcu, save the previous value for reinstating. */
if (!inescq &&
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
!xclass_has_prop &&
#endif
class_one_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
{
ptr++;
- zeroreqchar = reqchar;
- zeroreqcharflags = reqcharflags;
+ zeroreqcu = reqcu;
+ zeroreqcuflags = reqcuflags;
if (negate_class)
{
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
int d;
#endif
- if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
- zerofirstchar = firstchar;
- zerofirstcharflags = firstcharflags;
+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
+ zerofirstcu = firstcu;
+ zerofirstcuflags = firstcuflags;
- /* For caseless UTF-8 mode when UCP support is available, check
- whether this character has more than one other case. If so, generate
- a special OP_NOTPROP item instead of OP_NOTI. */
+ /* For caseless UTF mode, check whether this character has more than
+ one other case. If so, generate a special OP_NOTPROP item instead of
+ OP_NOTI. */
-#ifdef SUPPORT_UCP
- if (utf && (options & PCRE_CASELESS) != 0 &&
+#ifdef SUPPORT_UNICODE
+ if (utf && (options & PCRE2_CASELESS) != 0 &&
(d = UCD_CASESET(c)) != 0)
{
*code++ = OP_NOTPROP;
@@ -5488,13 +4912,8 @@ for (;; ptr++)
/* Char has only one other case, or UCP not available */
{
- *code++ = ((options & PCRE_CASELESS) != 0)? OP_NOTI: OP_NOT;
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
- if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR)
- code += PRIV(ord2utf)(c, code);
- else
-#endif
- *code++ = c;
+ *code++ = ((options & PCRE2_CASELESS) != 0)? OP_NOTI: OP_NOT;
+ code += PUTCHAR(c, code);
}
/* We are finished with this character class */
@@ -5505,15 +4924,7 @@ for (;; ptr++)
/* For a single, positive character, get the value into mcbuffer, and
then we can handle this with the normal one-character code. */
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
- if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR)
- mclength = PRIV(ord2utf)(c, mcbuffer);
- else
-#endif
- {
- mcbuffer[0] = c;
- mclength = 1;
- }
+ mclength = PUTCHAR(c, mcbuffer);
goto ONE_CHAR;
} /* End of 1-char optimization */
@@ -5521,64 +4932,85 @@ for (;; ptr++)
has been generated. Add this character to the class. */
class_has_8bitchar +=
- add_to_class(classbits, &class_uchardata, options, cd, c, c);
- }
-
- /* 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)) != CHAR_NULL ||
- (nestptr != NULL &&
- (ptr = nestptr, nestptr = NULL, c = *(++ptr)) != CHAR_NULL)) &&
- (c != CHAR_RIGHT_SQUARE_BRACKET || inescq));
+ add_to_class(classbits, &class_uchardata, options, cb, c, c);
- /* Check for missing terminating ']' */
+ /* Continue to the next character in the class. Closing square bracket
+ not within \Q..\E ends the class. A NULL character terminates a
+ nested substitution string, but may be a data character in the main
+ pattern (tested at the start of this loop). */
- if (c == CHAR_NULL)
- {
- *errorcodeptr = ERR6;
- goto FAILED;
- }
+ CONTINUE_CLASS:
+ c = *(++ptr);
+ if (c == CHAR_NULL && cb->nestptr[0] != NULL)
+ {
+ ptr = cb->nestptr[0];
+ cb->nestptr[0] = cb->nestptr[1];
+ cb->nestptr[1] = NULL;
+ c = *(++ptr);
+ }
- /* We will need an XCLASS if data has been placed in class_uchardata. In
- the second phase this is a sufficient test. However, in the pre-compile
- phase, class_uchardata gets emptied to prevent workspace overflow, so it
- only if the very last character in the class needs XCLASS will it contain
- anything at this point. For this reason, xclass gets set TRUE above when
- uchar_classdata is emptied, and that's why this code is the way it is here
- instead of just doing a test on class_uchardata below. */
+#ifdef SUPPORT_WIDE_CHARS
+ /* If any wide characters have been encountered, set xclass = TRUE. Then,
+ in the pre-compile phase, accumulate the length of the wide characters
+ and reset the pointer. This is so that very large classes that contain a
+ zillion wide characters do not overwrite the work space (which is on the
+ stack). */
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
- if (class_uchardata > class_uchardata_base) xclass = TRUE;
+ if (class_uchardata > class_uchardata_base)
+ {
+ xclass = TRUE;
+ if (lengthptr != NULL)
+ {
+ *lengthptr += class_uchardata - class_uchardata_base;
+ class_uchardata = class_uchardata_base;
+ }
+ }
#endif
+ /* An unescaped ] ends the class */
+
+ if (c == CHAR_RIGHT_SQUARE_BRACKET && !inescq) break;
+ } /* End of main class-processing loop */
/* 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
+ setting, whatever the repeat count. Any reqcu setting must remain
unchanged after any kind of repeat. */
- if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
- zerofirstchar = firstchar;
- zerofirstcharflags = firstcharflags;
- zeroreqchar = reqchar;
- zeroreqcharflags = reqcharflags;
-
- /* 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 (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
+ zerofirstcu = firstcu;
+ zerofirstcuflags = firstcuflags;
+ zeroreqcu = reqcu;
+ zeroreqcuflags = reqcuflags;
+
+ /* If there are characters with values > 255, or Unicode property settings
+ (\p or \P), we have to compile an extended class, with its own opcode,
+ unless there were no property settings and there was a negated special such
+ as \S in the class, and PCRE2_UCP is not set, because in that case all
+ characters > 255 are in or not in the class, so any that were explicitly
+ given as well can be ignored.
+
+ In the UCP case, if certain negated POSIX classes ([:^ascii:] or
+ [^:xdigit:]) were present in a class, we either have to match or not match
+ all wide characters (depending on whether the whole class is or is not
+ negated). This requirement is indicated by match_all_or_no_wide_chars being
+ true. We do this by including an explicit range, which works in both cases.
+
+ If, when generating an xclass, there are no characters < 256, we can omit
+ the bitmap in the actual compiled code. */
+
+#ifdef SUPPORT_WIDE_CHARS
+#ifdef SUPPORT_UNICODE
if (xclass && (xclass_has_prop || !should_flip_negation ||
- (options & PCRE_UCP) != 0))
-#elif !defined COMPILE_PCRE8
+ (options & PCRE2_UCP) != 0))
+#elif PCRE2_CODE_UNIT_WIDTH != 8
if (xclass && (xclass_has_prop || !should_flip_negation))
#endif
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
{
+ if (match_all_or_no_wide_chars)
+ {
+ *class_uchardata++ = XCL_RANGE;
+ class_uchardata += PRIV(ord2utf)(0x100, class_uchardata);
+ class_uchardata += PRIV(ord2utf)(MAX_UTF_CODE_POINT, class_uchardata);
+ }
*class_uchardata++ = XCL_END; /* Marks the end of extra data */
*code++ = OP_XCLASS;
code += LINK_SIZE;
@@ -5591,12 +5023,12 @@ for (;; ptr++)
if (class_has_8bitchar > 0)
{
*code++ |= XCL_MAP;
- memmove(code + (32 / sizeof(pcre_uchar)), code,
- IN_UCHARS(class_uchardata - code));
+ memmove(code + (32 / sizeof(PCRE2_UCHAR)), code,
+ CU2BYTES(class_uchardata - code));
if (negate_class && !xclass_has_prop)
for (c = 0; c < 32; c++) classbits[c] = ~classbits[c];
memcpy(code, classbits, 32);
- code = class_uchardata + (32 / sizeof(pcre_uchar));
+ code = class_uchardata + (32 / sizeof(PCRE2_UCHAR));
}
else code = class_uchardata;
@@ -5605,12 +5037,6 @@ for (;; ptr++)
PUT(previous, 1, (int)(code - previous));
break; /* End of class handling */
}
-
- /* Even though any XCLASS list is now discarded, we must allow for
- its memory. */
-
- if (lengthptr != NULL)
- *lengthptr += (int)(class_uchardata - class_uchardata_base);
#endif
/* If there are no characters > 255, or they are all to be included or
@@ -5626,7 +5052,7 @@ for (;; ptr++)
for (c = 0; c < 32; c++) classbits[c] = ~classbits[c];
memcpy(code, classbits, 32);
}
- code += 32 / sizeof(pcre_uchar);
+ code += 32 / sizeof(PCRE2_UCHAR);
END_CLASS:
break;
@@ -5665,10 +5091,10 @@ for (;; ptr++)
if (repeat_min == 0)
{
- firstchar = zerofirstchar; /* Adjust for zero repeat */
- firstcharflags = zerofirstcharflags;
- reqchar = zeroreqchar; /* Ditto */
- reqcharflags = zeroreqcharflags;
+ firstcu = zerofirstcu; /* Adjust for zero repeat */
+ firstcuflags = zerofirstcuflags;
+ reqcu = zeroreqcu; /* Ditto */
+ reqcuflags = zeroreqcuflags;
}
/* Remember whether this is a variable length repeat */
@@ -5687,34 +5113,34 @@ for (;; ptr++)
whitespace and comments in extended mode because Perl allows white space at
this point. */
- if ((options & PCRE_EXTENDED) != 0)
+ if ((options & PCRE2_EXTENDED) != 0)
{
- const pcre_uchar *p = ptr + 1;
+ ptr++;
for (;;)
{
- while (MAX_255(*p) && (cd->ctypes[*p] & ctype_space) != 0) p++;
- if (*p != CHAR_NUMBER_SIGN) break;
- p++;
- while (*p != CHAR_NULL)
+ while (MAX_255(*ptr) && (cb->ctypes[*ptr] & ctype_space) != 0) ptr++;
+ if (*ptr != CHAR_NUMBER_SIGN) break;
+ ptr++;
+ while (ptr < cb->end_pattern)
{
- if (IS_NEWLINE(p)) /* For non-fixed-length newline cases, */
- { /* IS_NEWLINE sets cd->nllen. */
- p += cd->nllen;
+ if (IS_NEWLINE(ptr)) /* For non-fixed-length newline cases, */
+ { /* IS_NEWLINE sets cb->nllen. */
+ ptr += cb->nllen;
break;
}
- p++;
-#ifdef SUPPORT_UTF
- if (utf) FORWARDCHAR(p);
+ ptr++;
+#ifdef SUPPORT_UNICODE
+ if (utf) FORWARDCHAR(ptr);
#endif
} /* Loop for comment characters */
} /* Loop for multiple comments */
- ptr = p - 1; /* Character before the next significant one. */
+ ptr--; /* Last code unit of previous character. */
}
/* If the next character is '+', we have a possessive quantifier. This
- implies greediness, whatever the setting of the PCRE_UNGREEDY option.
+ implies greediness, whatever the setting of the PCRE2_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
+ but if PCRE2_UNGREEDY is set, it works the other way round. We change the
repeat type to the non-default. */
if (ptr[1] == CHAR_PLUS)
@@ -5730,6 +5156,10 @@ for (;; ptr++)
}
else repeat_type = greedy_default;
+ /* If the repeat is {1} we can ignore it. */
+
+ if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;
+
/* 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
@@ -5738,32 +5168,22 @@ for (;; ptr++)
if (*previous == OP_RECURSE)
{
- memmove(previous + 1 + LINK_SIZE, previous, IN_UCHARS(1 + LINK_SIZE));
+ memmove(previous + 1 + LINK_SIZE, previous, CU2BYTES(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 or negated character match, abolish the item
and generate a repeat item instead. If a char item has a minimum of more
- than one, ensure that it is set in reqchar - it might not be if a sequence
+ than one, ensure that it is set in reqcu - it might not be if a sequence
such as x{3} is the first thing in a branch because the x will have gone
- into firstchar instead. */
+ into firstcu instead. */
if (*previous == OP_CHAR || *previous == OP_CHARI
|| *previous == OP_NOT || *previous == OP_NOTI)
@@ -5777,31 +5197,31 @@ for (;; ptr++)
case OP_NOTI: op_type = OP_NOTSTARI - OP_STAR; break;
}
- /* Deal with UTF characters that take up more than one character. It's
+ /* Deal with UTF characters that take up more than one code unit. 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. */
+ hold the length of the character in code units, plus UTF_LENGTH to flag
+ that it's a length rather than a small character. */
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
- if (utf && NOT_FIRSTCHAR(code[-1]))
+#ifdef MAYBE_UTF_MULTI
+ if (utf && NOT_FIRSTCU(code[-1]))
{
- pcre_uchar *lastchar = code - 1;
+ PCRE2_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 */
+ c = (int)(code - lastchar); /* Length of UTF character */
+ memcpy(utf_units, lastchar, CU2BYTES(c)); /* Save the char */
+ c |= UTF_LENGTH; /* Flag c as a length */
}
else
-#endif /* SUPPORT_UTF */
+#endif /* MAYBE_UTF_MULTI */
/* Handle the case of a single charater - either with no UTF support, or
- with UTF disabled, or for a single character UTF character. */
+ with UTF disabled, or for a single-code-unit UTF character. */
{
c = code[-1];
if (*previous <= OP_CHARI && repeat_min > 1)
{
- reqchar = c;
- reqcharflags = req_caseopt | cd->req_varyopt;
+ reqcu = c;
+ reqcuflags = req_caseopt | cb->req_varyopt;
}
}
@@ -5811,26 +5231,33 @@ for (;; ptr++)
/* 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
+ the the Unicode property types will be present only when SUPPORT_UNICODE is
defined, but we don't wrap the little bits of code here because it just
makes it horribly messy. */
else if (*previous < OP_EODN)
{
- pcre_uchar *oldcode;
+ PCRE2_UCHAR *oldcode;
int prop_type, prop_value;
- op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */
- c = *previous;
-
- OUTPUT_SINGLE_REPEAT:
- if (*previous == OP_PROP || *previous == OP_NOTPROP)
+ op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */
+ c = *previous; /* Save previous opcode */
+ if (c == OP_PROP || c == OP_NOTPROP)
{
prop_type = previous[1];
prop_value = previous[2];
}
- else prop_type = prop_value = -1;
+ else
+ {
+ /* Come here from just above with a character in c */
+ OUTPUT_SINGLE_REPEAT:
+ prop_type = prop_value = -1;
+ }
- oldcode = code;
+ /* At this point we either have prop_type == prop_value == -1 and either
+ a code point or a character type that is not OP_[NOT]PROP in c, or we
+ have OP_[NOT]PROP in c and prop_type/prop_value not negative. */
+
+ oldcode = code; /* Save where we were */
code = previous; /* Usually overwrite previous item */
/* If the maximum is zero then the minimum must also be zero; Perl allows
@@ -5867,7 +5294,7 @@ for (;; ptr++)
*code++ = OP_PLUS + repeat_type;
else
{
- code = oldcode; /* leave previous item in place */
+ 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);
@@ -5875,29 +5302,30 @@ for (;; ptr++)
}
/* The case {n,n} is just an EXACT, while the general case {n,m} is
- handled as an EXACT followed by an UPTO. */
+ handled as an EXACT followed by an UPTO or STAR or QUERY. */
else
{
*code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */
PUT2INC(code, 0, repeat_min);
- /* 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. */
+ /* Unless repeat_max equals repeat_min, fill in the data for EXACT, and
+ then generate the second opcode. In UTF mode, multi-code-unit
+ characters have their length in c, with the UTF_LENGTH bit as a flag,
+ and the code units in utf_units. For a repeated Unicode property match,
+ there are two extra values that define the required property, and c
+ never has the UTF_LENGTH bit set. */
- if (repeat_max < 0)
+ if (repeat_max != repeat_min)
{
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#ifdef MAYBE_UTF_MULTI
if (utf && (c & UTF_LENGTH) != 0)
{
- memcpy(code, utf_chars, IN_UCHARS(c & 7));
+ memcpy(code, utf_units, CU2BYTES(c & 7));
code += c & 7;
}
else
-#endif
+#endif /* MAYBE_UTF_MULTI */
{
*code++ = c;
if (prop_type >= 0)
@@ -5906,72 +5334,50 @@ for (;; ptr++)
*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)
- {
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
- 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;
+ /* Now set up the following opcode */
- if (repeat_max == 1)
- {
- *code++ = OP_QUERY + repeat_type;
- }
- else
+ if (repeat_max < 0) *code++ = OP_STAR + repeat_type; else
{
- *code++ = OP_UPTO + repeat_type;
- PUT2INC(code, 0, repeat_max);
+ 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. */
+ /* Fill in the character or character type for the final opcode. */
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#ifdef MAYBE_UTF_MULTI
if (utf && (c & UTF_LENGTH) != 0)
{
- memcpy(code, utf_chars, IN_UCHARS(c & 7));
+ memcpy(code, utf_units, CU2BYTES(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)
+#endif /* MAYBEW_UTF_MULTI */
{
- *code++ = prop_type;
- *code++ = prop_value;
+ *code++ = c;
+ 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
+#ifdef SUPPORT_WIDE_CHARS
*previous == OP_XCLASS ||
#endif
*previous == OP_REF || *previous == OP_REFI ||
@@ -6011,14 +5417,15 @@ for (;; ptr++)
{
register int i;
int len = (int)(code - previous);
- size_t base_hwm_offset = item_hwm_offset;
- pcre_uchar *bralink = NULL;
- pcre_uchar *brazeroptr = NULL;
+ PCRE2_UCHAR *bralink = NULL;
+ PCRE2_UCHAR *brazeroptr = NULL;
- /* Repeating a DEFINE group is pointless, but Perl allows the syntax, so
- we just ignore the repeat. */
+ /* Repeating a DEFINE group (or any group where the condition is always
+ FALSE and there is only one branch) is pointless, but Perl allows the
+ syntax, so we just ignore the repeat. */
- if (*previous == OP_COND && previous[LINK_SIZE+1] == OP_DEF)
+ if (*previous == OP_COND && previous[LINK_SIZE+1] == OP_FALSE &&
+ previous[GET(previous, 1)] != OP_ALT)
goto END_REPEAT;
/* There is no sense in actually repeating assertions. The only potential
@@ -6057,17 +5464,11 @@ for (;; ptr++)
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. */
+ and do no more at this point. */
if (repeat_max <= 1) /* Covers 0, 1, and unlimited */
{
- *code = OP_END;
- adjust_recurse(previous, 1, utf, cd, item_hwm_offset);
- memmove(previous + 1, previous, IN_UCHARS(len));
+ memmove(previous + 1, previous, CU2BYTES(len));
code++;
if (repeat_max == 0)
{
@@ -6083,15 +5484,12 @@ for (;; ptr++)
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. */
+ adjust the value or repeat_max, since one less copy is required. */
else
{
int offset;
- *code = OP_END;
- adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, item_hwm_offset);
- memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len));
+ memmove(previous + 2 + LINK_SIZE, previous, CU2BYTES(len));
code += 2 + LINK_SIZE;
*previous++ = OP_BRAZERO + repeat_type;
*previous++ = OP_BRA;
@@ -6109,10 +5507,7 @@ for (;; ptr++)
/* 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. */
+ copies that we need. */
else
{
@@ -6125,7 +5520,7 @@ for (;; ptr++)
if (lengthptr != NULL)
{
- int delta = (repeat_min - 1)*length_prevgroup;
+ size_t delta = (repeat_min - 1)*length_prevgroup;
if ((INT64_OR_DOUBLE)(repeat_min - 1)*
(INT64_OR_DOUBLE)length_prevgroup >
(INT64_OR_DOUBLE)INT_MAX ||
@@ -6138,40 +5533,18 @@ for (;; ptr++)
}
/* 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. */
+ the group, and we have not yet set a "required byte", set it. */
else
{
- if (groupsetfirstchar && reqcharflags < 0)
+ if (groupsetfirstcu && reqcuflags < 0)
{
- reqchar = firstchar;
- reqcharflags = firstcharflags;
+ reqcu = firstcu;
+ reqcuflags = firstcuflags;
}
-
for (i = 1; i < repeat_min; i++)
{
- pcre_uchar *hc;
- size_t this_hwm_offset = cd->hwm - cd->start_workspace;
- memcpy(code, previous, IN_UCHARS(len));
-
- while (cd->hwm > cd->start_workspace + cd->workspace_size -
- WORK_SIZE_SAFETY_MARGIN -
- (this_hwm_offset - base_hwm_offset))
- {
- *errorcodeptr = expand_workspace(cd);
- if (*errorcodeptr != 0) goto FAILED;
- }
-
- for (hc = (pcre_uchar *)cd->start_workspace + base_hwm_offset;
- hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset;
- hc += LINK_SIZE)
- {
- PUT(cd->hwm, 0, GET(hc, 0) + len);
- cd->hwm += LINK_SIZE;
- }
- base_hwm_offset = this_hwm_offset;
+ memcpy(code, previous, CU2BYTES(len));
code += len;
}
}
@@ -6198,7 +5571,7 @@ for (;; ptr++)
if (lengthptr != NULL && repeat_max > 0)
{
- int delta = repeat_max * (length_prevgroup + 1 + 2 + 2*LINK_SIZE) -
+ size_t 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)
@@ -6215,9 +5588,6 @@ for (;; ptr++)
else for (i = repeat_max - 1; i >= 0; i--)
{
- pcre_uchar *hc;
- size_t this_hwm_offset = cd->hwm - cd->start_workspace;
-
*code++ = OP_BRAZERO + repeat_type;
/* All but the final copy start a new nesting, maintaining the
@@ -6232,27 +5602,7 @@ for (;; ptr++)
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_offset - base_hwm_offset))
- {
- *errorcodeptr = expand_workspace(cd);
- if (*errorcodeptr != 0) goto FAILED;
- }
-
- for (hc = (pcre_uchar *)cd->start_workspace + base_hwm_offset;
- hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset;
- hc += LINK_SIZE)
- {
- PUT(cd->hwm, 0, GET(hc, 0) + len + ((i != 0)? 2+LINK_SIZE : 1));
- cd->hwm += LINK_SIZE;
- }
- base_hwm_offset = this_hwm_offset;
+ memcpy(code, previous, CU2BYTES(len));
code += len;
}
@@ -6263,7 +5613,7 @@ for (;; ptr++)
{
int oldlinkoffset;
int offset = (int)(code - bralink + 1);
- pcre_uchar *bra = code - offset;
+ PCRE2_UCHAR *bra = code - offset;
oldlinkoffset = GET(bra, 1);
bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;
*code++ = OP_KET;
@@ -6288,7 +5638,7 @@ for (;; ptr++)
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
+ makes it possible to reduce greatly the stack usage in pcre2_match(). If
the group is preceded by OP_BRAZERO, convert this to OP_BRAPOSZERO.
Then, if the minimum number of matches is 1 or 0, cancel the possessive
@@ -6299,8 +5649,8 @@ for (;; ptr++)
else
{
- pcre_uchar *ketcode = code - 1 - LINK_SIZE;
- pcre_uchar *bracode = ketcode - GET(ketcode, 1);
+ PCRE2_UCHAR *ketcode = code - 1 - LINK_SIZE;
+ PCRE2_UCHAR *bracode = ketcode - GET(ketcode, 1);
/* Convert possessive ONCE brackets to non-capturing */
@@ -6318,14 +5668,23 @@ for (;; ptr++)
else
{
- /* In the compile phase, check for empty string matching. */
+ /* In the compile phase, check whether the group could match an empty
+ string. */
if (lengthptr == NULL)
{
- pcre_uchar *scode = bracode;
+ PCRE2_UCHAR *scode = bracode;
do
{
- if (could_be_empty_branch(scode, ketcode, utf, cd, NULL))
+ int count = 0;
+ int rc = could_be_empty_branch(scode, ketcode, utf, cb, FALSE,
+ NULL, &count);
+ if (rc < 0)
+ {
+ *errorcodeptr = ERR86;
+ goto FAILED;
+ }
+ if (rc > 0)
{
*bracode += OP_SBRA - OP_BRA;
break;
@@ -6333,13 +5692,13 @@ for (;; ptr++)
scode += GET(scode, 1);
}
while (*scode == OP_ALT);
- }
- /* A conditional group with only one branch has an implicit empty
- alternative branch. */
+ /* A conditional group with only one branch has an implicit empty
+ alternative branch. */
- if (*bracode == OP_COND && bracode[GET(bracode,1)] != OP_ALT)
- *bracode = OP_SCOND;
+ if (*bracode == OP_COND && bracode[GET(bracode,1)] != OP_ALT)
+ *bracode = OP_SCOND;
+ }
/* Handle possessive quantifiers. */
@@ -6347,15 +5706,12 @@ for (;; ptr++)
{
/* 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. */
+ versions of the COND opcodes. */
if (*bracode == OP_COND || *bracode == OP_SCOND)
{
int nlen = (int)(code - bracode);
- *code = OP_END;
- adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, item_hwm_offset);
- memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen));
+ memmove(bracode + 1 + LINK_SIZE, bracode, CU2BYTES(nlen));
code += 1 + LINK_SIZE;
nlen += 1 + LINK_SIZE;
*bracode = (*bracode == OP_COND)? OP_BRAPOS : OP_SBRAPOS;
@@ -6386,10 +5742,11 @@ for (;; ptr++)
}
}
- /* 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. */
+ /* If previous is OP_FAIL, it was generated by an empty class []
+ (PCRE2_ALLOW_EMPTY_CLASS is set). The other ways in which OP_FAIL can be
+ generated, that is by (*FAIL) or (?!), set previous to NULL, which gives a
+ "nothing to repeat" error above. We can just ignore the repeat in empty
+ class case. */
else if (*previous == OP_FAIL) goto END_REPEAT;
@@ -6397,7 +5754,7 @@ for (;; ptr++)
else
{
- *errorcodeptr = ERR11;
+ *errorcodeptr = ERR10;
goto FAILED;
}
@@ -6442,7 +5799,7 @@ for (;; ptr++)
case OP_NOTEXACT:
case OP_NOTEXACTI:
tempcode += PRIV(OP_lengths)[*tempcode];
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf && HAS_EXTRALEN(tempcode[-1]))
tempcode += GET_EXTRALEN(tempcode[-1]);
#endif
@@ -6453,10 +5810,10 @@ for (;; ptr++)
case OP_CLASS:
case OP_NCLASS:
- tempcode += 1 + 32/sizeof(pcre_uchar);
+ tempcode += 1 + 32/sizeof(PCRE2_UCHAR);
break;
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
tempcode += GET(tempcode, 1);
break;
@@ -6482,14 +5839,11 @@ for (;; ptr++)
*tempcode = opcode_possessify[repcode];
/* For opcode without a special possessified version, wrap the item in
- ONCE brackets. Because we are moving code along, we must ensure that any
- pending recursive references are updated. */
+ ONCE brackets. */
else
{
- *code = OP_END;
- adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset);
- memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len));
+ memmove(tempcode + 1 + LINK_SIZE, tempcode, CU2BYTES(len));
code += 1 + LINK_SIZE;
len += 1 + LINK_SIZE;
tempcode[0] = OP_ONCE;
@@ -6498,104 +5852,80 @@ for (;; ptr++)
PUT(tempcode, 1, len);
}
}
-
-#ifdef NEVER
- 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;
-
- case OP_CRSTAR: *tempcode = OP_CRPOSSTAR; break;
- case OP_CRPLUS: *tempcode = OP_CRPOSPLUS; break;
- case OP_CRQUERY: *tempcode = OP_CRPOSQUERY; break;
- case OP_CRRANGE: *tempcode = OP_CRPOSRANGE; 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, item_hwm_offset);
- 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;
- }
-#endif
}
/* In all case we no longer have a previous item. We also set the
- "follows varying string" flag for subsequently encountered reqchars if
+ "follows varying string" flag for subsequently encountered reqcus if
it isn't already set and we have just passed a varying length item. */
END_REPEAT:
previous = NULL;
- cd->req_varyopt |= reqvary;
+ cb->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. */
+ /* Start of nested parenthesized sub-expression, or lookahead or lookbehind
+ or option setting or condition or all the other extended parenthesis forms.
+ We must save the current high-water-mark for the forward reference list so
+ that we know where they start for this group. However, because the list may
+ be extended when there are very many forward references (usually the result
+ of a replicated inner group), we must use an offset rather than an absolute
+ address. Note that (?# comments are dealt with at the top of the loop;
+ they do not get this far. */
case CHAR_LEFT_PARENTHESIS:
ptr++;
- /* Now deal with various "verbs" that can be introduced by '*'. */
+ /* Deal with various "verbs" that can be introduced by '*'. */
if (ptr[0] == CHAR_ASTERISK && (ptr[1] == ':'
- || (MAX_255(ptr[1]) && ((cd->ctypes[ptr[1]] & ctype_letter) != 0))))
+ || (MAX_255(ptr[1]) && ((cb->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;
+ PCRE2_SPTR name = ptr + 1;
+ PCRE2_SPTR arg = NULL;
previous = NULL;
ptr++;
- while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_letter) != 0) ptr++;
- namelen = (int)(ptr - name);
+
+ /* Increment ptr, set namelen, check length */
+
+ READ_NAME(ctype_letter, ERR60, *errorcodeptr);
/* 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. */
+ letters, digits, and underscores. Perl does not, however, do any
+ interpretation within arguments, and has no means of including a closing
+ parenthesis. PCRE supports escape processing but only when it is
+ requested by an option. Note that check_escape() will not return values
+ greater than the code unit maximum when not in UTF mode. */
if (*ptr == CHAR_COLON)
{
arg = ++ptr;
- while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
- arglen = (int)(ptr - arg);
- if ((unsigned int)arglen > MAX_MARK)
+
+ if ((options & PCRE2_ALT_VERBNAMES) == 0)
{
- *errorcodeptr = ERR75;
- goto FAILED;
+ arglen = 0;
+ while (ptr < cb->end_pattern && *ptr != CHAR_RIGHT_PARENTHESIS)
+ {
+ ptr++; /* Check length as we go */
+ arglen++; /* along, to avoid the */
+ if ((unsigned int)arglen > MAX_MARK) /* possibility of overflow. */
+ {
+ *errorcodeptr = ERR76;
+ goto FAILED;
+ }
+ }
+ }
+ else
+ {
+ /* The length check is in process_verb_names() */
+ arglen = process_verb_name(&ptr, NULL, errorcodeptr, options,
+ utf, cb);
+ if (arglen < 0) goto FAILED;
}
}
@@ -6610,7 +5940,7 @@ for (;; ptr++)
for (i = 0; i < verbcount; i++)
{
if (namelen == verbs[i].len &&
- STRNCMP_UC_C8(name, vn, namelen) == 0)
+ PRIV(strncmp_c8)(name, vn, namelen) == 0)
{
int setverb;
@@ -6625,18 +5955,17 @@ for (;; ptr++)
*errorcodeptr = ERR59;
goto FAILED;
}
- cd->had_accept = TRUE;
- for (oc = cd->open_caps; oc != NULL; oc = oc->next)
+ cb->had_accept = TRUE;
+
+ /* In the first pass, just accumulate the length required;
+ otherwise hitting (*ACCEPT) inside many nested parentheses can
+ cause workspace overflow. */
+
+ for (oc = cb->open_caps; oc != NULL; oc = oc->next)
{
if (lengthptr != NULL)
{
-#ifdef COMPILE_PCRE8
- *lengthptr += 1 + IMM2_SIZE;
-#elif defined COMPILE_PCRE16
- *lengthptr += 2 + IMM2_SIZE;
-#elif defined COMPILE_PCRE32
- *lengthptr += 4 + IMM2_SIZE;
-#endif
+ *lengthptr += CU2BYTES(1) + IMM2_SIZE;
}
else
{
@@ -6645,15 +5974,15 @@ for (;; ptr++)
}
}
setverb = *code++ =
- (cd->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;
+ (cb->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;
- /* Do not set firstchar after *ACCEPT */
- if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ /* Do not set firstcu after *ACCEPT */
+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
}
/* Handle other cases with/without an argument */
- else if (arglen == 0)
+ else if (arglen == 0) /* There is no argument */
{
if (verbs[i].op < 0) /* Argument is mandatory */
{
@@ -6663,25 +5992,42 @@ for (;; ptr++)
setverb = *code++ = verbs[i].op;
}
- else
+ else /* An argument is present */
{
- if (verbs[i].op_arg < 0) /* Argument is forbidden */
+ if (verbs[i].op_arg < 0) /* Argument is forbidden */
{
*errorcodeptr = ERR59;
goto FAILED;
}
setverb = *code++ = verbs[i].op_arg;
- if (lengthptr != NULL) /* In pass 1 just add in the length */
- { /* to avoid potential workspace */
- *lengthptr += arglen; /* overflow. */
+
+ /* Arguments can be very long, especially in 16- and 32-bit modes,
+ and can overflow the workspace in the first pass. Instead of
+ putting the argument into memory, we just update the length counter
+ and set up an empty argument. */
+
+ if (lengthptr != NULL)
+ {
+ *lengthptr += arglen;
*code++ = 0;
}
else
{
*code++ = arglen;
- memcpy(code, arg, IN_UCHARS(arglen));
- code += arglen;
+ if ((options & PCRE2_ALT_VERBNAMES) != 0)
+ {
+ PCRE2_UCHAR *memcode = code; /* code is "register" */
+ (void)process_verb_name(&arg, &memcode, errorcodeptr, options,
+ utf, cb);
+ code = memcode;
+ }
+ else /* No argument processing */
+ {
+ memcpy(code, arg, CU2BYTES(arglen));
+ code += arglen;
+ }
}
+
*code++ = 0;
}
@@ -6689,14 +6035,14 @@ for (;; ptr++)
{
case OP_THEN:
case OP_THEN_ARG:
- cd->external_flags |= PCRE_HASTHEN;
+ cb->external_flags |= PCRE2_HASTHEN;
break;
case OP_PRUNE:
case OP_PRUNE_ARG:
case OP_SKIP:
case OP_SKIP_ARG:
- cd->had_pruneorskip = TRUE;
+ cb->had_pruneorskip = TRUE;
break;
}
@@ -6711,12 +6057,11 @@ for (;; ptr++)
goto FAILED;
}
- /* Initialize for "real" parentheses */
+ /* Initialization for "real" parentheses */
newoptions = options;
- skipbytes = 0;
+ skipunits = 0;
bravalue = OP_CBRA;
- item_hwm_offset = cd->hwm - cd->start_workspace;
reset_bracount = FALSE;
/* Deal with the extended parentheses; all are introduced by '?', and the
@@ -6724,17 +6069,19 @@ for (;; ptr++)
if (*ptr == CHAR_QUESTION_MARK)
{
- int i, set, unset, namelen;
- int *optset;
- const pcre_uchar *name;
- pcre_uchar *slot;
+ int i, count;
+ int namelen; /* Must be signed */
+ uint32_t index;
+ uint32_t set, unset, *optset;
+ named_group *ng;
+ PCRE2_SPTR name;
+ PCRE2_UCHAR *slot;
switch (*(++ptr))
{
/* ------------------------------------------------------------ */
case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */
reset_bracount = TRUE;
- cd->dupgroups = TRUE; /* Record (?| encountered */
/* Fall through */
/* ------------------------------------------------------------ */
@@ -6743,7 +6090,6 @@ for (;; ptr++)
ptr++;
break;
-
/* ------------------------------------------------------------ */
case CHAR_LEFT_PARENTHESIS:
bravalue = OP_COND; /* Conditional group */
@@ -6768,9 +6114,39 @@ for (;; ptr++)
if (ptr[1] == CHAR_QUESTION_MARK && ptr[2] == CHAR_C)
{
- for (i = 3;; i++) if (!IS_DIGIT(ptr[i])) break;
- if (ptr[i] == CHAR_RIGHT_PARENTHESIS)
- tempptr += i + 1;
+ if (IS_DIGIT(ptr[3]) || ptr[3] == CHAR_RIGHT_PARENTHESIS)
+ {
+ for (i = 3;; i++) if (!IS_DIGIT(ptr[i])) break;
+ if (ptr[i] == CHAR_RIGHT_PARENTHESIS)
+ tempptr += i + 1;
+ }
+ else
+ {
+ uint32_t delimiter = 0;
+ for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)
+ {
+ if (ptr[3] == PRIV(callout_start_delims)[i])
+ {
+ delimiter = PRIV(callout_end_delims)[i];
+ break;
+ }
+ }
+ if (delimiter != 0)
+ {
+ for (i = 4; ptr + i < cb->end_pattern; i++)
+ {
+ if (ptr[i] == delimiter)
+ {
+ if (ptr[i+1] == delimiter) i++;
+ else
+ {
+ if (ptr[i+1] == CHAR_RIGHT_PARENTHESIS) tempptr += i + 2;
+ break;
+ }
+ }
+ }
+ }
+ }
/* tempptr should now be pointing to the opening parenthesis of the
assertion condition. */
@@ -6783,8 +6159,10 @@ for (;; ptr++)
}
/* 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. */
+ the switch. This will take control down to where bracketed groups
+ are processed. The assertion will be handled as part of the group,
+ but we need to identify this case because the conditional assertion may
+ not be quantifier. */
if (tempptr[1] == CHAR_QUESTION_MARK &&
(tempptr[2] == CHAR_EQUALS_SIGN ||
@@ -6793,7 +6171,7 @@ for (;; ptr++)
(tempptr[3] == CHAR_EQUALS_SIGN ||
tempptr[3] == CHAR_EXCLAMATION_MARK))))
{
- cd->iscondassert = TRUE;
+ cb->iscondassert = TRUE;
break;
}
@@ -6801,15 +6179,72 @@ for (;; ptr++)
need to skip at least 1+IMM2_SIZE bytes at the start of the group. */
code[1+LINK_SIZE] = OP_CREF;
- skipbytes = 1+IMM2_SIZE;
+ skipunits = 1+IMM2_SIZE;
refsign = -1; /* => not a number */
namelen = -1; /* => not a name; must set to avoid warning */
name = NULL; /* Always set to avoid warning */
recno = 0; /* Always set to avoid warning */
- /* Check for a test for recursion in a named group. */
+ /* Point at character after (?( */
ptr++;
+
+ /* Check for (?(VERSION[>]=n.m), which is a facility whereby indirect
+ users of PCRE2 via an application can discover which release of PCRE2
+ is being used. */
+
+ if (PRIV(strncmp_c8)(ptr, STRING_VERSION, 7) == 0 &&
+ ptr[7] != CHAR_RIGHT_PARENTHESIS)
+ {
+ BOOL ge = FALSE;
+ int major = 0;
+ int minor = 0;
+
+ ptr += 7;
+ if (*ptr == CHAR_GREATER_THAN_SIGN)
+ {
+ ge = TRUE;
+ ptr++;
+ }
+
+ /* NOTE: cannot write IS_DIGIT(*(++ptr)) here because IS_DIGIT
+ references its argument twice. */
+
+ if (*ptr != CHAR_EQUALS_SIGN || (ptr++, !IS_DIGIT(*ptr)))
+ {
+ *errorcodeptr = ERR79;
+ goto FAILED;
+ }
+
+ while (IS_DIGIT(*ptr)) major = major * 10 + *ptr++ - '0';
+ if (*ptr == CHAR_DOT)
+ {
+ ptr++;
+ while (IS_DIGIT(*ptr)) minor = minor * 10 + *ptr++ - '0';
+ if (minor < 10) minor *= 10;
+ }
+
+ if (*ptr != CHAR_RIGHT_PARENTHESIS || minor > 99)
+ {
+ *errorcodeptr = ERR79;
+ goto FAILED;
+ }
+
+ if (ge)
+ code[1+LINK_SIZE] = ((PCRE2_MAJOR > major) ||
+ (PCRE2_MAJOR == major && PCRE2_MINOR >= minor))?
+ OP_TRUE : OP_FALSE;
+ else
+ code[1+LINK_SIZE] = (PCRE2_MAJOR == major && PCRE2_MINOR == minor)?
+ OP_TRUE : OP_FALSE;
+
+ ptr++;
+ skipunits = 1;
+ break; /* End of condition processing */
+ }
+
+ /* Check for a test for recursion in a named group. */
+
if (*ptr == CHAR_R && ptr[1] == CHAR_AMPERSAND)
{
terminator = -1;
@@ -6856,34 +6291,33 @@ for (;; ptr++)
}
/* Otherwise we expect to read a name; anything else is an error. When
- a name is one of a number of duplicates, a different opcode is used and
- it needs more memory. Unfortunately we cannot tell whether a name is a
- duplicate in the first pass, so we have to allow for more memory. */
+ the referenced name is one of a number of duplicates, a different
+ opcode is used and it needs more memory. Unfortunately we cannot tell
+ whether this is the case in the first pass, so we have to allow for
+ more memory always. In the second pass, the additional to skipunits
+ happens later. */
else
{
if (IS_DIGIT(*ptr))
{
- *errorcodeptr = ERR84;
+ *errorcodeptr = ERR44; /* Group name must start with non-digit */
goto FAILED;
}
- if (!MAX_255(*ptr) || (cd->ctypes[*ptr] & ctype_word) == 0)
+ if (!MAX_255(*ptr) || (cb->ctypes[*ptr] & ctype_word) == 0)
{
*errorcodeptr = ERR28; /* Assertion expected */
goto FAILED;
}
- name = ptr++;
- while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0)
- {
- ptr++;
- }
- namelen = (int)(ptr - name);
- if (lengthptr != NULL) skipbytes += IMM2_SIZE;
+ name = ptr;
+ /* Increment ptr, set namelen, check length */
+ READ_NAME(ctype_word, ERR48, *errorcodeptr);
+ if (lengthptr != NULL) skipunits += IMM2_SIZE;
}
/* Check the terminator */
- if ((terminator > 0 && *ptr++ != (pcre_uchar)terminator) ||
+ if ((terminator > 0 && *ptr++ != (PCRE2_UCHAR)terminator) ||
*ptr++ != CHAR_RIGHT_PARENTHESIS)
{
ptr--; /* Error offset */
@@ -6907,24 +6341,24 @@ for (;; ptr++)
goto FAILED;
}
if (refsign != 0) recno = (refsign == CHAR_MINUS)?
- cd->bracount - recno + 1 : recno + cd->bracount;
- if (recno <= 0 || recno > cd->final_bracount)
+ (cb->bracount + 1) - recno : recno + cb->bracount;
+ if (recno <= 0 || (uint32_t)recno > cb->final_bracount)
{
*errorcodeptr = ERR15;
goto FAILED;
}
PUT2(code, 2+LINK_SIZE, recno);
- if (recno > cd->top_backref) cd->top_backref = recno;
+ if ((uint32_t)recno > cb->top_backref) cb->top_backref = recno;
break;
}
/* Otherwise look for the name. */
- slot = cd->name_table;
- for (i = 0; i < cd->names_found; i++)
+ slot = cb->name_table;
+ for (i = 0; i < cb->names_found; i++)
{
- if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0) break;
- slot += cd->name_entry_size;
+ if (PRIV(strncmp)(name, slot+IMM2_SIZE, namelen) == 0) break;
+ slot += cb->name_entry_size;
}
/* Found the named subpattern. If the name is duplicated, add one to
@@ -6932,25 +6366,27 @@ for (;; ptr++)
appropriate data values. Otherwise, just insert the unique subpattern
number. */
- if (i < cd->names_found)
+ if (i < cb->names_found)
{
- int offset = i++;
- int count = 1;
- recno = GET2(slot, 0); /* Number from first found */
- if (recno > cd->top_backref) cd->top_backref = recno;
- for (; i < cd->names_found; i++)
+ int offset = i; /* Offset of first name found */
+
+ count = 0;
+ for (;;)
{
- slot += cd->name_entry_size;
- if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) != 0 ||
- (slot+IMM2_SIZE)[namelen] != 0) break;
+ recno = GET2(slot, 0); /* Number for last found */
+ if ((uint32_t)recno > cb->top_backref) cb->top_backref = recno;
count++;
+ if (++i >= cb->names_found) break;
+ slot += cb->name_entry_size;
+ if (PRIV(strncmp)(name, slot+IMM2_SIZE, namelen) != 0 ||
+ (slot+IMM2_SIZE)[namelen] != 0) break;
}
if (count > 1)
{
PUT2(code, 2+LINK_SIZE, offset);
PUT2(code, 2+LINK_SIZE+IMM2_SIZE, count);
- skipbytes += IMM2_SIZE;
+ skipunits += IMM2_SIZE;
code[1+LINK_SIZE]++;
}
else /* Not a duplicated name */
@@ -6981,7 +6417,7 @@ for (;; ptr++)
{
if (!IS_DIGIT(name[i]))
{
- *errorcodeptr = ERR15;
+ *errorcodeptr = ERR15; /* Non-existent subpattern */
goto FAILED;
}
if (recno > INT_MAX / 10 - 1) /* Integer overflow */
@@ -6997,12 +6433,14 @@ for (;; ptr++)
}
/* Similarly, check for the (?(DEFINE) "condition", which is always
- false. */
+ false. During compilation we set OP_DEFINE to distinguish this from
+ other OP_FALSE conditions so that it can be checked for having only one
+ branch, but after that the opcode is changed to OP_FALSE. */
- else if (namelen == 6 && STRNCMP_UC_C8(name, STRING_DEFINE, 6) == 0)
+ else if (namelen == 6 && PRIV(strncmp_c8)(name, STRING_DEFINE, 6) == 0)
{
- code[1+LINK_SIZE] = OP_DEF;
- skipbytes = 1;
+ code[1+LINK_SIZE] = OP_DEFINE;
+ skipunits = 1;
}
/* Reference to an unidentified subpattern. */
@@ -7018,7 +6456,7 @@ for (;; ptr++)
/* ------------------------------------------------------------ */
case CHAR_EQUALS_SIGN: /* Positive lookahead */
bravalue = OP_ASSERT;
- cd->assert_depth += 1;
+ cb->assert_depth += 1;
ptr++;
break;
@@ -7040,7 +6478,7 @@ for (;; ptr++)
continue;
}
bravalue = OP_ASSERT_NOT;
- cd->assert_depth += 1;
+ cb->assert_depth += 1;
break;
@@ -7050,22 +6488,24 @@ for (;; ptr++)
{
case CHAR_EQUALS_SIGN: /* Positive lookbehind */
bravalue = OP_ASSERTBACK;
- cd->assert_depth += 1;
+ cb->assert_depth += 1;
ptr += 2;
break;
case CHAR_EXCLAMATION_MARK: /* Negative lookbehind */
bravalue = OP_ASSERTBACK_NOT;
- cd->assert_depth += 1;
+ cb->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;
+ /* Must be a name definition - as the syntax was checked in the
+ pre-pass, we can assume here that it is valid. Skip over the name
+ and go to handle the numbered group. */
+
+ default:
+ while (*(++ptr) != CHAR_GREATER_THAN_SIGN);
+ ptr++;
+ goto NUMBERED_GROUP;
}
break;
@@ -7078,159 +6518,161 @@ for (;; ptr++)
/* ------------------------------------------------------------ */
- case CHAR_C: /* Callout - may be followed by digits; */
+ case CHAR_C: /* Callout */
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;
- if (IS_DIGIT(*ptr))
- {
- *errorcodeptr = ERR84; /* Group name must start with non-digit */
- goto FAILED;
- }
- while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++;
- namelen = (int)(ptr - name);
+ ptr++; /* Character after (?C */
- /* In the pre-compile phase, do a syntax check, remember the longest
- name, and then remember the group in a vector, expanding it if
- necessary. Duplicates for the same number are skipped; other duplicates
- are checked for validity. In the actual compile, there is nothing to
- do. */
+ /* A callout may have a string argument, delimited by one of a fixed
+ number of characters, or an undelimited numerical argument, or no
+ argument, which is the same as (?C0). Different opcodes are used for
+ the two cases. */
- if (lengthptr != NULL)
+ if (*ptr != CHAR_RIGHT_PARENTHESIS && !IS_DIGIT(*ptr))
{
- named_group *ng;
- pcre_uint32 number = cd->bracount + 1;
+ uint32_t delimiter = 0;
- if (*ptr != (pcre_uchar)terminator)
+ for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)
{
- *errorcodeptr = ERR42;
- goto FAILED;
+ if (*ptr == PRIV(callout_start_delims)[i])
+ {
+ delimiter = PRIV(callout_end_delims)[i];
+ break;
+ }
}
- if (cd->names_found >= MAX_NAME_COUNT)
+ if (delimiter == 0)
{
- *errorcodeptr = ERR49;
+ *errorcodeptr = ERR82;
goto FAILED;
}
- if (namelen + IMM2_SIZE + 1 > cd->name_entry_size)
+ /* During the pre-compile phase, we parse the string and update the
+ length. There is no need to generate any code. (In fact, the string
+ has already been parsed in the pre-pass that looks for named
+ parentheses, but it does no harm to leave this code in.) */
+
+ if (lengthptr != NULL) /* Only check the string */
{
- cd->name_entry_size = namelen + IMM2_SIZE + 1;
- if (namelen > MAX_NAME_SIZE)
+ PCRE2_SPTR start = ptr;
+ do
{
- *errorcodeptr = ERR48;
- goto FAILED;
+ if (++ptr >= cb->end_pattern)
+ {
+ *errorcodeptr = ERR81;
+ ptr = start; /* To give a more useful message */
+ goto FAILED;
+ }
+ if (ptr[0] == delimiter && ptr[1] == delimiter) ptr += 2;
}
+ while (ptr[0] != delimiter);
+
+ /* Start points to the opening delimiter, ptr points to the
+ closing delimiter. We must allow for including the delimiter and
+ for the terminating zero. Any doubled delimiters within the string
+ make this an overestimate, but it is not worth bothering about. */
+
+ (*lengthptr) += (ptr - start) + 2 + (1 + 4*LINK_SIZE);
}
- /* Scan the list to check for duplicates. For duplicate names, if the
- number is the same, break the loop, which causes the name to be
- discarded; otherwise, if DUPNAMES is not set, give an error.
- If it is set, allow the name with a different number, but continue
- scanning in case this is a duplicate with the same number. For
- non-duplicate names, give an error if the number is duplicated. */
+ /* In the real compile we can copy the string, knowing that it is
+ syntactically OK. The starting delimiter is included so that the
+ client can discover it if they want. We also pass the start offset to
+ help a script language give better error messages. */
- ng = cd->named_groups;
- for (i = 0; i < cd->names_found; i++, ng++)
+ else
{
- if (namelen == ng->length &&
- STRNCMP_UC_UC(name, ng->name, namelen) == 0)
+ PCRE2_UCHAR *callout_string = code + (1 + 4*LINK_SIZE);
+ *callout_string++ = *ptr++;
+ PUT(code, 1 + 3*LINK_SIZE, (int)(ptr - cb->start_pattern)); /* Start offset */
+ for(;;)
{
- if (ng->number == number) break;
- if ((options & PCRE_DUPNAMES) == 0)
+ if (*ptr == delimiter)
{
- *errorcodeptr = ERR43;
- goto FAILED;
+ if (ptr[1] == delimiter) ptr++; else break;
}
- cd->dupnames = TRUE; /* Duplicate names exist */
+ *callout_string++ = *ptr++;
}
- else if (ng->number == number)
+ *callout_string++ = CHAR_NULL;
+ code[0] = OP_CALLOUT_STR;
+ PUT(code, 1, (int)(ptr + 2 - cb->start_pattern)); /* Next offset */
+ PUT(code, 1 + LINK_SIZE, 0); /* Default length */
+ PUT(code, 1 + 2*LINK_SIZE, /* Compute size */
+ (int)(callout_string - code));
+ code = callout_string;
+ }
+
+ /* Advance to what should be the closing parenthesis, which is
+ checked below. */
+
+ ptr++;
+ }
+
+ /* Handle a callout with an optional numerical argument, which must be
+ less than or equal to 255. A missing argument gives 0. */
+
+ else
+ {
+ int n = 0;
+ code[0] = OP_CALLOUT; /* Numerical callout */
+ while (IS_DIGIT(*ptr))
+ {
+ n = n * 10 + *ptr++ - CHAR_0;
+ if (n > 255)
{
- *errorcodeptr = ERR65;
+ *errorcodeptr = ERR38;
goto FAILED;
}
}
+ PUT(code, 1, (int)(ptr - cb->start_pattern + 1)); /* Next offset */
+ PUT(code, 1 + LINK_SIZE, 0); /* Default length */
+ code[1 + 2*LINK_SIZE] = n; /* Callout number */
+ code += PRIV(OP_lengths)[OP_CALLOUT];
+ }
- if (i >= cd->names_found) /* Not a duplicate with same number */
- {
- /* Increase the list size if necessary */
+ /* Both formats must have a closing parenthesis */
- if (cd->names_found >= cd->named_group_list_size)
- {
- int newsize = cd->named_group_list_size * 2;
- named_group *newspace = (PUBL(malloc))
- (newsize * sizeof(named_group));
+ if (*ptr != CHAR_RIGHT_PARENTHESIS)
+ {
+ *errorcodeptr = ERR39;
+ goto FAILED;
+ }
- if (newspace == NULL)
- {
- *errorcodeptr = ERR21;
- goto FAILED;
- }
+ /* Callouts cannot be quantified. */
- memcpy(newspace, cd->named_groups,
- cd->named_group_list_size * sizeof(named_group));
- if (cd->named_group_list_size > NAMED_GROUP_LIST_SIZE)
- (PUBL(free))((void *)cd->named_groups);
- cd->named_groups = newspace;
- cd->named_group_list_size = newsize;
- }
+ previous = NULL;
+ continue;
- cd->named_groups[cd->names_found].name = name;
- cd->named_groups[cd->names_found].length = namelen;
- cd->named_groups[cd->names_found].number = number;
- cd->names_found++;
- }
+
+ /* ------------------------------------------------------------ */
+ 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 */
+
- ptr++; /* Move past > or ' in both passes. */
- goto NUMBERED_GROUP;
+ /* ------------------------------------------------------------ */
+ case CHAR_APOSTROPHE: /* Define a name - note fall through above */
+
+ /* The syntax was checked and the list of names was set up in the
+ pre-pass, so there is nothing to be done now except to skip over the
+ name. */
+
+ terminator = (*ptr == CHAR_LESS_THAN_SIGN)?
+ CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE;
+ while (*(++ptr) != (unsigned int)terminator);
+ ptr++;
+ goto NUMBERED_GROUP; /* Set up numbered group */
/* ------------------------------------------------------------ */
@@ -7249,193 +6691,115 @@ for (;; ptr++)
name = ++ptr;
if (IS_DIGIT(*ptr))
{
- *errorcodeptr = ERR84; /* Group name must start with non-digit */
+ *errorcodeptr = ERR44; /* Group name must start with non-digit */
goto FAILED;
}
- while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++;
- namelen = (int)(ptr - name);
+ /* Increment ptr, set namelen, check length */
+ READ_NAME(ctype_word, ERR48, *errorcodeptr);
- /* 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. */
+ /* In the pre-compile phase, do a syntax check. */
if (lengthptr != NULL)
{
- named_group *ng;
- recno = 0;
-
if (namelen == 0)
{
*errorcodeptr = ERR62;
goto FAILED;
}
- if (*ptr != (pcre_uchar)terminator)
+ if (*ptr != (PCRE2_UCHAR)terminator)
{
*errorcodeptr = ERR42;
goto FAILED;
}
- if (namelen > MAX_NAME_SIZE)
- {
- *errorcodeptr = ERR48;
- goto FAILED;
- }
-
- /* Count named back references. */
-
- if (!is_recurse) cd->namedrefcount++;
-
- /* We have to allow for a named reference to a duplicated name (this
- cannot be determined until the second pass). This needs an extra
- 16-bit data item. */
-
- *lengthptr += IMM2_SIZE;
+ }
- /* If this is a forward reference and we are within a (?|...) group,
- the reference may end up as the number of a group which we are
- currently inside, that is, it could be a recursive reference. In the
- real compile this will be picked up and the reference wrapped with
- OP_ONCE to make it atomic, so we must space in case this occurs. */
+ /* Scan the list of names generated in the pre-pass in order to get
+ a number and whether or not this name is duplicated. */
- /* In fact, this can happen for a non-forward reference because
- another group with the same number might be created later. This
- issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance
- only mode, we finesse the bug by allowing more memory always. */
+ recno = 0;
+ is_dupname = FALSE;
+ ng = cb->named_groups;
- *lengthptr += 4 + 4*LINK_SIZE;
+ for (i = 0; i < cb->names_found; i++, ng++)
+ {
+ if (namelen == ng->length &&
+ PRIV(strncmp)(name, ng->name, namelen) == 0)
+ {
+ open_capitem *oc;
+ is_dupname = ng->isdup;
+ recno = ng->number;
- /* It is even worse than that. The current reference may be to an
- existing named group with a different number (so apparently not
- recursive) but which later on is also attached to a group with the
- current number. This can only happen if $(| has been previous
- encountered. In that case, we allow yet more memory, just in case.
- (Again, this is fixed "properly" in PCRE2. */
+ /* For a recursion, that's all that is needed. We can now go to the
+ code that handles numerical recursion. */
- if (cd->dupgroups) *lengthptr += 4 + 4*LINK_SIZE;
+ if (is_recurse) goto HANDLE_RECURSION;
- /* Otherwise, check for recursion here. The name table does not exist
- in the first pass; instead we must scan the list of names encountered
- so far in order to get the number. If the name is not found, leave
- the value of recno as 0 for a forward reference. */
+ /* For a back reference, update the back reference map and the
+ maximum back reference. Then for each group we must check to see if
+ it is recursive, that is, it is inside the group that it
+ references. A flag is set so that the group can be made atomic. */
- /* This patch (removing "else") fixes a problem when a reference is
- to multiple identically named nested groups from within the nest.
- Once again, it is not the "proper" fix, and it results in an
- over-allocation of memory. */
+ cb->backref_map |= (recno < 32)? (1u << recno) : 1;
+ if ((uint32_t)recno > cb->top_backref) cb->top_backref = recno;
- /* else */
- {
- ng = cd->named_groups;
- for (i = 0; i < cd->names_found; i++, ng++)
+ for (oc = cb->open_caps; oc != NULL; oc = oc->next)
{
- if (namelen == ng->length &&
- STRNCMP_UC_UC(name, ng->name, namelen) == 0)
+ if (oc->number == recno)
{
- open_capitem *oc;
- recno = ng->number;
- if (is_recurse) break;
- for (oc = cd->open_caps; oc != NULL; oc = oc->next)
- {
- if (oc->number == recno)
- {
- oc->flag = TRUE;
- break;
- }
- }
+ oc->flag = TRUE;
+ break;
}
}
}
}
- /* In the real compile, search the name 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 is longer than any in the table, the
- comparison will fail without reading beyond the table entry. */
+ /* If the name was not found we have a bad reference. */
- else
+ if (recno == 0)
{
- 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)
- {
- recno = GET2(slot, 0);
- }
- else
- {
- *errorcodeptr = ERR15;
- goto FAILED;
- }
+ *errorcodeptr = ERR15;
+ goto FAILED;
}
- /* In both phases, for recursions, we can now go to the code than
- handles numerical recursion. */
-
- if (is_recurse) goto HANDLE_RECURSION;
+ /* If a back reference name is not duplicated, we can handle it as a
+ numerical reference. */
- /* In the second pass we must see if the name is duplicated. If so, we
- generate a different opcode. */
+ if (!is_dupname) goto HANDLE_REFERENCE;
- if (lengthptr == NULL && cd->dupnames)
- {
- int count = 1;
- unsigned int index = i;
- pcre_uchar *cslot = slot + cd->name_entry_size;
+ /* If a back reference name is duplicated, we generate a different
+ opcode to a numerical back reference. In the second pass we must search
+ for the index and count in the final name table. */
- for (i++; i < cd->names_found; i++)
- {
- if (STRCMP_UC_UC(slot + IMM2_SIZE, cslot + IMM2_SIZE) != 0) break;
- count++;
- cslot += cd->name_entry_size;
- }
+ count = 0;
+ index = 0;
- if (count > 1)
+ if (lengthptr == NULL)
+ {
+ slot = cb->name_table;
+ for (i = 0; i < cb->names_found; i++)
{
- if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
- previous = code;
- item_hwm_offset = cd->hwm - cd->start_workspace;
- *code++ = ((options & PCRE_CASELESS) != 0)? OP_DNREFI : OP_DNREF;
- PUT2INC(code, 0, index);
- PUT2INC(code, 0, count);
-
- /* Process each potentially referenced group. */
-
- for (; slot < cslot; slot += cd->name_entry_size)
+ if (PRIV(strncmp)(name, slot+IMM2_SIZE, namelen) == 0 &&
+ slot[IMM2_SIZE+namelen] == 0)
{
- open_capitem *oc;
- recno = GET2(slot, 0);
- 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;
- }
- }
+ if (count == 0) index = i;
+ count++;
}
+ slot += cb->name_entry_size;
+ }
- continue; /* End of back ref handling */
+ if (count == 0)
+ {
+ *errorcodeptr = ERR15;
+ goto FAILED;
}
}
- /* First pass, or a non-duplicated name. */
-
- goto HANDLE_REFERENCE;
+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
+ previous = code;
+ *code++ = ((options & PCRE2_CASELESS) != 0)? OP_DNREFI : OP_DNREF;
+ PUT2INC(code, 0, index);
+ PUT2INC(code, 0, count);
+ continue; /* End of back ref handling */
/* ------------------------------------------------------------ */
@@ -7454,7 +6818,6 @@ for (;; ptr++)
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
@@ -7482,7 +6845,7 @@ for (;; ptr++)
}
recno = 0;
- while(IS_DIGIT(*ptr))
+ while (IS_DIGIT(*ptr))
{
if (recno > INT_MAX / 10 - 1) /* Integer overflow */
{
@@ -7493,7 +6856,7 @@ for (;; ptr++)
recno = recno * 10 + *ptr++ - CHAR_0;
}
- if (*ptr != (pcre_uchar)terminator)
+ if (*ptr != (PCRE2_UCHAR)terminator)
{
*errorcodeptr = ERR29;
goto FAILED;
@@ -7506,7 +6869,7 @@ for (;; ptr++)
*errorcodeptr = ERR58;
goto FAILED;
}
- recno = cd->bracount - recno + 1;
+ recno = (int)(cb->bracount + 1) - recno;
if (recno <= 0)
{
*errorcodeptr = ERR15;
@@ -7520,84 +6883,37 @@ for (;; ptr++)
*errorcodeptr = ERR58;
goto FAILED;
}
- recno += cd->bracount;
+ recno += cb->bracount;
}
- /* Come here from code above that handles a named recursion */
-
- HANDLE_RECURSION:
-
- previous = code;
- item_hwm_offset = cd->hwm - cd->start_workspace;
- called = cd->start_code;
-
- /* When we are actually compiling, find the bracket that is being
- 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)
+ if ((uint32_t)recno > cb->final_bracount)
{
- *code = OP_END;
- if (recno != 0)
- called = PRIV(find_bracket)(cd->start_code, utf, recno);
-
- /* Forward reference */
-
- if (called == NULL)
- {
- if (recno > cd->final_bracount)
- {
- *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;
- }
+ *errorcodeptr = ERR15;
+ 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). */
+ /* Come here from code above that handles a named recursion.
+ We insert the number of the called group after OP_RECURSE. At the
+ end of compiling the pattern is scanned and these numbers are
+ replaced by offsets within the pattern. It is done like this to avoid
+ problems with forward references and adjusting offsets when groups
+ are duplicated and moved (as discovered in previous implementations).
+ Note that a recursion does not have a set first character (relevant
+ if it is repeated, because it will then be wrapped with ONCE
+ brackets). */
+ HANDLE_RECURSION:
+ previous = code;
*code = OP_RECURSE;
- PUT(code, 1, (int)(called - cd->start_code));
+ PUT(code, 1, recno);
code += 1 + LINK_SIZE;
- groupsetfirstchar = FALSE;
+ groupsetfirstcu = FALSE;
+ cb->had_recurse = TRUE;
}
/* Can't determine a first byte now */
- if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
continue;
@@ -7614,18 +6930,17 @@ for (;; 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;
+ *optset |= PCRE2_DUPNAMES;
+ cb->external_flags |= PCRE2_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;
+ case CHAR_i: *optset |= PCRE2_CASELESS; break;
+ case CHAR_m: *optset |= PCRE2_MULTILINE; break;
+ case CHAR_s: *optset |= PCRE2_DOTALL; break;
+ case CHAR_x: *optset |= PCRE2_EXTENDED; break;
+ case CHAR_U: *optset |= PCRE2_UNGREEDY; break;
- default: *errorcodeptr = ERR12;
+ default: *errorcodeptr = ERR11;
ptr--; /* Correct the offset */
goto FAILED;
}
@@ -7636,20 +6951,16 @@ for (;; ptr++)
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 we are not at the pattern start, reset the greedy defaults and the
- case value for firstchar and reqchar. */
+ group with option changes, so the options change at this level. They
+ must also be passed back for use in subsequent branches. Reset the
+ greedy defaults and the case value for firstcu and reqcu. */
if (*ptr == CHAR_RIGHT_PARENTHESIS)
{
- 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;
+ greedy_default = ((newoptions & PCRE2_UNGREEDY) != 0);
+ greedy_non_default = greedy_default ^ 1;
+ req_caseopt = ((newoptions & PCRE2_CASELESS) != 0)? REQ_CASELESS:0;
previous = NULL; /* This item can't be repeated */
continue; /* It is complete */
}
@@ -7664,11 +6975,11 @@ for (;; ptr++)
} /* End of switch for character following (? */
} /* End of (? handling */
- /* Opening parenthesis not followed by '*' or '?'. If PCRE_NO_AUTO_CAPTURE
+ /* Opening parenthesis not followed by '*' or '?'. If PCRE2_NO_AUTO_CAPTURE
is set, all unadorned brackets become non-capturing and behave like (?:...)
brackets. */
- else if ((options & PCRE_NO_AUTO_CAPTURE) != 0)
+ else if ((options & PCRE2_NO_AUTO_CAPTURE) != 0)
{
bravalue = OP_BRA;
}
@@ -7678,17 +6989,17 @@ for (;; ptr++)
else
{
NUMBERED_GROUP:
- cd->bracount += 1;
- PUT2(code, 1+LINK_SIZE, cd->bracount);
- skipbytes = IMM2_SIZE;
+ cb->bracount += 1;
+ PUT2(code, 1+LINK_SIZE, cb->bracount);
+ skipunits = IMM2_SIZE;
}
/* Process nested bracketed regex. First check for parentheses nested too
deeply. */
- if ((cd->parens_depth += 1) > PARENS_NEST_LIMIT)
+ if ((cb->parens_depth += 1) > (int)(cb->cx->parens_nest_limit))
{
- *errorcodeptr = ERR82;
+ *errorcodeptr = ERR19;
goto FAILED;
}
@@ -7697,25 +7008,24 @@ for (;; ptr++)
conditions (Perl also forbids these to 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. At the start of a conditional
- group whose condition is an assertion, cd->iscondassert is set. We unset it
+ group whose condition is an assertion, cb->iscondassert is set. We unset it
here so as to allow assertions later in the group to be quantified. */
if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT &&
- cd->iscondassert)
+ cb->iscondassert)
{
previous = NULL;
- cd->iscondassert = FALSE;
+ cb->iscondassert = FALSE;
}
else
{
previous = code;
- item_hwm_offset = cd->hwm - cd->start_workspace;
}
*code = bravalue;
tempcode = code;
- tempreqvary = cd->req_varyopt; /* Save value before bracket */
- tempbracount = cd->bracount; /* Save value before bracket */
+ tempreqvary = cb->req_varyopt; /* Save value before bracket */
+ tempbracount = cb->bracount; /* Save value before bracket */
length_prevgroup = 0; /* Initialize for pre-compile phase */
if (!compile_regex(
@@ -7726,30 +7036,30 @@ for (;; ptr++)
(bravalue == OP_ASSERTBACK ||
bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */
reset_bracount, /* True if (?| group */
- skipbytes, /* Skip over bracket number */
+ skipunits, /* Skip over bracket number */
cond_depth +
((bravalue == OP_COND)?1:0), /* Depth of condition subpatterns */
- &subfirstchar, /* For possible first char */
- &subfirstcharflags,
- &subreqchar, /* For possible last char */
- &subreqcharflags,
+ &subfirstcu, /* For possible first char */
+ &subfirstcuflags,
+ &subreqcu, /* For possible last char */
+ &subreqcuflags,
bcptr, /* Current branch chain */
- cd, /* Tables block */
+ cb, /* Compile data block */
(lengthptr == NULL)? NULL : /* Actual compile phase */
&length_prevgroup /* Pre-compile phase */
))
goto FAILED;
- cd->parens_depth -= 1;
+ cb->parens_depth -= 1;
/* 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)
+ if (bravalue == OP_ONCE && cb->bracount <= tempbracount)
*code = OP_ONCE_NC;
if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT)
- cd->assert_depth -= 1;
+ cb->assert_depth -= 1;
/* At the end of compiling, code is still pointing to the start of the
group, while tempcode has been updated to point past the end of the group.
@@ -7762,7 +7072,7 @@ for (;; ptr++)
if (bravalue == OP_COND && lengthptr == NULL)
{
- pcre_uchar *tc = code;
+ PCRE2_UCHAR *tc = code;
int condcount = 0;
do {
@@ -7772,20 +7082,22 @@ for (;; ptr++)
while (*tc != OP_KET);
/* A DEFINE group is never obeyed inline (the "condition" is always
- false). It must have only one branch. */
+ false). It must have only one branch. Having checked this, change the
+ opcode to OP_FALSE. */
- if (code[LINK_SIZE+1] == OP_DEF)
+ if (code[LINK_SIZE+1] == OP_DEFINE)
{
if (condcount > 1)
{
*errorcodeptr = ERR54;
goto FAILED;
}
- bravalue = OP_DEF; /* Just a flag to suppress char handling below */
+ code[LINK_SIZE+1] = OP_FALSE;
+ bravalue = OP_DEFINE; /* 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
+ make use of its firstcu or reqcu, because this is equivalent to an
empty second branch. */
else
@@ -7795,11 +7107,13 @@ for (;; ptr++)
*errorcodeptr = ERR27;
goto FAILED;
}
- if (condcount == 1) subfirstcharflags = subreqcharflags = REQ_NONE;
+ if (condcount == 1) subfirstcuflags = subreqcuflags = REQ_NONE;
}
}
- /* Error if hit end of pattern */
+ /* At the end of a group, it's an error if we hit end of pattern or
+ any non-closing parenthesis. This check also happens in the pre-scan,
+ so should not trigger here, but leave this code as an insurance. */
if (*ptr != CHAR_RIGHT_PARENTHESIS)
{
@@ -7834,73 +7148,73 @@ for (;; ptr++)
/* For a DEFINE group, required and first character settings are not
relevant. */
- if (bravalue == OP_DEF) break;
+ if (bravalue == OP_DEFINE) 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
+ zero repeat, we have to back off. Hence the definition of zeroreqcu and
+ zerofirstcu outside the main loop so that they can be accessed for the
back off. */
- zeroreqchar = reqchar;
- zeroreqcharflags = reqcharflags;
- zerofirstchar = firstchar;
- zerofirstcharflags = firstcharflags;
- groupsetfirstchar = FALSE;
+ zeroreqcu = reqcu;
+ zeroreqcuflags = reqcuflags;
+ zerofirstcu = firstcu;
+ zerofirstcuflags = firstcuflags;
+ groupsetfirstcu = FALSE;
if (bravalue >= OP_ONCE)
{
- /* If we have not yet set a firstchar in this branch, take it from the
+ /* If we have not yet set a firstcu in this branch, take it from the
subpattern, remembering that it was set here so that a repeat of more
- than one can replicate it as 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". */
+ than one can replicate it as reqcu if necessary. If the subpattern has
+ no firstcu, set "none" for the whole branch. In both cases, a zero
+ repeat forces firstcu to "none". */
- if (firstcharflags == REQ_UNSET)
+ if (firstcuflags == REQ_UNSET && subfirstcuflags != REQ_UNSET)
{
- if (subfirstcharflags >= 0)
+ if (subfirstcuflags >= 0)
{
- firstchar = subfirstchar;
- firstcharflags = subfirstcharflags;
- groupsetfirstchar = TRUE;
+ firstcu = subfirstcu;
+ firstcuflags = subfirstcuflags;
+ groupsetfirstcu = TRUE;
}
- else firstcharflags = REQ_NONE;
- zerofirstcharflags = REQ_NONE;
+ else firstcuflags = REQ_NONE;
+ zerofirstcuflags = 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
+ /* If firstcu was previously set, convert the subpattern's firstcu
+ into reqcu if there wasn't one, using the vary flag that was in
existence beforehand. */
- else if (subfirstcharflags >= 0 && subreqcharflags < 0)
+ else if (subfirstcuflags >= 0 && subreqcuflags < 0)
{
- subreqchar = subfirstchar;
- subreqcharflags = subfirstcharflags | tempreqvary;
+ subreqcu = subfirstcu;
+ subreqcuflags = subfirstcuflags | 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 (subreqcharflags >= 0)
+ if (subreqcuflags >= 0)
{
- reqchar = subreqchar;
- reqcharflags = subreqcharflags;
+ reqcu = subreqcu;
+ reqcuflags = subreqcuflags;
}
}
- /* For a forward assertion, we take the reqchar, if set. This can be
+ /* For a forward assertion, we take the reqcu, 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
+ char. For example, it's useful for /(?=abcde).+/. We can't set firstcu
for an assertion, however because it leads to incorrect effect for patterns
- such as /(?=a)a.+/ when the "real" "a" would then become a 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. */
+ such as /(?=a)a.+/ when the "real" "a" would then become a reqcu instead
+ of a firstcu. This is overcome by a scan at the end if there's no
+ firstcu, looking for an asserted first char. */
- else if (bravalue == OP_ASSERT && subreqcharflags >= 0)
+ else if (bravalue == OP_ASSERT && subreqcuflags >= 0)
{
- reqchar = subreqchar;
- reqcharflags = subreqcharflags;
+ reqcu = subreqcu;
+ reqcuflags = subreqcuflags;
}
break; /* End of processing '(' */
@@ -7908,15 +7222,19 @@ for (;; ptr++)
/* ===================================================================*/
/* 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
+ default case when PCRE2_UCP is not set. For the back references, the values
are negative 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. */
+ ever created.
+
+ Note: \Q and \E are handled at the start of the character-processing loop,
+ not here. */
case CHAR_BACKSLASH:
tempptr = ptr;
- escape = check_escape(&ptr, &ec, errorcodeptr, cd->bracount, options, FALSE);
+ escape = PRIV(check_escape)(&ptr, cb->end_pattern, &ec, errorcodeptr,
+ options, FALSE, cb);
if (*errorcodeptr != 0) goto FAILED;
if (escape == 0) /* The escape coded a single character */
@@ -7926,15 +7244,15 @@ for (;; ptr++)
/* For metasequences that actually match a character, we disable the
setting of a first character if it hasn't already been set. */
- if (firstcharflags == REQ_UNSET && escape > ESC_b && escape < ESC_Z)
- firstcharflags = REQ_NONE;
+ if (firstcuflags == REQ_UNSET && escape > ESC_b && escape < ESC_Z)
+ firstcuflags = REQ_NONE;
/* Set values to reset to if this is followed by a zero repeat. */
- zerofirstchar = firstchar;
- zerofirstcharflags = firstcharflags;
- zeroreqchar = reqchar;
- zeroreqcharflags = reqcharflags;
+ zerofirstcu = firstcu;
+ zerofirstcuflags = firstcuflags;
+ zeroreqcu = reqcu;
+ zeroreqcuflags = reqcuflags;
/* \g<name> or \g'name' is a subroutine call by name and \g<n> or \g'n'
is a subroutine call by number (Oniguruma syntax). In fact, the value
@@ -7945,10 +7263,9 @@ for (;; ptr++)
if (escape == ESC_g)
{
- const pcre_uchar *p;
- pcre_uint32 cf;
+ PCRE2_SPTR p;
+ uint32_t cf;
- item_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */
terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)?
CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE;
@@ -7957,7 +7274,7 @@ for (;; ptr++)
fact, because we do the check for a number below, the paths that
would actually be in error are never taken. */
- skipbytes = 0;
+ skipunits = 0;
reset_bracount = FALSE;
/* If it's not a signed or unsigned number, treat it as a name. */
@@ -7974,7 +7291,7 @@ for (;; ptr++)
p = ptr + 2;
while (IS_DIGIT(*p)) p++;
- if (*p != (pcre_uchar)terminator)
+ if (*p != (PCRE2_UCHAR)terminator)
{
*errorcodeptr = ERR57;
goto FAILED;
@@ -8001,7 +7318,7 @@ for (;; ptr++)
goto NAMED_REF_OR_RECURSE;
}
- /* Back references are handled specially; must disable firstchar if
+ /* Back references are handled specially; must disable firstcu if
not set to cope with cases like (?=(\w+))\1: which would otherwise set
':' later. */
@@ -8011,22 +7328,26 @@ for (;; ptr++)
recno = -escape;
/* Come here from named backref handling when the reference is to a
- single group (i.e. not to a duplicated name. */
+ single group (i.e. not to a duplicated name). */
HANDLE_REFERENCE:
- if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE;
+ if (recno > (int)cb->final_bracount)
+ {
+ *errorcodeptr = ERR15;
+ goto FAILED;
+ }
+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
previous = code;
- item_hwm_offset = cd->hwm - cd->start_workspace;
- *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF;
+ *code++ = ((options & PCRE2_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;
+ cb->backref_map |= (recno < 32)? (1u << recno) : 1;
+ if ((uint32_t)recno > cb->top_backref) cb->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)
+ for (oc = cb->open_caps; oc != NULL; oc = oc->next)
{
if (oc->number == recno)
{
@@ -8038,15 +7359,14 @@ for (;; ptr++)
/* So are Unicode property matches, if supported. */
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
else if (escape == ESC_P || escape == ESC_p)
{
BOOL negated;
unsigned int ptype = 0, pdata = 0;
- if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr))
+ if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr, cb))
goto FAILED;
previous = code;
- item_hwm_offset = cd->hwm - cd->start_workspace;
*code++ = ((escape == ESC_p) != negated)? OP_PROP : OP_NOTPROP;
*code++ = ptype;
*code++ = pdata;
@@ -8063,32 +7383,54 @@ for (;; ptr++)
}
#endif
+ /* The use of \C can be locked out. */
+
+#ifdef NEVER_BACKSLASH_C
+ else if (escape == ESC_C)
+ {
+ *errorcodeptr = ERR85;
+ goto FAILED;
+ }
+#else
+ else if (escape == ESC_C && (options & PCRE2_NEVER_BACKSLASH_C) != 0)
+ {
+ *errorcodeptr = ERR83;
+ 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
+ situation when PCRE2_UCP is not set. When it *is* set, we substitute
Unicode property tests. Note that \b and \B do a one-character
lookbehind, and \A also behaves as if it does. */
else
{
+ if (escape == ESC_C) cb->external_flags |= PCRE2_HASBKC; /* Record */
if ((escape == ESC_b || escape == ESC_B || escape == ESC_A) &&
- cd->max_lookbehind == 0)
- cd->max_lookbehind = 1;
-#ifdef SUPPORT_UCP
+ cb->max_lookbehind == 0)
+ cb->max_lookbehind = 1;
+#ifdef SUPPORT_UNICODE
if (escape >= ESC_DU && escape <= ESC_wu)
{
- nestptr = ptr + 1; /* Where to resume */
+ cb->nestptr[1] = cb->nestptr[0]; /* Back up if at 2nd level */
+ cb->nestptr[0] = ptr + 1; /* Where to resume */
ptr = substitutes[escape - 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. */
+ /* In non-UTF mode, and for both 32-bit modes, we turn \C into
+ OP_ALLANY instead of OP_ANYBYTE so that it works in DFA mode and in
+ lookbehinds. */
{
previous = (escape > ESC_b && escape < ESC_Z)? code : NULL;
- item_hwm_offset = cd->hwm - cd->start_workspace;
+#if PCRE2_CODE_UNIT_WIDTH == 32
+ *code++ = (escape == ESC_C)? OP_ALLANY : escape;
+#else
*code++ = (!utf && escape == ESC_C)? OP_ALLANY : escape;
+#endif
}
}
continue;
@@ -8098,16 +7440,7 @@ for (;; ptr++)
a value > 127. We set its representation in the length/buffer, and then
handle it as a data character. */
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
- if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR)
- mclength = PRIV(ord2utf)(c, mcbuffer);
- else
-#endif
-
- {
- mcbuffer[0] = c;
- mclength = 1;
- }
+ mclength = PUTCHAR(c, mcbuffer);
goto ONE_CHAR;
@@ -8121,24 +7454,22 @@ for (;; ptr++)
mclength = 1;
mcbuffer[0] = c;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
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. */
+ in mclength. When not in UTF mode, the length is always 1. */
ONE_CHAR:
previous = code;
- item_hwm_offset = cd->hwm - cd->start_workspace;
- /* For caseless UTF-8 mode when UCP support is available, check whether
- this character has more than one other case. If so, generate a special
- OP_PROP item instead of OP_CHARI. */
+ /* For caseless UTF mode, check whether this character has more than one
+ other case. If so, generate a special OP_PROP item instead of OP_CHARI. */
-#ifdef SUPPORT_UCP
- if (utf && (options & PCRE_CASELESS) != 0)
+#ifdef SUPPORT_UNICODE
+ if (utf && (options & PCRE2_CASELESS) != 0)
{
GETCHAR(c, mcbuffer);
if ((c = UCD_CASESET(c)) != 0)
@@ -8146,8 +7477,8 @@ for (;; ptr++)
*code++ = OP_PROP;
*code++ = PT_CLIST;
*code++ = c;
- if (firstcharflags == REQ_UNSET)
- firstcharflags = zerofirstcharflags = REQ_NONE;
+ if (firstcuflags == REQ_UNSET)
+ firstcuflags = zerofirstcuflags = REQ_NONE;
break;
}
}
@@ -8155,56 +7486,56 @@ for (;; ptr++)
/* Caseful matches, or not one of the multicase characters. */
- *code++ = ((options & PCRE_CASELESS) != 0)? OP_CHARI : OP_CHAR;
+ *code++ = ((options & PCRE2_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;
+ cb->external_flags |= PCRE2_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
+ Otherwise, leave the firstcu value alone, and don't change it on a zero
repeat. */
- if (firstcharflags == REQ_UNSET)
+ if (firstcuflags == REQ_UNSET)
{
- zerofirstcharflags = REQ_NONE;
- zeroreqchar = reqchar;
- zeroreqcharflags = reqcharflags;
+ zerofirstcuflags = REQ_NONE;
+ zeroreqcu = reqcu;
+ zeroreqcuflags = reqcuflags;
- /* If the character is more than one byte long, we can set firstchar
+ /* If the character is more than one byte long, we can set firstcu
only if it is not to be matched caselessly. */
if (mclength == 1 || req_caseopt == 0)
{
- firstchar = mcbuffer[0] | req_caseopt;
- firstchar = mcbuffer[0];
- firstcharflags = req_caseopt;
+ firstcu = mcbuffer[0] | req_caseopt;
+ firstcu = mcbuffer[0];
+ firstcuflags = req_caseopt;
if (mclength != 1)
{
- reqchar = code[-1];
- reqcharflags = cd->req_varyopt;
+ reqcu = code[-1];
+ reqcuflags = cb->req_varyopt;
}
}
- else firstcharflags = reqcharflags = REQ_NONE;
+ else firstcuflags = reqcuflags = REQ_NONE;
}
- /* firstchar was previously set; we can set reqchar only if the length is
+ /* firstcu was previously set; we can set reqcu only if the length is
1 or the matching is caseful. */
else
{
- zerofirstchar = firstchar;
- zerofirstcharflags = firstcharflags;
- zeroreqchar = reqchar;
- zeroreqcharflags = reqcharflags;
+ zerofirstcu = firstcu;
+ zerofirstcuflags = firstcuflags;
+ zeroreqcu = reqcu;
+ zeroreqcuflags = reqcuflags;
if (mclength == 1 || req_caseopt == 0)
{
- reqchar = code[-1];
- reqcharflags = req_caseopt | cd->req_varyopt;
+ reqcu = code[-1];
+ reqcuflags = req_caseopt | cb->req_varyopt;
}
}
@@ -8212,7 +7543,6 @@ for (;; ptr++)
}
} /* 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. */
@@ -8225,7 +7555,7 @@ return FALSE;
/*************************************************
-* Compile sequence of alternatives *
+* Compile regex: a sequence of alternatives *
*************************************************/
/* On entry, ptr is pointing past the bracket character, but on return it
@@ -8242,14 +7572,14 @@ Arguments:
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)
+ skipunits skip this many code units at start (for brackets and OP_COND)
cond_depth depth of nesting for conditional subpatterns
- firstcharptr place to put the first required character
- firstcharflagsptr place to put the first character flags, or a negative number
- reqcharptr place to put the last required character
- reqcharflagsptr place to put the last required character flags, or a negative number
+ firstcuptr place to put the first required code unit
+ firstcuflagsptr place to put the first code unit flags, or a negative number
+ reqcuptr place to put the last required code unit
+ reqcuflagsptr place to put the last required code unit flags, or a negative number
bcptr pointer to the chain of currently open branches
- cd points to the data block with tables pointers etc.
+ cb points to the data block with tables pointers etc.
lengthptr NULL during the real compile phase
points to length accumulator during pre-compile phase
@@ -8257,35 +7587,34 @@ 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_uint32 *firstcharptr, pcre_int32 *firstcharflagsptr,
- pcre_uint32 *reqcharptr, pcre_int32 *reqcharflagsptr,
- branch_chain *bcptr, compile_data *cd, int *lengthptr)
+compile_regex(uint32_t options, PCRE2_UCHAR **codeptr, PCRE2_SPTR *ptrptr,
+ int *errorcodeptr, BOOL lookbehind, BOOL reset_bracount, uint32_t skipunits,
+ int cond_depth, uint32_t *firstcuptr, int32_t *firstcuflagsptr,
+ uint32_t *reqcuptr, int32_t *reqcuflagsptr, branch_chain *bcptr,
+ compile_block *cb, size_t *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;
+PCRE2_SPTR ptr = *ptrptr;
+PCRE2_UCHAR *code = *codeptr;
+PCRE2_UCHAR *last_branch = code;
+PCRE2_UCHAR *start_bracket = code;
+PCRE2_UCHAR *reverse_count = NULL;
open_capitem capitem;
int capnumber = 0;
-pcre_uint32 firstchar, reqchar;
-pcre_int32 firstcharflags, reqcharflags;
-pcre_uint32 branchfirstchar, branchreqchar;
-pcre_int32 branchfirstcharflags, branchreqcharflags;
-int length;
+uint32_t firstcu, reqcu;
+int32_t firstcuflags, reqcuflags;
+uint32_t branchfirstcu, branchreqcu;
+int32_t branchfirstcuflags, branchreqcuflags;
+size_t length;
unsigned int orig_bracount;
unsigned int max_bracount;
branch_chain bc;
-size_t save_hwm_offset;
/* If set, call the external function that checks for stack availability. */
-if (PUBL(stack_guard) != NULL && PUBL(stack_guard)())
+if (cb->cx->stack_guard != NULL &&
+ cb->cx->stack_guard(cb->parens_depth, cb->cx->stack_guard_data))
{
- *errorcodeptr= ERR85;
+ *errorcodeptr= ERR33;
return FALSE;
}
@@ -8294,26 +7623,24 @@ if (PUBL(stack_guard) != NULL && PUBL(stack_guard)())
bc.outer = bcptr;
bc.current_branch = code;
-firstchar = reqchar = 0;
-firstcharflags = reqcharflags = REQ_UNSET;
-
-save_hwm_offset = cd->hwm - cd->start_workspace;
+firstcu = reqcu = 0;
+firstcuflags = reqcuflags = REQ_UNSET;
/* Accumulate the length for use in the pre-compile phase. Start with the
-length of the BRA and KET and any extra bytes that are required at the
+length of the BRA and KET and any extra code units that are required at the
beginning. We accumulate in a local variable to save frequent testing of
-lenthptr for NULL. We cannot do this by looking at the value of code at the
+lengthptr for NULL. We cannot do this by looking at the value of 'code' at the
start and end of each alternative, because compiled items are discarded during
the pre-compile phase so that the work space is not exceeded. */
-length = 2 + 2*LINK_SIZE + skipbytes;
+length = 2 + 2*LINK_SIZE + skipunits;
/* 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. */
+pre-compile phase to find out whether or not anything has yet been compiled.
-/* If this is a capturing subpattern, add to the chain of open capturing items
+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,
@@ -8323,25 +7650,26 @@ if (*code == OP_CBRA)
{
capnumber = GET2(code, 1 + LINK_SIZE);
capitem.number = capnumber;
- capitem.next = cd->open_caps;
+ capitem.next = cb->open_caps;
capitem.flag = FALSE;
- cd->open_caps = &capitem;
+ cb->open_caps = &capitem;
}
/* Offset is set zero to mark that this bracket is still open */
PUT(code, 1, 0);
-code += 1 + LINK_SIZE + skipbytes;
+code += 1 + LINK_SIZE + skipunits;
/* Loop for each alternative branch */
-orig_bracount = max_bracount = cd->bracount;
+orig_bracount = max_bracount = cb->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;
+ if (reset_bracount) cb->bracount = orig_bracount;
/* Set up dummy OP_REVERSE if lookbehind assertion */
@@ -8356,9 +7684,9 @@ for (;;)
/* Now compile the branch; in the pre-compile phase its length gets added
into the length. */
- if (!compile_branch(&options, &code, &ptr, errorcodeptr, &branchfirstchar,
- &branchfirstcharflags, &branchreqchar, &branchreqcharflags, &bc,
- cond_depth, cd, (lengthptr == NULL)? NULL : &length))
+ if (!compile_branch(&options, &code, &ptr, errorcodeptr, &branchfirstcu,
+ &branchfirstcuflags, &branchreqcu, &branchreqcuflags, &bc,
+ cond_depth, cb, (lengthptr == NULL)? NULL : &length))
{
*ptrptr = ptr;
return FALSE;
@@ -8367,96 +7695,98 @@ for (;;)
/* 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;
+ if (cb->bracount > max_bracount) max_bracount = cb->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
+ /* If this is the first branch, the firstcu and reqcu values for the
branch become the values for the regex. */
if (*last_branch != OP_ALT)
{
- firstchar = branchfirstchar;
- firstcharflags = branchfirstcharflags;
- reqchar = branchreqchar;
- reqcharflags = branchreqcharflags;
+ firstcu = branchfirstcu;
+ firstcuflags = branchfirstcuflags;
+ reqcu = branchreqcu;
+ reqcuflags = branchreqcuflags;
}
- /* If this is not the first branch, the first char and reqchar have to
+ /* If this is not the first branch, the first char and reqcu have to
match the values from all the previous branches, except that if the
- previous value for reqchar didn't have REQ_VARY set, it can still match,
+ previous value for reqcu 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 we previously had a firstcu, but it doesn't match the new branch,
+ we have to abandon the firstcu for the regex, but if there was
+ previously no reqcu, it takes on the value of the old firstcu. */
- if (firstcharflags >= 0 &&
- (firstcharflags != branchfirstcharflags || firstchar != branchfirstchar))
+ if (firstcuflags != branchfirstcuflags || firstcu != branchfirstcu)
{
- if (reqcharflags < 0)
+ if (firstcuflags >= 0)
{
- reqchar = firstchar;
- reqcharflags = firstcharflags;
+ if (reqcuflags < 0)
+ {
+ reqcu = firstcu;
+ reqcuflags = firstcuflags;
+ }
}
- firstcharflags = REQ_NONE;
+ firstcuflags = 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 we (now or from before) have no firstcu, a firstcu from the
+ branch becomes a reqcu if there isn't a branch reqcu. */
- if (firstcharflags < 0 && branchfirstcharflags >= 0 && branchreqcharflags < 0)
+ if (firstcuflags < 0 && branchfirstcuflags >= 0 &&
+ branchreqcuflags < 0)
{
- branchreqchar = branchfirstchar;
- branchreqcharflags = branchfirstcharflags;
+ branchreqcu = branchfirstcu;
+ branchreqcuflags = branchfirstcuflags;
}
- /* Now ensure that the reqchars match */
+ /* Now ensure that the reqcus match */
- if (((reqcharflags & ~REQ_VARY) != (branchreqcharflags & ~REQ_VARY)) ||
- reqchar != branchreqchar)
- reqcharflags = REQ_NONE;
+ if (((reqcuflags & ~REQ_VARY) != (branchreqcuflags & ~REQ_VARY)) ||
+ reqcu != branchreqcu)
+ reqcuflags = REQ_NONE;
else
{
- reqchar = branchreqchar;
- reqcharflags |= branchreqcharflags; /* To "or" REQ_VARY */
+ reqcu = branchreqcu;
+ reqcuflags |= branchreqcuflags; /* 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. */
+ branch with OP_END. If the branch contains OP_RECURSE, the result is
+ FFL_LATER (a negative value) 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 errors can be picked up
+ here and the offset of the problem can be shown. */
if (lookbehind)
{
int fixed_length;
+ int count = 0;
*code = OP_END;
- fixed_length = find_fixedlength(last_branch, (options & PCRE_UTF8) != 0,
- FALSE, cd, NULL);
- DPRINTF(("fixed length = %d\n", fixed_length));
- if (fixed_length == -3)
+ fixed_length = find_fixedlength(last_branch, (options & PCRE2_UTF) != 0,
+ FALSE, cb, NULL, &count);
+ if (fixed_length == FFL_LATER)
{
- cd->check_lookbehind = TRUE;
+ cb->check_lookbehind = TRUE;
}
else if (fixed_length < 0)
{
- *errorcodeptr = (fixed_length == -2)? ERR36 :
- (fixed_length == -4)? ERR70: ERR25;
+ *errorcodeptr = fixed_length_errors[-fixed_length];
*ptrptr = ptr;
return FALSE;
}
else
{
- if (fixed_length > cd->max_lookbehind)
- cd->max_lookbehind = fixed_length;
+ if (fixed_length > cb->max_lookbehind)
+ cb->max_lookbehind = fixed_length;
PUT(reverse_count, 0, fixed_length);
}
}
@@ -8473,10 +7803,10 @@ for (;;)
{
if (lengthptr == NULL)
{
- int branch_length = (int)(code - last_branch);
+ size_t branch_length = code - last_branch;
do
{
- int prev_length = GET(last_branch, 1);
+ size_t prev_length = GET(last_branch, 1);
PUT(last_branch, 1, branch_length);
branch_length = prev_length;
last_branch -= branch_length;
@@ -8491,19 +7821,15 @@ for (;;)
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.
- Because we are moving code along, we must ensure that any pending recursive
- references are updated. In any event, remove the block from the chain. */
+ 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)
+ if (cb->open_caps->flag)
{
- *code = OP_END;
- adjust_recurse(start_bracket, 1 + LINK_SIZE,
- (options & PCRE_UTF8) != 0, cd, save_hwm_offset);
memmove(start_bracket + 1 + LINK_SIZE, start_bracket,
- IN_UCHARS(code - start_bracket));
+ CU2BYTES(code - start_bracket));
*start_bracket = OP_ONCE;
code += 1 + LINK_SIZE;
PUT(start_bracket, 1, (int)(code - start_bracket));
@@ -8512,21 +7838,21 @@ for (;;)
code += 1 + LINK_SIZE;
length += 2 + 2*LINK_SIZE;
}
- cd->open_caps = cd->open_caps->next;
+ cb->open_caps = cb->open_caps->next;
}
/* Retain the highest bracket number, in case resetting was used. */
- cd->bracount = max_bracount;
+ cb->bracount = max_bracount;
/* Set values to pass back */
*codeptr = code;
*ptrptr = ptr;
- *firstcharptr = firstchar;
- *firstcharflagsptr = firstcharflags;
- *reqcharptr = reqchar;
- *reqcharflagsptr = reqcharflags;
+ *firstcuptr = firstcu;
+ *firstcuflagsptr = firstcuflags;
+ *reqcuptr = reqcu;
+ *reqcuflagsptr = reqcuflags;
if (lengthptr != NULL)
{
if (OFLOW_MAX - *lengthptr < length)
@@ -8550,7 +7876,7 @@ for (;;)
if (lengthptr != NULL)
{
- code = *codeptr + 1 + LINK_SIZE + skipbytes;
+ code = *codeptr + 1 + LINK_SIZE + skipunits;
length += 1 + LINK_SIZE;
}
else
@@ -8561,6 +7887,8 @@ for (;;)
code += 1 + LINK_SIZE;
}
+ /* Advance past the vertical bar */
+
ptr++;
}
/* Control never reaches here */
@@ -8568,9 +7896,8 @@ for (;;)
-
/*************************************************
-* Check for anchored expression *
+* Check for anchored pattern *
*************************************************/
/* Try to find out if this is an anchored regular expression. Consider each
@@ -8600,22 +7927,22 @@ of the more common cases more precisely.
this prevents the number of characters it matches from being adjusted.
Arguments:
- code points to start of expression (the bracket)
+ code points to start of the compiled pattern
bracket_map a bitmap of which brackets we are inside while testing; this
- handles up to substring 31; after that we just have to take
- the less precise approach
- cd points to the compile data block
+ handles up to substring 31; after that we just have to take
+ the less precise approach
+ cb points to the compile data block
atomcount atomic group level
Returns: TRUE or FALSE
*/
static BOOL
-is_anchored(register const pcre_uchar *code, unsigned int bracket_map,
- compile_data *cd, int atomcount)
+is_anchored(register PCRE2_SPTR code, unsigned int bracket_map,
+ compile_block *cb, int atomcount)
{
do {
- const pcre_uchar *scode = first_significant_code(
+ PCRE2_SPTR scode = first_significant_code(
code + PRIV(OP_lengths)[*code], FALSE);
register int op = *scode;
@@ -8624,7 +7951,7 @@ do {
if (op == OP_BRA || op == OP_BRAPOS ||
op == OP_SBRA || op == OP_SBRAPOS)
{
- if (!is_anchored(scode, bracket_map, cd, atomcount)) return FALSE;
+ if (!is_anchored(scode, bracket_map, cb, atomcount)) return FALSE;
}
/* Capturing brackets */
@@ -8633,34 +7960,35 @@ do {
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, cd, atomcount)) return FALSE;
+ int new_map = bracket_map | ((n < 32)? (1u << n) : 1);
+ if (!is_anchored(scode, new_map, cb, atomcount)) return FALSE;
}
/* Positive forward assertions and conditions */
else if (op == OP_ASSERT || op == OP_COND)
{
- if (!is_anchored(scode, bracket_map, cd, atomcount)) return FALSE;
+ if (!is_anchored(scode, bracket_map, cb, atomcount)) return FALSE;
}
/* Atomic groups */
else if (op == OP_ONCE || op == OP_ONCE_NC)
{
- if (!is_anchored(scode, bracket_map, cd, atomcount + 1))
+ if (!is_anchored(scode, bracket_map, cb, atomcount + 1))
return FALSE;
}
/* .* is not anchored unless DOTALL is set (which generates OP_ALLANY) and
it isn't in brackets that are or may be referenced or inside an atomic
- group. */
+ group. There is also an option that disables auto-anchoring. */
else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR ||
op == OP_TYPEPOSSTAR))
{
- if (scode[1] != OP_ALLANY || (bracket_map & cd->backref_map) != 0 ||
- atomcount > 0 || cd->had_pruneorskip)
+ if (scode[1] != OP_ALLANY || (bracket_map & cb->backref_map) != 0 ||
+ atomcount > 0 || cb->had_pruneorskip ||
+ (cb->external_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)
return FALSE;
}
@@ -8690,22 +8018,22 @@ inside atomic brackets or in a pattern that contains *PRUNE or *SKIP does not
count, because once again the assumption no longer holds.
Arguments:
- code points to start of expression (the bracket)
+ code points to start of the compiled pattern or a group
bracket_map a bitmap of which brackets we are inside while testing; this
- handles up to substring 31; after that we just have to take
- the less precise approach
- cd points to the compile data
+ handles up to substring 31; after that we just have to take
+ the less precise approach
+ cb points to the compile data
atomcount atomic group level
Returns: TRUE or FALSE
*/
static BOOL
-is_startline(const pcre_uchar *code, unsigned int bracket_map,
- compile_data *cd, int atomcount)
+is_startline(PCRE2_SPTR code, unsigned int bracket_map, compile_block *cb,
+ int atomcount)
{
do {
- const pcre_uchar *scode = first_significant_code(
+ PCRE2_SPTR scode = first_significant_code(
code + PRIV(OP_lengths)[*code], FALSE);
register int op = *scode;
@@ -8717,19 +8045,23 @@ do {
if (op == OP_COND)
{
scode += 1 + LINK_SIZE;
+
if (*scode == OP_CALLOUT) scode += PRIV(OP_lengths)[OP_CALLOUT];
+ else if (*scode == OP_CALLOUT_STR) scode += GET(scode, 1 + 2*LINK_SIZE);
+
switch (*scode)
{
case OP_CREF:
case OP_DNCREF:
case OP_RREF:
case OP_DNRREF:
- case OP_DEF:
case OP_FAIL:
+ case OP_FALSE:
+ case OP_TRUE:
return FALSE;
default: /* Assertion */
- if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE;
+ if (!is_startline(scode, bracket_map, cb, atomcount)) return FALSE;
do scode += GET(scode, 1); while (*scode == OP_ALT);
scode += 1 + LINK_SIZE;
break;
@@ -8743,7 +8075,7 @@ do {
if (op == OP_BRA || op == OP_BRAPOS ||
op == OP_SBRA || op == OP_SBRAPOS)
{
- if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE;
+ if (!is_startline(scode, bracket_map, cb, atomcount)) return FALSE;
}
/* Capturing brackets */
@@ -8752,34 +8084,35 @@ do {
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, cd, atomcount)) return FALSE;
+ int new_map = bracket_map | ((n < 32)? (1u << n) : 1);
+ if (!is_startline(scode, new_map, cb, atomcount)) return FALSE;
}
/* Positive forward assertions */
else if (op == OP_ASSERT)
{
- if (!is_startline(scode, bracket_map, cd, atomcount)) return FALSE;
+ if (!is_startline(scode, bracket_map, cb, atomcount)) return FALSE;
}
/* Atomic brackets */
else if (op == OP_ONCE || op == OP_ONCE_NC)
{
- if (!is_startline(scode, bracket_map, cd, atomcount + 1)) return FALSE;
+ if (!is_startline(scode, bracket_map, cb, atomcount + 1)) return FALSE;
}
/* .* means "start at start or after \n" if it isn't in atomic brackets or
brackets that may be referenced, as long as the pattern does not contain
*PRUNE or *SKIP, because these break the feature. Consider, for example,
/.*?a(*PRUNE)b/ with the subject "aab", which matches "ab", i.e. not at the
- start of a line. */
+ start of a line. There is also an option that disables this optimization. */
else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR)
{
- if (scode[1] != OP_ANY || (bracket_map & cd->backref_map) != 0 ||
- atomcount > 0 || cd->had_pruneorskip)
+ if (scode[1] != OP_ANY || (bracket_map & cb->backref_map) != 0 ||
+ atomcount > 0 || cb->had_pruneorskip ||
+ (cb->external_options & PCRE2_NO_DOTSTAR_ANCHOR) != 0)
return FALSE;
}
@@ -8801,42 +8134,41 @@ return TRUE;
/*************************************************
-* Check for asserted fixed first char *
+* Check for asserted fixed first code unit *
*************************************************/
-/* 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
-non-conditional bracket all of whose alternatives start with the same asserted
-char (recurse ad lib), then we return that char, with the flags set to zero or
-REQ_CASELESS; otherwise return zero with REQ_NONE in the flags.
+/* During compilation, the "first code unit" settings from forward assertions
+are discarded, because they can cause conflicts with actual literals that
+follow. However, if we end up without a first code unit setting for an
+unanchored pattern, it is worth scanning the regex to see if there is an
+initial asserted first code unit. If all branches start with the same asserted
+code unit, or with a non-conditional bracket all of whose alternatives start
+with the same asserted code unit (recurse ad lib), then we return that code
+unit, with the flags set to zero or REQ_CASELESS; otherwise return zero with
+REQ_NONE in the flags.
Arguments:
- code points to start of expression (the bracket)
- flags points to the first char flags, or to REQ_NONE
+ code points to start of compiled pattern
+ flags points to the first code unit flags
inassert TRUE if in an assertion
-Returns: the fixed first char, or 0 with REQ_NONE in flags
+Returns: the fixed first code unit, or 0 with REQ_NONE in flags
*/
-static pcre_uint32
-find_firstassertedchar(const pcre_uchar *code, pcre_int32 *flags,
- BOOL inassert)
+static uint32_t
+find_firstassertedcu(PCRE2_SPTR code, int32_t *flags, BOOL inassert)
{
-register pcre_uint32 c = 0;
+register uint32_t c = 0;
int cflags = REQ_NONE;
*flags = REQ_NONE;
do {
- pcre_uint32 d;
+ uint32_t d;
int dflags;
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 pcre_uchar op = *scode;
+ PCRE2_SPTR scode = first_significant_code(code + 1+LINK_SIZE + xl, TRUE);
+ register PCRE2_UCHAR op = *scode;
switch(op)
{
@@ -8852,10 +8184,11 @@ do {
case OP_ASSERT:
case OP_ONCE:
case OP_ONCE_NC:
- d = find_firstassertedchar(scode, &dflags, op == OP_ASSERT);
+ d = find_firstassertedcu(scode, &dflags, op == OP_ASSERT);
if (dflags < 0)
return 0;
- if (cflags < 0) { c = d; cflags = dflags; } else if (c != d || cflags != dflags) return 0;
+ if (cflags < 0) { c = d; cflags = dflags; }
+ else if (c != d || cflags != dflags) return 0;
break;
case OP_EXACT:
@@ -8904,7 +8237,7 @@ name/number table, maintaining alphabetical order. Checking for permitted
and forbidden duplicates has already been done.
Arguments:
- cd the compile data block
+ cb the compile data block
name the name to add
length the length of the name
groupno the group number
@@ -8913,15 +8246,15 @@ Returns: nothing
*/
static void
-add_name(compile_data *cd, const pcre_uchar *name, int length,
+add_name_to_table(compile_block *cb, PCRE2_SPTR name, int length,
unsigned int groupno)
{
int i;
-pcre_uchar *slot = cd->name_table;
+PCRE2_UCHAR *slot = cb->name_table;
-for (i = 0; i < cd->names_found; i++)
+for (i = 0; i < cb->names_found; i++)
{
- int crc = memcmp(name, slot+IMM2_SIZE, IN_UCHARS(length));
+ int crc = memcmp(name, slot+IMM2_SIZE, CU2BYTES(length));
if (crc == 0 && slot[IMM2_SIZE+length] != 0)
crc = -1; /* Current name is a substring */
@@ -8932,598 +8265,619 @@ for (i = 0; i < cd->names_found; i++)
if (crc < 0)
{
- memmove(slot + cd->name_entry_size, slot,
- IN_UCHARS((cd->names_found - i) * cd->name_entry_size));
+ memmove(slot + cb->name_entry_size, slot,
+ CU2BYTES((cb->names_found - i) * cb->name_entry_size));
break;
}
/* Continue the loop for a later or duplicate name */
- slot += cd->name_entry_size;
+ slot += cb->name_entry_size;
}
PUT2(slot, 0, groupno);
-memcpy(slot + IMM2_SIZE, name, IN_UCHARS(length));
-slot[IMM2_SIZE + length] = 0;
-cd->names_found++;
+memcpy(slot + IMM2_SIZE, name, CU2BYTES(length));
+cb->names_found++;
+
+/* Add a terminating zero and fill the rest of the slot with zeroes so that
+the memory is all initialized. Otherwise valgrind moans about uninitialized
+memory when saving serialized compiled patterns. */
+
+memset(slot + IMM2_SIZE + length, 0,
+ CU2BYTES(cb->name_entry_size - length - IMM2_SIZE));
}
/*************************************************
-* Compile a Regular Expression *
+* External function to compile a pattern *
*************************************************/
-/* 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.
+/* This function reads a regular expression in the form of a string and returns
+a pointer to a block of store holding a compiled version of the expression.
Arguments:
pattern the regular expression
- 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
+ patlen the length of the pattern, or PCRE2_ZERO_TERMINATED
+ options option bits
+ errorptr pointer to errorcode
+ erroroffset pointer to error offset
+ ccontext points to a compile context or is NULL
Returns: pointer to compiled data block, or NULL on error,
- with errorptr and erroroffset set
+ with errorcode and erroroffset set
*/
-#if defined 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)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN pcre16 * PCRE_CALL_CONVENTION
-pcre16_compile(PCRE_SPTR16 pattern, int options, const char **errorptr,
- int *erroroffset, const unsigned char *tables)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN pcre32 * PCRE_CALL_CONVENTION
-pcre32_compile(PCRE_SPTR32 pattern, int options, const char **errorptr,
- int *erroroffset, const unsigned char *tables)
-#endif
+PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION
+pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE patlen, uint32_t options,
+ int *errorptr, PCRE2_SIZE *erroroffset, pcre2_compile_context *ccontext)
{
-#if defined COMPILE_PCRE8
-return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
-#elif defined COMPILE_PCRE16
-return pcre16_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
-#elif defined COMPILE_PCRE32
-return pcre32_compile2(pattern, options, NULL, errorptr, erroroffset, tables);
-#endif
-}
+BOOL utf; /* Set TRUE for UTF mode */
+pcre2_real_code *re = NULL; /* What we will return */
+compile_block cb; /* "Static" compile-time data */
+const uint8_t *tables; /* Char tables base pointer */
+PCRE2_UCHAR *code; /* Current pointer in compiled code */
+PCRE2_SPTR codestart; /* Start of compiled code */
+PCRE2_SPTR ptr; /* Current pointer in pattern */
-#if defined 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)
-#elif defined COMPILE_PCRE16
-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)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN pcre32 * PCRE_CALL_CONVENTION
-pcre32_compile2(PCRE_SPTR32 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 firstcharflags, reqcharflags;
-pcre_uint32 firstchar, reqchar;
-pcre_uint32 limit_match = PCRE_UINT32_MAX;
-pcre_uint32 limit_recursion = PCRE_UINT32_MAX;
-int newline;
-int errorcode = 0;
-int skipatstart = 0;
-BOOL utf;
-BOOL never_utf = FALSE;
-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];
-
-/* This vector is used for remembering name groups during the pre-compile. In a
-similar way to cworkspace, it can be expanded using malloc() if necessary. */
+size_t length = 1; /* Allow or final END opcode */
+size_t usedlength; /* Actual length used */
+size_t re_blocksize; /* Size of memory block */
+int32_t firstcuflags, reqcuflags; /* Type of first/req code unit */
+uint32_t firstcu, reqcu; /* Value of first/req code unit */
+uint32_t setflags = 0; /* NL and BSR set flags */
+
+uint32_t skipatstart; /* When checking (*UTF) etc */
+uint32_t limit_match = UINT32_MAX; /* Unset match limits */
+uint32_t limit_recursion = UINT32_MAX;
+
+int newline = 0; /* Unset; can be set by the pattern */
+int bsr = 0; /* Unset; can be set by the pattern */
+int errorcode = 0; /* Initialize to avoid compiler warn */
+
+/* Comments at the head of this file explain about these variables. */
+
+PCRE2_UCHAR *copied_pattern = NULL;
+PCRE2_UCHAR stack_copied_pattern[COPIED_PATTERN_SIZE];
named_group named_groups[NAMED_GROUP_LIST_SIZE];
-/* Set this early so that early errors get offset 0. */
+/* The workspace is used in different ways in the different compiling phases.
+It needs to be 16-bit aligned for the preliminary group scan, and 32-bit
+aligned for the group information cache. */
+
+uint32_t c32workspace[C32_WORK_SIZE];
+PCRE2_UCHAR *cworkspace = (PCRE2_UCHAR *)c32workspace;
+
-ptr = (const pcre_uchar *)pattern;
+/* -------------- Check arguments and set up the 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. */
+/* There must be error code and offset pointers. */
-if (errorptr == NULL)
+if (errorptr == NULL || erroroffset == NULL) return NULL;
+*errorptr = ERR0;
+*erroroffset = 0;
+
+/* There must be a pattern! */
+
+if (pattern == NULL)
{
- if (errorcodeptr != NULL) *errorcodeptr = 99;
+ *errorptr = ERR16;
return NULL;
}
-*errorptr = NULL;
-if (errorcodeptr != NULL) *errorcodeptr = ERR0;
+/* Check that all undefined public option bits are zero. */
-/* However, we can give a message for this error */
-
-if (erroroffset == NULL)
+if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0)
{
- errorcode = ERR16;
- goto PCRE_EARLY_ERROR_RETURN2;
+ *errorptr = ERR17;
+ return NULL;
}
-*erroroffset = 0;
-
-/* Set up pointers to the individual character tables */
+/* A NULL compile context means "use a default context" */
-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;
+if (ccontext == NULL)
+ ccontext = (pcre2_compile_context *)(&PRIV(default_compile_context));
-/* Check that all undefined public option bits are zero */
+/* A zero-terminated pattern is indicated by the special length value
+PCRE2_ZERO_TERMINATED. Otherwise, we make a copy of the pattern and add a zero,
+to ensure that it is always possible to look one code unit beyond the end of
+the pattern's characters. In both cases, check that the pattern is overlong. */
-if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0)
+if (patlen == PCRE2_ZERO_TERMINATED)
+ {
+ patlen = PRIV(strlen)(pattern);
+ if (patlen > ccontext->max_pattern_length)
+ {
+ *errorptr = ERR88;
+ return NULL;
+ }
+ }
+else
{
- errorcode = ERR17;
- goto PCRE_EARLY_ERROR_RETURN;
+ if (patlen > ccontext->max_pattern_length)
+ {
+ *errorptr = ERR88;
+ return NULL;
+ }
+ if (patlen < COPIED_PATTERN_SIZE)
+ copied_pattern = stack_copied_pattern;
+ else
+ {
+ copied_pattern = ccontext->memctl.malloc(CU2BYTES(patlen + 1),
+ ccontext->memctl.memory_data);
+ if (copied_pattern == NULL)
+ {
+ *errorptr = ERR21;
+ return NULL;
+ }
+ }
+ memcpy(copied_pattern, pattern, CU2BYTES(patlen));
+ copied_pattern[patlen] = 0;
+ pattern = copied_pattern;
}
-/* If PCRE_NEVER_UTF is set, remember it. */
+/* ------------ Initialize the "static" compile data -------------- */
+
+tables = (ccontext->tables != NULL)? ccontext->tables : PRIV(default_tables);
+
+cb.lcc = tables + lcc_offset; /* Individual */
+cb.fcc = tables + fcc_offset; /* character */
+cb.cbits = tables + cbits_offset; /* tables */
+cb.ctypes = tables + ctypes_offset;
+
+cb.assert_depth = 0;
+cb.bracount = cb.final_bracount = 0;
+cb.cx = ccontext;
+cb.dupnames = FALSE;
+cb.end_pattern = pattern + patlen;
+cb.nestptr[0] = cb.nestptr[1] = NULL;
+cb.external_flags = 0;
+cb.external_options = options;
+cb.groupinfo = c32workspace;
+cb.had_recurse = FALSE;
+cb.iscondassert = FALSE;
+cb.max_lookbehind = 0;
+cb.name_entry_size = 0;
+cb.name_table = NULL;
+cb.named_groups = named_groups;
+cb.named_group_list_size = NAMED_GROUP_LIST_SIZE;
+cb.names_found = 0;
+cb.open_caps = NULL;
+cb.parens_depth = 0;
+cb.req_varyopt = 0;
+cb.start_code = cworkspace;
+cb.start_pattern = pattern;
+cb.start_workspace = cworkspace;
+cb.workspace_size = COMPILE_WORK_SIZE;
+
+/* Maximum back reference and backref bitmap. The bitmap records up to 31 back
+references to help in deciding whether (.*) can be treated as anchored or not.
+*/
+
+cb.top_backref = 0;
+cb.backref_map = 0;
-if ((options & PCRE_NEVER_UTF) != 0) never_utf = TRUE;
+/* --------------- Start looking at the pattern --------------- */
-/* Check for global one-time settings at the start of the pattern, and remember
-the offset for later. */
+/* Check for global one-time option settings at the start of the pattern, and
+remember the offset to the actual regex. */
-cd->external_flags = 0; /* Initialize here for LIMIT_MATCH/RECURSION */
+ptr = pattern;
+skipatstart = 0;
while (ptr[skipatstart] == CHAR_LEFT_PARENTHESIS &&
ptr[skipatstart+1] == CHAR_ASTERISK)
{
- int newnl = 0;
- int newbsr = 0;
+ unsigned int i;
+ for (i = 0; i < sizeof(pso_list)/sizeof(pso); i++)
+ {
+ pso *p = pso_list + i;
-/* For completeness and backward compatibility, (*UTFn) is supported in the
-relevant libraries, but (*UTF) is generic and always supported. Note that
-PCRE_UTF8 == PCRE_UTF16 == PCRE_UTF32. */
+ if (PRIV(strncmp_c8)(ptr+skipatstart+2, (char *)(p->name), p->length) == 0)
+ {
+ uint32_t c, pp;
-#ifdef COMPILE_PCRE8
- if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF8_RIGHTPAR, 5) == 0)
- { skipatstart += 7; options |= PCRE_UTF8; continue; }
-#endif
-#ifdef COMPILE_PCRE16
- if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF16_RIGHTPAR, 6) == 0)
- { skipatstart += 8; options |= PCRE_UTF16; continue; }
-#endif
-#ifdef COMPILE_PCRE32
- if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF32_RIGHTPAR, 6) == 0)
- { skipatstart += 8; options |= PCRE_UTF32; continue; }
-#endif
+ skipatstart += p->length + 2;
+ switch(p->type)
+ {
+ case PSO_OPT:
+ cb.external_options |= p->value;
+ break;
- else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF_RIGHTPAR, 4) == 0)
- { skipatstart += 6; options |= PCRE_UTF8; continue; }
- 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_AUTO_POSSESS_RIGHTPAR, 16) == 0)
- { skipatstart += 18; options |= PCRE_NO_AUTO_POSSESS; continue; }
- else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_NO_START_OPT_RIGHTPAR, 13) == 0)
- { skipatstart += 15; options |= PCRE_NO_START_OPTIMIZE; continue; }
+ case PSO_FLG:
+ setflags |= p->value;
+ break;
- else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_LIMIT_MATCH_EQ, 12) == 0)
- {
- pcre_uint32 c = 0;
- int p = skipatstart + 14;
- while (isdigit(ptr[p]))
- {
- if (c > PCRE_UINT32_MAX / 10 - 1) break; /* Integer overflow */
- c = c*10 + ptr[p++] - CHAR_0;
- }
- if (ptr[p++] != CHAR_RIGHT_PARENTHESIS) break;
- if (c < limit_match)
- {
- limit_match = c;
- cd->external_flags |= PCRE_MLSET;
- }
- skipatstart = p;
- continue;
- }
+ case PSO_NL:
+ newline = p->value;
+ setflags |= PCRE2_NL_SET;
+ break;
- else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_LIMIT_RECURSION_EQ, 16) == 0)
- {
- pcre_uint32 c = 0;
- int p = skipatstart + 18;
- while (isdigit(ptr[p]))
- {
- if (c > PCRE_UINT32_MAX / 10 - 1) break; /* Integer overflow check */
- c = c*10 + ptr[p++] - CHAR_0;
- }
- if (ptr[p++] != CHAR_RIGHT_PARENTHESIS) break;
- if (c < limit_recursion)
- {
- limit_recursion = c;
- cd->external_flags |= PCRE_RLSET;
+ case PSO_BSR:
+ bsr = p->value;
+ setflags |= PCRE2_BSR_SET;
+ break;
+
+ case PSO_LIMM:
+ case PSO_LIMR:
+ c = 0;
+ pp = skipatstart;
+ if (!IS_DIGIT(ptr[pp]))
+ {
+ errorcode = ERR60;
+ ptr += pp;
+ goto HAD_ERROR;
+ }
+ while (IS_DIGIT(ptr[pp]))
+ {
+ if (c > UINT32_MAX / 10 - 1) break; /* Integer overflow */
+ c = c*10 + (ptr[pp++] - CHAR_0);
+ }
+ if (ptr[pp++] != CHAR_RIGHT_PARENTHESIS)
+ {
+ errorcode = ERR60;
+ ptr += pp;
+ goto HAD_ERROR;
+ }
+ if (p->type == PSO_LIMM) limit_match = c;
+ else limit_recursion = c;
+ skipatstart += pp - skipatstart;
+ break;
+ }
+ break; /* Out of the table scan loop */
}
- skipatstart = p;
- 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;
+ if (i >= sizeof(pso_list)/sizeof(pso)) break; /* Out of pso loop */
}
-/* PCRE_UTF(16|32) have the same value as PCRE_UTF8. */
-utf = (options & PCRE_UTF8) != 0;
-if (utf && never_utf)
- {
- errorcode = ERR78;
- goto PCRE_EARLY_ERROR_RETURN2;
- }
+/* End of pattern-start options; advance to start of real regex. */
-/* 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. */
+ptr += skipatstart;
-#ifdef SUPPORT_UTF
-if (utf && (options & PCRE_NO_UTF8_CHECK) == 0 &&
- (errorcode = PRIV(valid_utf)((PCRE_PUCHAR)pattern, -1, erroroffset)) != 0)
- {
-#if defined COMPILE_PCRE8
- errorcode = ERR44;
-#elif defined COMPILE_PCRE16
- errorcode = ERR74;
-#elif defined COMPILE_PCRE32
- errorcode = ERR77;
-#endif
- goto PCRE_EARLY_ERROR_RETURN2;
- }
-#else
-if (utf)
+/* Can't support UTF or UCP unless PCRE2 has been compiled with UTF support. */
+
+#ifndef SUPPORT_UNICODE
+if ((cb.external_options & (PCRE2_UTF|PCRE2_UCP)) != 0)
{
errorcode = ERR32;
- goto PCRE_EARLY_ERROR_RETURN;
+ goto HAD_ERROR;
}
#endif
-/* Can't support UCP unless PCRE has been compiled to include the code. */
+/* Check UTF. We have the original options in 'options', with that value as
+modified by (*UTF) etc in cb->external_options. */
-#ifndef SUPPORT_UCP
-if ((options & PCRE_UCP) != 0)
+utf = (cb.external_options & PCRE2_UTF) != 0;
+if (utf)
{
- errorcode = ERR67;
- goto PCRE_EARLY_ERROR_RETURN;
+ if ((options & PCRE2_NEVER_UTF) != 0)
+ {
+ errorcode = ERR74;
+ goto HAD_ERROR;
+ }
+ if ((options & PCRE2_NO_UTF_CHECK) == 0 &&
+ (errorcode = PRIV(valid_utf)(pattern, patlen, erroroffset)) != 0)
+ goto HAD_UTF_ERROR;
}
-#endif
-/* Check validity of \R options. */
+/* Check UCP lockout. */
-if ((options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) ==
- (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE))
+if ((cb.external_options & (PCRE2_UCP|PCRE2_NEVER_UCP)) ==
+ (PCRE2_UCP|PCRE2_NEVER_UCP))
{
- errorcode = ERR56;
- goto PCRE_EARLY_ERROR_RETURN;
+ errorcode = ERR75;
+ goto HAD_ERROR;
}
-/* 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". */
+/* Process the BSR setting. */
-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 (bsr == 0) bsr = ccontext->bsr_convention;
-if (newline == -2)
- {
- cd->nltype = NLTYPE_ANYCRLF;
- }
-else if (newline < 0)
+/* Process the newline setting. */
+
+if (newline == 0) newline = ccontext->newline_convention;
+cb.nltype = NLTYPE_FIXED;
+switch(newline)
{
- cd->nltype = NLTYPE_ANY;
+ case PCRE2_NEWLINE_CR:
+ cb.nllen = 1;
+ cb.nl[0] = CHAR_CR;
+ break;
+
+ case PCRE2_NEWLINE_LF:
+ cb.nllen = 1;
+ cb.nl[0] = CHAR_NL;
+ break;
+
+ case PCRE2_NEWLINE_CRLF:
+ cb.nllen = 2;
+ cb.nl[0] = CHAR_CR;
+ cb.nl[1] = CHAR_NL;
+ break;
+
+ case PCRE2_NEWLINE_ANY:
+ cb.nltype = NLTYPE_ANY;
+ break;
+
+ case PCRE2_NEWLINE_ANYCRLF:
+ cb.nltype = NLTYPE_ANYCRLF;
+ break;
+
+ default:
+ errorcode = ERR56;
+ goto HAD_ERROR;
}
-else
+
+/* Before we do anything else, do a pre-scan of the pattern in order to
+discover the named groups and their numerical equivalents, so that this
+information is always available for the remaining processing. */
+
+errorcode = scan_for_captures(&ptr, cb.external_options, &cb);
+if (errorcode != 0) goto HAD_ERROR;
+
+/* For obscure debugging this code can be enabled. */
+
+#if 0
{
- cd->nltype = NLTYPE_FIXED;
- if (newline > 255)
- {
- cd->nllen = 2;
- cd->nl[0] = (newline >> 8) & 255;
- cd->nl[1] = newline & 255;
- }
- else
+ int i;
+ named_group *ng = cb.named_groups;
+ fprintf(stderr, "+++Captures: %d\n", cb.final_bracount);
+ for (i = 0; i < cb.names_found; i++, ng++)
{
- cd->nllen = 1;
- cd->nl[0] = newline;
+ fprintf(stderr, "+++%3d %.*s\n", ng->number, ng->length, ng->name);
}
}
+#endif
-/* 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.
-*/
+/* Reset current bracket count to zero and current pointer to the start of the
+pattern. */
-cd->top_backref = 0;
-cd->backref_map = 0;
+cb.bracount = 0;
+ptr = pattern + skipatstart;
-/* Reflect pattern for debugging output */
+/* Pretend to compile the pattern while actually just accumulating the amount
+of memory required in the 'length' variable. This behaviour is triggered by
+passing a non-NULL final argument to compile_regex(). We pass a block of
+workspace (cworkspace) for it to compile parts of the pattern into; the
+compiled code is discarded when it is no longer needed, so hopefully this
+workspace will never overflow, though there is a test for its doing so.
-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->dupnames = FALSE;
-cd->dupgroups = FALSE;
-cd->namedrefcount = 0;
-cd->start_code = cworkspace;
-cd->hwm = cworkspace;
-cd->iscondassert = FALSE;
-cd->start_workspace = cworkspace;
-cd->workspace_size = COMPILE_WORK_SIZE;
-cd->named_groups = named_groups;
-cd->named_group_list_size = NAMED_GROUP_LIST_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->parens_depth = 0;
-cd->assert_depth = 0;
-cd->max_lookbehind = 0;
-cd->external_options = options;
-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. */
+On error, errorcode will be set non-zero, so we don't need to look at the
+result of the function. The initial options have been put into the cb block 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. We still have to pass a separate options variable (the
+first argument) because that may change as the pattern is processed. */
-ptr += skipatstart;
code = cworkspace;
*code = OP_BRA;
-(void)compile_regex(cd->external_options, &code, &ptr, &errorcode, FALSE,
- FALSE, 0, 0, &firstchar, &firstcharflags, &reqchar, &reqcharflags, 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)));
+(void)compile_regex(cb.external_options, &code, &ptr, &errorcode, FALSE,
+ FALSE, 0, 0, &firstcu, &firstcuflags, &reqcu, &reqcuflags, NULL,
+ &cb, &length);
+if (errorcode != 0) goto HAD_ERROR;
if (length > MAX_PATTERN_SIZE)
{
errorcode = ERR20;
- goto PCRE_EARLY_ERROR_RETURN;
+ goto HAD_ERROR;
}
-/* Compute the size of the data block for storing the compiled pattern. 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);
-
-/* Get the memory. */
+/* Compute the size of, and then get and initialize, the data block for storing
+the compiled pattern and names table. Integer overflow should no longer be
+possible because nowadays we limit the maximum value of cb.names_found and
+cb.name_entry_size. */
-re = (REAL_PCRE *)(PUBL(malloc))(size);
+re_blocksize = sizeof(pcre2_real_code) +
+ CU2BYTES(length + cb.names_found * cb.name_entry_size);
+re = (pcre2_real_code *)
+ ccontext->memctl.malloc(re_blocksize, ccontext->memctl.memory_data);
if (re == NULL)
{
errorcode = ERR21;
- goto PCRE_EARLY_ERROR_RETURN;
+ goto HAD_ERROR;
}
-/* 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->memctl = ccontext->memctl;
+re->tables = tables;
+re->executable_jit = NULL;
+memset(re->start_bitmap, 0, 32 * sizeof(uint8_t));
+re->blocksize = re_blocksize;
re->magic_number = MAGIC_NUMBER;
-re->size = (int)size;
-re->options = cd->external_options;
-re->flags = cd->external_flags;
+re->compile_options = options;
+re->overall_options = cb.external_options;
+re->flags = PCRE2_CODE_UNIT_WIDTH/8 | cb.external_flags | setflags;
re->limit_match = limit_match;
re->limit_recursion = limit_recursion;
-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;
-#ifdef COMPILE_PCRE32
-re->dummy = 0;
-#else
-re->dummy1 = re->dummy2 = re->dummy3 = 0;
-#endif
-
-/* 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->parens_depth = 0;
-cd->assert_depth = 0;
-cd->bracount = 0;
-cd->max_lookbehind = 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->iscondassert = FALSE;
-cd->req_varyopt = 0;
-cd->had_accept = FALSE;
-cd->had_pruneorskip = FALSE;
-cd->check_lookbehind = FALSE;
-cd->open_caps = NULL;
+re->first_codeunit = 0;
+re->last_codeunit = 0;
+re->bsr_convention = bsr;
+re->newline_convention = newline;
+re->max_lookbehind = 0;
+re->minlength = 0;
+re->top_bracket = 0;
+re->top_backref = 0;
+re->name_entry_size = cb.name_entry_size;
+re->name_count = cb.names_found;
+
+/* The basic block is immediately followed by the name table, and the compiled
+code follows after that. */
+
+codestart = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code)) +
+ re->name_entry_size * re->name_count;
+
+/* Workspace is needed to remember information about numbered groups: whether a
+group can match an empty string and what its fixed length is. This is done to
+avoid the possibility of recursive references causing very long compile times
+when checking these features. Unnumbered groups do not have this exposure since
+they cannot be referenced. We use an indexed vector for this purpose. If there
+are sufficiently few groups, it can be the c32workspace vector, as set up
+above. Otherwise we have to get/free a special vector. The vector must be
+initialized to zero. */
+
+if (cb.final_bracount >= C32_WORK_SIZE)
+ {
+ cb.groupinfo = ccontext->memctl.malloc(
+ (cb.final_bracount + 1)*sizeof(uint32_t), ccontext->memctl.memory_data);
+ if (cb.groupinfo == NULL)
+ {
+ errorcode = ERR21;
+ goto HAD_ERROR;
+ }
+ }
+memset(cb.groupinfo, 0, (cb.final_bracount + 1) * sizeof(uint32_t));
+
+/* Update the compile data block for the actual compile. The starting points of
+the name/number translation table and of the code are passed around in the
+compile data block. The start/end pattern and initial options are already set
+from the pre-compile phase, as is the name_entry_size field. Reset the bracket
+count and the names_found field. */
+
+cb.parens_depth = 0;
+cb.assert_depth = 0;
+cb.bracount = 0;
+cb.max_lookbehind = 0;
+cb.name_table = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code));
+cb.start_code = codestart;
+cb.iscondassert = FALSE;
+cb.req_varyopt = 0;
+cb.had_accept = FALSE;
+cb.had_pruneorskip = FALSE;
+cb.check_lookbehind = FALSE;
+cb.open_caps = NULL;
/* If any named groups were found, create the name/number table from the list
-created in the first pass. */
+created in the pre-pass. */
-if (cd->names_found > 0)
+if (cb.names_found > 0)
{
- int i = cd->names_found;
- named_group *ng = cd->named_groups;
- cd->names_found = 0;
+ int i = cb.names_found;
+ named_group *ng = cb.named_groups;
+ cb.names_found = 0;
for (; i > 0; i--, ng++)
- add_name(cd, ng->name, ng->length, ng->number);
- if (cd->named_group_list_size > NAMED_GROUP_LIST_SIZE)
- (PUBL(free))((void *)cd->named_groups);
+ add_name_to_table(&cb, ng->name, ng->length, ng->number);
}
/* 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;
+ptr = pattern + skipatstart;
+code = (PCRE2_UCHAR *)codestart;
*code = OP_BRA;
-(void)compile_regex(re->options, &code, &ptr, &errorcode, FALSE, FALSE, 0, 0,
- &firstchar, &firstcharflags, &reqchar, &reqcharflags, NULL, cd, NULL);
-re->top_bracket = cd->bracount;
-re->top_backref = cd->top_backref;
-re->max_lookbehind = cd->max_lookbehind;
-re->flags = cd->external_flags | PCRE_MODE;
-
-if (cd->had_accept)
- {
- reqchar = 0; /* Must disable after (*ACCEPT) */
- reqcharflags = REQ_NONE;
- }
+(void)compile_regex(re->overall_options, &code, &ptr, &errorcode, FALSE, FALSE,
+ 0, 0, &firstcu, &firstcuflags, &reqcu, &reqcuflags, NULL, &cb, NULL);
-/* If not reached end of pattern on success, there's an excess bracket. */
+re->top_bracket = cb.bracount;
+re->top_backref = cb.top_backref;
+re->max_lookbehind = cb.max_lookbehind;
-if (errorcode == 0 && *ptr != CHAR_NULL) errorcode = ERR22;
+if (cb.had_accept)
+ {
+ reqcu = 0; /* Must disable after (*ACCEPT) */
+ reqcuflags = REQ_NONE;
+ }
-/* Fill in the terminating state and check for disastrous overflow, but
-if debugging, leave the test till after things are printed out. */
+/* Fill in the final opcode and check for disastrous overflow. If no overflow,
+but the estimated length exceeds the really used length, adjust the value of
+re->blocksize, and if valgrind support is configured, mark the extra allocated
+memory as unaddressable, so that any out-of-bound reads can be detected. */
*code++ = OP_END;
-
-#ifndef PCRE_DEBUG
-if (code - codestart > length) errorcode = ERR23;
-#endif
-
+usedlength = code - codestart;
+if (usedlength > length) errorcode = ERR23; else
+ {
+ re->blocksize -= CU2BYTES(length - usedlength);
#ifdef SUPPORT_VALGRIND
-/* If the estimated length exceeds the really used length, mark the extra
-allocated memory as unaddressable, so that any out-of-bound reads can be
-detected. */
-VALGRIND_MAKE_MEM_NOACCESS(code, (length - (code - codestart)) * sizeof(pcre_uchar));
+ VALGRIND_MAKE_MEM_NOACCESS(code, CU2BYTES(length - usedlength));
#endif
+ }
+
+/* Scan the pattern for recursion/subroutine calls and convert the group
+numbers into offsets. Maintain a small cache so that repeated groups containing
+recursions are efficiently handled. */
-/* Fill in any forward references that are required. There may be repeated
-references; optimize for them, as searching a large regex takes time. */
+#define RSCAN_CACHE_SIZE 8
-if (cd->hwm > cd->start_workspace)
+if (errorcode == 0 && cb.had_recurse)
{
- int prev_recno = -1;
- const pcre_uchar *groupptr = NULL;
- while (errorcode == 0 && cd->hwm > cd->start_workspace)
+ PCRE2_UCHAR *rcode;
+ PCRE2_SPTR rgroup;
+ int ccount = 0;
+ int start = RSCAN_CACHE_SIZE;
+ recurse_cache rc[RSCAN_CACHE_SIZE];
+
+ for (rcode = (PCRE2_UCHAR *)find_recurse(codestart, utf);
+ rcode != NULL;
+ rcode = (PCRE2_UCHAR *)find_recurse(rcode + 1 + LINK_SIZE, utf))
{
- int offset, recno;
- cd->hwm -= LINK_SIZE;
- offset = GET(cd->hwm, 0);
+ int i, p, recno;
- /* Check that the hwm handling hasn't gone wrong. This whole area is
- rewritten in PCRE2 because there are some obscure cases. */
-
- if (offset == 0 || codestart[offset-1] != OP_RECURSE)
+ recno = (int)GET(rcode, 1);
+ if (recno == 0) rgroup = codestart; else
{
- errorcode = ERR10;
- break;
- }
+ PCRE2_SPTR search_from = codestart;
+ rgroup = NULL;
+ for (i = 0, p = start; i < ccount; i++, p = (p + 1) & 7)
+ {
+ if (recno == rc[p].recno)
+ {
+ rgroup = rc[p].group;
+ break;
+ }
- recno = GET(codestart, offset);
- if (recno != prev_recno)
- {
- groupptr = PRIV(find_bracket)(codestart, utf, recno);
- prev_recno = recno;
+ /* Group n+1 must always start to the right of group n, so we can save
+ search time below when the new group number is greater than any of the
+ previously found groups. */
+
+ if (recno > rc[p].recno) search_from = rc[p].group;
+ }
+
+ if (rgroup == NULL)
+ {
+ rgroup = PRIV(find_bracket)(search_from, utf, recno);
+ if (rgroup == NULL)
+ {
+ errorcode = ERR53;
+ break;
+ }
+ if (--start < 0) start = RSCAN_CACHE_SIZE - 1;
+ rc[start].recno = recno;
+ rc[start].group = rgroup;
+ if (ccount < RSCAN_CACHE_SIZE) ccount++;
+ }
}
- if (groupptr == NULL) errorcode = ERR53;
- else PUT(((pcre_uchar *)codestart), offset, (int)(groupptr - codestart));
+
+ PUT(rcode, 1, rgroup - codestart);
}
}
-/* If the workspace had to be expanded, free the new memory. Set the pointer to
-NULL to indicate that forward references have been filled in. */
+/* In rare debugging situations we sometimes need to look at the compiled code
+at this stage. */
-if (cd->workspace_size > COMPILE_WORK_SIZE)
- (PUBL(free))((void *)cd->start_workspace);
-cd->start_workspace = NULL;
-
-/* 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;
+#ifdef CALL_PRINTINT
+pcre2_printint(re, stderr, TRUE);
+fprintf(stderr, "Length=%lu Used=%lu\n", length, usedlength);
+#endif
-/* Unless disabled, check whether any single character iterators can be
-auto-possessified. The function overwrites the appropriate opcode values, so
-the type of the pointer must be cast. NOTE: the intermediate variable "temp" is
-used in this code because at least one compiler gives a warning about loss of
-"const" attribute if the cast (pcre_uchar *)codestart is used directly in the
-function call. */
+/* After a successful compile, give an error if there's back reference to a
+non-existent capturing subpattern. Then, unless disabled, check whether any
+single character iterators can be auto-possessified. The function overwrites
+the appropriate opcode values, so the type of the pointer must be cast. NOTE:
+the intermediate variable "temp" is used in this code because at least one
+compiler gives a warning about loss of "const" attribute if the cast
+(PCRE2_UCHAR *)codestart is used directly in the function call. */
-if (errorcode == 0 && (options & PCRE_NO_AUTO_POSSESS) == 0)
+if (errorcode == 0)
{
- pcre_uchar *temp = (pcre_uchar *)codestart;
- auto_possessify(temp, utf, cd);
+ if (re->top_backref > re->top_bracket) errorcode = ERR15;
+ else if ((re->overall_options & PCRE2_NO_AUTO_POSSESS) == 0)
+ {
+ PCRE2_UCHAR *temp = (PCRE2_UCHAR *)codestart;
+ if (PRIV(auto_possessify)(temp, utf, &cb) != 0) errorcode = ERR80;
+ }
}
/* If there were any lookbehind assertions that contained OP_RECURSE
@@ -9534,216 +8888,194 @@ 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 (errorcode == 0 && cd->check_lookbehind)
+if (errorcode == 0 && cb.check_lookbehind)
{
- pcre_uchar *cc = (pcre_uchar *)codestart;
+ PCRE2_UCHAR *cc = (PCRE2_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. */
+ one, we temporarily terminate the branch it is in while we scan it. Note that
+ calling find_bracket() with a negative group number returns a pointer to the
+ OP_REVERSE item, not the actual lookbehind. */
- for (cc = (pcre_uchar *)PRIV(find_bracket)(codestart, utf, -1);
+ for (cc = (PCRE2_UCHAR *)PRIV(find_bracket)(codestart, utf, -1);
cc != NULL;
- cc = (pcre_uchar *)PRIV(find_bracket)(cc, utf, -1))
+ cc = (PCRE2_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 count = 0;
+ PCRE2_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, NULL);
+ fixed_length = find_fixedlength(cc, utf, TRUE, &cb, NULL, &count);
*be = end_op;
- DPRINTF(("fixed length = %d\n", fixed_length));
if (fixed_length < 0)
{
- errorcode = (fixed_length == -2)? ERR36 :
- (fixed_length == -4)? ERR70 : ERR25;
+ errorcode = fixed_length_errors[-fixed_length];
break;
}
- if (fixed_length > cd->max_lookbehind) cd->max_lookbehind = fixed_length;
+ if (fixed_length > cb.max_lookbehind) cb.max_lookbehind = fixed_length;
PUT(cc, 1, fixed_length);
}
cc += 1 + LINK_SIZE;
}
+
+ /* The previous value of the maximum lookbehind was transferred to the
+ compiled regex block above. We could have updated this value in the loop
+ above, but keep the two values in step, just in case some later code below
+ uses the cb value. */
+
+ re->max_lookbehind = cb.max_lookbehind;
}
-/* Failed to compile, or error while post-processing */
+/* Failed to compile, or error while post-processing. Earlier errors get here
+via the dreaded goto. */
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;
+ HAD_ERROR:
+ *erroroffset = (int)(ptr - pattern);
+ HAD_UTF_ERROR:
+ *errorptr = errorcode;
+ pcre2_code_free(re);
+ re = NULL;
+ goto EXIT;
}
-/* 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 non-atomic .* when DOTALL is set and there are no occurrences
-of *PRUNE or *SKIP.
+/* Successful compile. If the anchored option was not passed, set it if
+we can determine that the pattern is anchored by virtue of ^ characters or \A
+or anything else, such as starting with non-atomic .* when DOTALL is set and
+there are no occurrences of *PRUNE or *SKIP (though there is an option to
+disable this case). */
+
+if ((re->overall_options & PCRE2_ANCHORED) == 0 &&
+ is_anchored(codestart, 0, &cb, 0))
+ re->overall_options |= PCRE2_ANCHORED;
-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 non-atomic .* for
-non-DOTALL matches when *PRUNE and SKIP are not present. */
+/* If the pattern is still not anchored and we do not have a first code unit,
+see if there is one that is asserted (these are not saved during the compile
+because they can cause conflicts with actual literals that follow). This code
+need not be obeyed if PCRE2_NO_START_OPTIMIZE is set, as the data it would
+create will not be used. */
-if ((re->options & PCRE_ANCHORED) == 0)
+if ((re->overall_options & (PCRE2_ANCHORED|PCRE2_NO_START_OPTIMIZE)) == 0)
{
- if (is_anchored(codestart, 0, cd, 0)) re->options |= PCRE_ANCHORED;
- else
- {
- if (firstcharflags < 0)
- firstchar = find_firstassertedchar(codestart, &firstcharflags, FALSE);
- if (firstcharflags >= 0) /* Remove caseless flag for non-caseable chars */
- {
-#if defined COMPILE_PCRE8
- re->first_char = firstchar & 0xff;
-#elif defined COMPILE_PCRE16
- re->first_char = firstchar & 0xffff;
-#elif defined COMPILE_PCRE32
- re->first_char = firstchar;
-#endif
- if ((firstcharflags & 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;
- }
+ if (firstcuflags < 0)
+ firstcu = find_firstassertedcu(codestart, &firstcuflags, FALSE);
- re->flags |= PCRE_FIRSTSET;
- }
+ /* Save the data for a first code unit. */
- else if (is_startline(codestart, 0, cd, 0)) re->flags |= PCRE_STARTLINE;
- }
- }
+ if (firstcuflags >= 0)
+ {
+ re->first_codeunit = firstcu;
+ re->flags |= PCRE2_FIRSTSET;
-/* 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. */
+ /* Handle caseless first code units. */
-if (reqcharflags >= 0 &&
- ((re->options & PCRE_ANCHORED) == 0 || (reqcharflags & REQ_VARY) != 0))
- {
-#if defined COMPILE_PCRE8
- re->req_char = reqchar & 0xff;
-#elif defined COMPILE_PCRE16
- re->req_char = reqchar & 0xffff;
-#elif defined COMPILE_PCRE32
- re->req_char = reqchar;
-#endif
- if ((reqcharflags & REQ_CASELESS) != 0)
- {
-#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
- /* We ignore non-ASCII first chars in 8 bit mode. */
- if (utf)
+ if ((firstcuflags & REQ_CASELESS) != 0)
{
- if (re->req_char < 128)
+ if (firstcu < 128 || (!utf && firstcu < 255))
{
- if (cd->fcc[re->req_char] != re->req_char)
- re->flags |= PCRE_RCH_CASELESS;
+ if (cb.fcc[firstcu] != firstcu) re->flags |= PCRE2_FIRSTCASELESS;
}
- else if (UCD_OTHERCASE(re->req_char) != re->req_char)
- re->flags |= PCRE_RCH_CASELESS;
- }
- else
+
+ /* The first code unit is > 128 in UTF mode, or > 255 otherwise. In
+ 8-bit UTF mode, codepoints in the range 128-255 are introductory code
+ points and cannot have another case. In 16-bit and 32-bit modes, we can
+ check wide characters when UTF (and therefore UCP) is supported. */
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
+ else if (firstcu <= MAX_UTF_CODE_POINT &&
+ UCD_OTHERCASE(firstcu) != firstcu)
+ re->flags |= PCRE2_FIRSTCASELESS;
#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. */
+ /* When there is no first code unit, see if we can set the PCRE2_STARTLINE
+ flag. This is helpful for multiline matches when all branches start with ^
+ and also when all branches start with non-atomic .* for non-DOTALL matches
+ when *PRUNE and SKIP are not present. (There is an option that disables this
+ case.) */
-#ifdef PCRE_DEBUG
-printf("Length = %d top_bracket = %d top_backref = %d\n",
- length, re->top_bracket, re->top_backref);
+ else if (is_startline(codestart, 0, &cb, 0)) re->flags |= PCRE2_STARTLINE;
+ }
-printf("Options=%08x\n", re->options);
+/* Handle the "required code unit", if one is set. In the case of an anchored
+pattern, do this only if it follows a variable length item in the pattern.
+Again, skip this if PCRE2_NO_START_OPTIMIZE is set. */
-if ((re->flags & PCRE_FIRSTSET) != 0)
+if (reqcuflags >= 0 &&
+ ((re->overall_options & (PCRE2_ANCHORED|PCRE2_NO_START_OPTIMIZE)) == 0 ||
+ (reqcuflags & REQ_VARY) != 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);
- }
+ re->last_codeunit = reqcu;
+ re->flags |= PCRE2_LASTSET;
-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);
- }
+ /* Handle caseless required code units as for first code units (above). */
-#if defined COMPILE_PCRE8
-pcre_printint((pcre *)re, stdout, TRUE);
-#elif defined COMPILE_PCRE16
-pcre16_printint((pcre *)re, stdout, TRUE);
-#elif defined COMPILE_PCRE32
-pcre32_printint((pcre *)re, stdout, TRUE);
+ if ((reqcuflags & REQ_CASELESS) != 0)
+ {
+ if (reqcu < 128 || (!utf && reqcu < 255))
+ {
+ if (cb.fcc[reqcu] != reqcu) re->flags |= PCRE2_LASTCASELESS;
+ }
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
+ else if (reqcu <= MAX_UTF_CODE_POINT && UCD_OTHERCASE(reqcu) != reqcu)
+ re->flags |= PCRE2_LASTCASELESS;
#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 */
/* Check for a pattern than can match an empty string, so that this information
can be provided to applications. */
do
{
- if (could_be_empty_branch(codestart, code, utf, cd, NULL))
+ int count = 0;
+ int rc = could_be_empty_branch(codestart, code, utf, &cb, TRUE, NULL, &count);
+ if (rc < 0)
+ {
+ errorcode = ERR86;
+ goto HAD_ERROR;
+ }
+ if (rc > 0)
{
- re->flags |= PCRE_MATCH_EMPTY;
+ re->flags |= PCRE2_MATCH_EMPTY;
break;
}
codestart += GET(codestart, 1);
}
while (*codestart == OP_ALT);
-#if defined COMPILE_PCRE8
-return (pcre *)re;
-#elif defined COMPILE_PCRE16
-return (pcre16 *)re;
-#elif defined COMPILE_PCRE32
-return (pcre32 *)re;
-#endif
+/* Finally, unless PCRE2_NO_START_OPTIMIZE is set, study the compiled pattern
+to set up information such as a bitmap of starting code units and a minimum
+matching length. */
+
+if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 &&
+ PRIV(study)(re) != 0)
+ {
+ errorcode = ERR31;
+ goto HAD_ERROR;
+ }
+
+/* Control ends up here in all cases. If memory was obtained for a
+zero-terminated copy of the pattern, remember to free it before returning. Also
+free the list of named groups if a larger one had to be obtained, and likewise
+the group information vector. */
+
+EXIT:
+if (copied_pattern != stack_copied_pattern)
+ ccontext->memctl.free(copied_pattern, ccontext->memctl.memory_data);
+if (cb.named_group_list_size > NAMED_GROUP_LIST_SIZE)
+ ccontext->memctl.free((void *)cb.named_groups, ccontext->memctl.memory_data);
+if (cb.groupinfo != c32workspace)
+ ccontext->memctl.free((void *)cb.groupinfo, ccontext->memctl.memory_data);
+
+return re; /* Will be NULL after an error */
}
-/* End of pcre_compile.c */
+/* End of pcre2_compile.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_config.c b/src/3rdparty/pcre2/src/pcre2_config.c
new file mode 100644
index 0000000000..e99272f577
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_config.c
@@ -0,0 +1,218 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Save the configured link size, which is in bytes. In 16-bit and 32-bit modes
+its value gets changed by pcre2_internal.h to be in code units. */
+
+static int configured_link_size = LINK_SIZE;
+
+#include "pcre2_internal.h"
+
+/* These macros are the standard way of turning unquoted text into C strings.
+They allow macros like PCRE2_MAJOR to be defined without quotes, which is
+convenient for user programs that want to test their values. */
+
+#define STRING(a) # a
+#define XSTRING(s) STRING(s)
+
+
+/*************************************************
+* Return info about what features are configured *
+*************************************************/
+
+/* If where is NULL, the length of memory required is returned.
+
+Arguments:
+ what what information is required
+ where where to put the information
+
+Returns: 0 if a numerical value is returned
+ >= 0 if a string value
+ PCRE2_ERROR_BADOPTION if "where" not recognized
+ or JIT target requested when JIT not enabled
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_config(uint32_t what, void *where)
+{
+if (where == NULL) /* Requests a length */
+ {
+ switch(what)
+ {
+ default:
+ return PCRE2_ERROR_BADOPTION;
+
+ case PCRE2_CONFIG_BSR:
+ case PCRE2_CONFIG_JIT:
+ case PCRE2_CONFIG_LINKSIZE:
+ case PCRE2_CONFIG_MATCHLIMIT:
+ case PCRE2_CONFIG_NEWLINE:
+ case PCRE2_CONFIG_PARENSLIMIT:
+ case PCRE2_CONFIG_RECURSIONLIMIT:
+ case PCRE2_CONFIG_STACKRECURSE:
+ case PCRE2_CONFIG_UNICODE:
+ return sizeof(uint32_t);
+
+ /* These are handled below */
+
+ case PCRE2_CONFIG_JITTARGET:
+ case PCRE2_CONFIG_UNICODE_VERSION:
+ case PCRE2_CONFIG_VERSION:
+ break;
+ }
+ }
+
+switch (what)
+ {
+ default:
+ return PCRE2_ERROR_BADOPTION;
+
+ case PCRE2_CONFIG_BSR:
+#ifdef BSR_ANYCRLF
+ *((uint32_t *)where) = PCRE2_BSR_ANYCRLF;
+#else
+ *((uint32_t *)where) = PCRE2_BSR_UNICODE;
+#endif
+ break;
+
+ case PCRE2_CONFIG_JIT:
+#ifdef SUPPORT_JIT
+ *((uint32_t *)where) = 1;
+#else
+ *((uint32_t *)where) = 0;
+#endif
+ break;
+
+ case PCRE2_CONFIG_JITTARGET:
+#ifdef SUPPORT_JIT
+ {
+ const char *v = PRIV(jit_get_target)();
+ return (int)(1 + ((where == NULL)?
+ strlen(v) : PRIV(strcpy_c8)((PCRE2_UCHAR *)where, v)));
+ }
+#else
+ return PCRE2_ERROR_BADOPTION;
+#endif
+
+ case PCRE2_CONFIG_LINKSIZE:
+ *((uint32_t *)where) = (uint32_t)configured_link_size;
+ break;
+
+ case PCRE2_CONFIG_MATCHLIMIT:
+ *((uint32_t *)where) = MATCH_LIMIT;
+ break;
+
+ case PCRE2_CONFIG_NEWLINE:
+ *((uint32_t *)where) = NEWLINE_DEFAULT;
+ break;
+
+ case PCRE2_CONFIG_PARENSLIMIT:
+ *((uint32_t *)where) = PARENS_NEST_LIMIT;
+ break;
+
+ case PCRE2_CONFIG_RECURSIONLIMIT:
+ *((uint32_t *)where) = MATCH_LIMIT_RECURSION;
+ break;
+
+ case PCRE2_CONFIG_STACKRECURSE:
+#ifdef HEAP_MATCH_RECURSE
+ *((uint32_t *)where) = 0;
+#else
+ *((uint32_t *)where) = 1;
+#endif
+ break;
+
+ case PCRE2_CONFIG_UNICODE_VERSION:
+ {
+#if defined SUPPORT_UNICODE
+ const char *v = PRIV(unicode_version);
+#else
+ const char *v = "Unicode not supported";
+#endif
+ return (int)(1 + ((where == NULL)?
+ strlen(v) : PRIV(strcpy_c8)((PCRE2_UCHAR *)where, v)));
+ }
+ break;
+
+ case PCRE2_CONFIG_UNICODE:
+#if defined SUPPORT_UNICODE
+ *((uint32_t *)where) = 1;
+#else
+ *((uint32_t *)where) = 0;
+#endif
+ break;
+
+ /* The hackery in setting "v" below is to cope with the case when
+ PCRE2_PRERELEASE is set to an empty string (which it is for real releases).
+ If the second alternative is used in this case, it does not leave a space
+ before the date. On the other hand, if all four macros are put into a single
+ XSTRING when PCRE2_PRERELEASE is not empty, an unwanted space is inserted.
+ There are problems using an "obvious" approach like this:
+
+ XSTRING(PCRE2_MAJOR) "." XSTRING(PCRE_MINOR)
+ XSTRING(PCRE2_PRERELEASE) " " XSTRING(PCRE_DATE)
+
+ because, when PCRE2_PRERELEASE is empty, this leads to an attempted expansion
+ of STRING(). The C standard states: "If (before argument substitution) any
+ argument consists of no preprocessing tokens, the behavior is undefined." It
+ turns out the gcc treats this case as a single empty string - which is what
+ we really want - but Visual C grumbles about the lack of an argument for the
+ macro. Unfortunately, both are within their rights. As there seems to be no
+ way to test for a macro's value being empty at compile time, we have to
+ resort to a runtime test. */
+
+ case PCRE2_CONFIG_VERSION:
+ {
+ const char *v = (XSTRING(Z PCRE2_PRERELEASE)[1] == 0)?
+ XSTRING(PCRE2_MAJOR.PCRE2_MINOR PCRE2_DATE) :
+ XSTRING(PCRE2_MAJOR.PCRE2_MINOR) XSTRING(PCRE2_PRERELEASE PCRE2_DATE);
+ return (int)(1 + ((where == NULL)?
+ strlen(v) : PRIV(strcpy_c8)((PCRE2_UCHAR *)where, v)));
+ }
+ }
+
+return 0;
+}
+
+/* End of pcre2_config.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_context.c b/src/3rdparty/pcre2/src/pcre2_context.c
new file mode 100644
index 0000000000..ae050fe92c
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_context.c
@@ -0,0 +1,391 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre2_internal.h"
+
+
+
+/*************************************************
+* Default malloc/free functions *
+*************************************************/
+
+/* Ignore the "user data" argument in each case. */
+
+static void *default_malloc(size_t size, void *data)
+{
+(void)data;
+return malloc(size);
+}
+
+
+static void default_free(void *block, void *data)
+{
+(void)data;
+free(block);
+}
+
+
+
+/*************************************************
+* Get a block and save memory control *
+*************************************************/
+
+/* This internal function is called to get a block of memory in which the
+memory control data is to be stored at the start for future use.
+
+Arguments:
+ size amount of memory required
+ memctl pointer to a memctl block or NULL
+
+Returns: pointer to memory or NULL on failure
+*/
+
+extern void *
+PRIV(memctl_malloc)(size_t size, pcre2_memctl *memctl)
+{
+pcre2_memctl *newmemctl;
+void *yield = (memctl == NULL)? malloc(size) :
+ memctl->malloc(size, memctl->memory_data);
+if (yield == NULL) return NULL;
+newmemctl = (pcre2_memctl *)yield;
+if (memctl == NULL)
+ {
+ newmemctl->malloc = default_malloc;
+ newmemctl->free = default_free;
+ newmemctl->memory_data = NULL;
+ }
+else *newmemctl = *memctl;
+return yield;
+}
+
+
+
+/*************************************************
+* Create and initialize contexts *
+*************************************************/
+
+/* Initializing for compile and match contexts is done in separate, private
+functions so that these can be called from functions such as pcre2_compile()
+when an external context is not supplied. The initializing functions have an
+option to set up default memory management. */
+
+PCRE2_EXP_DEFN pcre2_general_context * PCRE2_CALL_CONVENTION
+pcre2_general_context_create(void *(*private_malloc)(size_t, void *),
+ void (*private_free)(void *, void *), void *memory_data)
+{
+pcre2_general_context *gcontext;
+if (private_malloc == NULL) private_malloc = default_malloc;
+if (private_free == NULL) private_free = default_free;
+gcontext = private_malloc(sizeof(pcre2_real_general_context), memory_data);
+if (gcontext == NULL) return NULL;
+gcontext->memctl.malloc = private_malloc;
+gcontext->memctl.free = private_free;
+gcontext->memctl.memory_data = memory_data;
+return gcontext;
+}
+
+
+/* A default compile context is set up to save having to initialize at run time
+when no context is supplied to the compile function. */
+
+const pcre2_compile_context PRIV(default_compile_context) = {
+ { default_malloc, default_free, NULL }, /* Default memory handling */
+ NULL, /* Stack guard */
+ NULL, /* Stack guard data */
+ PRIV(default_tables), /* Character tables */
+ PCRE2_UNSET, /* Max pattern length */
+ BSR_DEFAULT, /* Backslash R default */
+ NEWLINE_DEFAULT, /* Newline convention */
+ PARENS_NEST_LIMIT }; /* As it says */
+
+/* The create function copies the default into the new memory, but must
+override the default memory handling functions if a gcontext was provided. */
+
+PCRE2_EXP_DEFN pcre2_compile_context * PCRE2_CALL_CONVENTION
+pcre2_compile_context_create(pcre2_general_context *gcontext)
+{
+pcre2_compile_context *ccontext = PRIV(memctl_malloc)(
+ sizeof(pcre2_real_compile_context), (pcre2_memctl *)gcontext);
+if (ccontext == NULL) return NULL;
+*ccontext = PRIV(default_compile_context);
+if (gcontext != NULL)
+ *((pcre2_memctl *)ccontext) = *((pcre2_memctl *)gcontext);
+return ccontext;
+}
+
+
+/* A default match context is set up to save having to initialize at run time
+when no context is supplied to a match function. */
+
+const pcre2_match_context PRIV(default_match_context) = {
+ { default_malloc, default_free, NULL },
+#ifdef HEAP_MATCH_RECURSE
+ { default_malloc, default_free, NULL },
+#endif
+#ifdef SUPPORT_JIT
+ NULL,
+ NULL,
+#endif
+ NULL,
+ NULL,
+ PCRE2_UNSET, /* Offset limit */
+ MATCH_LIMIT,
+ MATCH_LIMIT_RECURSION };
+
+/* The create function copies the default into the new memory, but must
+override the default memory handling functions if a gcontext was provided. */
+
+PCRE2_EXP_DEFN pcre2_match_context * PCRE2_CALL_CONVENTION
+pcre2_match_context_create(pcre2_general_context *gcontext)
+{
+pcre2_match_context *mcontext = PRIV(memctl_malloc)(
+ sizeof(pcre2_real_match_context), (pcre2_memctl *)gcontext);
+if (mcontext == NULL) return NULL;
+*mcontext = PRIV(default_match_context);
+if (gcontext != NULL)
+ *((pcre2_memctl *)mcontext) = *((pcre2_memctl *)gcontext);
+return mcontext;
+}
+
+
+/*************************************************
+* Context copy functions *
+*************************************************/
+
+PCRE2_EXP_DEFN pcre2_general_context * PCRE2_CALL_CONVENTION
+pcre2_general_context_copy(pcre2_general_context *gcontext)
+{
+pcre2_general_context *new =
+ gcontext->memctl.malloc(sizeof(pcre2_real_general_context),
+ gcontext->memctl.memory_data);
+if (new == NULL) return NULL;
+memcpy(new, gcontext, sizeof(pcre2_real_general_context));
+return new;
+}
+
+
+PCRE2_EXP_DEFN pcre2_compile_context * PCRE2_CALL_CONVENTION
+pcre2_compile_context_copy(pcre2_compile_context *ccontext)
+{
+pcre2_compile_context *new =
+ ccontext->memctl.malloc(sizeof(pcre2_real_compile_context),
+ ccontext->memctl.memory_data);
+if (new == NULL) return NULL;
+memcpy(new, ccontext, sizeof(pcre2_real_compile_context));
+return new;
+}
+
+
+PCRE2_EXP_DEFN pcre2_match_context * PCRE2_CALL_CONVENTION
+pcre2_match_context_copy(pcre2_match_context *mcontext)
+{
+pcre2_match_context *new =
+ mcontext->memctl.malloc(sizeof(pcre2_real_match_context),
+ mcontext->memctl.memory_data);
+if (new == NULL) return NULL;
+memcpy(new, mcontext, sizeof(pcre2_real_match_context));
+return new;
+}
+
+
+
+/*************************************************
+* Context free functions *
+*************************************************/
+
+
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_general_context_free(pcre2_general_context *gcontext)
+{
+if (gcontext != NULL)
+ gcontext->memctl.free(gcontext, gcontext->memctl.memory_data);
+}
+
+
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_compile_context_free(pcre2_compile_context *ccontext)
+{
+if (ccontext != NULL)
+ ccontext->memctl.free(ccontext, ccontext->memctl.memory_data);
+}
+
+
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_match_context_free(pcre2_match_context *mcontext)
+{
+if (mcontext != NULL)
+ mcontext->memctl.free(mcontext, mcontext->memctl.memory_data);
+}
+
+
+
+
+/*************************************************
+* Set values in contexts *
+*************************************************/
+
+/* All these functions return 0 for success or PCRE2_ERROR_BADDATA if invalid
+data is given. Only some of the functions are able to test the validity of the
+data. */
+
+
+/* ------------ Compile contexts ------------ */
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_set_character_tables(pcre2_compile_context *ccontext,
+ const unsigned char *tables)
+{
+ccontext->tables = tables;
+return 0;
+}
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_set_bsr(pcre2_compile_context *ccontext, uint32_t value)
+{
+switch(value)
+ {
+ case PCRE2_BSR_ANYCRLF:
+ case PCRE2_BSR_UNICODE:
+ ccontext->bsr_convention = value;
+ return 0;
+
+ default:
+ return PCRE2_ERROR_BADDATA;
+ }
+}
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_set_max_pattern_length(pcre2_compile_context *ccontext, PCRE2_SIZE length)
+{
+ccontext->max_pattern_length = length;
+return 0;
+}
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_set_newline(pcre2_compile_context *ccontext, uint32_t newline)
+{
+switch(newline)
+ {
+ case PCRE2_NEWLINE_CR:
+ case PCRE2_NEWLINE_LF:
+ case PCRE2_NEWLINE_CRLF:
+ case PCRE2_NEWLINE_ANY:
+ case PCRE2_NEWLINE_ANYCRLF:
+ ccontext->newline_convention = newline;
+ return 0;
+
+ default:
+ return PCRE2_ERROR_BADDATA;
+ }
+}
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_set_parens_nest_limit(pcre2_compile_context *ccontext, uint32_t limit)
+{
+ccontext->parens_nest_limit = limit;
+return 0;
+}
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_set_compile_recursion_guard(pcre2_compile_context *ccontext,
+ int (*guard)(uint32_t, void *), void *user_data)
+{
+ccontext->stack_guard = guard;
+ccontext->stack_guard_data = user_data;
+return 0;
+}
+
+
+/* ------------ Match contexts ------------ */
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_set_callout(pcre2_match_context *mcontext,
+ int (*callout)(pcre2_callout_block *, void *), void *callout_data)
+{
+mcontext->callout = callout;
+mcontext->callout_data = callout_data;
+return 0;
+}
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_set_match_limit(pcre2_match_context *mcontext, uint32_t limit)
+{
+mcontext->match_limit = limit;
+return 0;
+}
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_set_offset_limit(pcre2_match_context *mcontext, PCRE2_SIZE limit)
+{
+mcontext->offset_limit = limit;
+return 0;
+}
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_set_recursion_limit(pcre2_match_context *mcontext, uint32_t limit)
+{
+mcontext->recursion_limit = limit;
+return 0;
+}
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_set_recursion_memory_management(pcre2_match_context *mcontext,
+ void *(*mymalloc)(size_t, void *), void (*myfree)(void *, void *),
+ void *mydata)
+{
+#ifdef HEAP_MATCH_RECURSE
+mcontext->stack_memctl.malloc = mymalloc;
+mcontext->stack_memctl.free = myfree;
+mcontext->stack_memctl.memory_data = mydata;
+#else
+(void)mcontext;
+(void)mymalloc;
+(void)myfree;
+(void)mydata;
+#endif
+return 0;
+}
+
+/* End of pcre2_context.c */
diff --git a/src/3rdparty/pcre/pcre_dfa_exec.c b/src/3rdparty/pcre2/src/pcre2_dfa_match.c
index 170ce6a001..12b31b1b36 100644
--- a/src/3rdparty/pcre/pcre_dfa_exec.c
+++ b/src/3rdparty/pcre2/src/pcre2_dfa_match.c
@@ -3,11 +3,11 @@
*************************************************/
/* 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).
+and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2014 University of Cambridge
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,8 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
-/* This module contains the external function pcre_dfa_exec(), which is an
+
+/* This module contains the external function pcre2_dfa_match(), which is an
alternative matching function that uses a sort of DFA algorithm (not a true
FSM). This is NOT Perl-compatible, but it has advantages in certain
applications. */
@@ -64,28 +65,27 @@ 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
+of internal_dfa_match(). (The supplied patch used a static vector, initialized
only once - I suspect this was the cause of the problems with the tests.)
Overall, I concluded that the gains in some cases did not outweigh the losses
in others, so I abandoned this code. */
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#define NLBLOCK md /* Block containing newline information */
+#define NLBLOCK mb /* Block containing newline information */
#define PSSTART start_subject /* Field containing processed string start */
#define PSEND end_subject /* Field containing processed string end */
-#include "pcre_internal.h"
-
+#include "pcre2_internal.h"
-/* For use to indent debugging output */
-
-#define SP " "
+#define PUBLIC_DFA_MATCH_OPTIONS \
+ (PCRE2_ANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \
+ PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK|PCRE2_PARTIAL_HARD| \
+ PCRE2_PARTIAL_SOFT|PCRE2_DFA_SHORTEST|PCRE2_DFA_RESTART)
/*************************************************
@@ -112,7 +112,7 @@ 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[] = {
+static const uint8_t coptable[] = {
0, /* End */
0, 0, 0, 0, 0, /* \A, \G, \K, \B, \b */
0, 0, 0, 0, 0, 0, /* \D, \d, \S, \s, \W, \w */
@@ -161,6 +161,7 @@ static const pcre_uint8 coptable[] = {
0, /* DNREFI */
0, /* RECURSE */
0, /* CALLOUT */
+ 0, /* CALLOUT_STR */
0, /* Alt */
0, /* Ket */
0, /* KetRmax */
@@ -176,12 +177,12 @@ static const pcre_uint8 coptable[] = {
0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */
0, 0, /* CREF, DNCREF */
0, 0, /* RREF, DNRREF */
- 0, /* DEF */
+ 0, 0, /* FALSE, TRUE */
0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */
0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */
0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */
0, 0, 0, 0, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */
- 0, 0 /* CLOSE, SKIPZERO */
+ 0, 0, 0 /* CLOSE, SKIPZERO, DEFINE */
};
/* This table identifies those opcodes that inspect a character. It is used to
@@ -189,7 +190,7 @@ 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[] = {
+static const uint8_t poptable[] = {
0, /* End */
0, 0, 0, 1, 1, /* \A, \G, \K, \B, \b */
1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */
@@ -233,6 +234,7 @@ static const pcre_uint8 poptable[] = {
0, /* DNREFI */
0, /* RECURSE */
0, /* CALLOUT */
+ 0, /* CALLOUT_STR */
0, /* Alt */
0, /* Ket */
0, /* KetRmax */
@@ -248,18 +250,18 @@ static const pcre_uint8 poptable[] = {
0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */
0, 0, /* CREF, DNCREF */
0, 0, /* RREF, DNRREF */
- 0, /* DEF */
+ 0, 0, /* FALSE, TRUE */
0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */
0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */
0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */
0, 0, 0, 0, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */
- 0, 0 /* CLOSE, SKIPZERO */
+ 0, 0, 0 /* CLOSE, SKIPZERO, DEFINE */
};
/* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,
and \w */
-static const pcre_uint8 toptable1[] = {
+static const uint8_t toptable1[] = {
0, 0, 0, 0, 0, 0,
ctype_digit, ctype_digit,
ctype_space, ctype_space,
@@ -267,7 +269,7 @@ static const pcre_uint8 toptable1[] = {
0, 0 /* OP_ANY, OP_ALLANY */
};
-static const pcre_uint8 toptable2[] = {
+static const uint8_t toptable2[] = {
0, 0, 0, 0, 0, 0,
ctype_digit, 0,
ctype_space, 0,
@@ -282,7 +284,7 @@ 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 offset; /* Offset to opcode (-ve has meaning) */
int count; /* Count for repeats */
int data; /* Some use extra data */
} stateblock;
@@ -290,39 +292,9 @@ typedef struct stateblock {
#define INTS_PER_STATEBLOCK (int)(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)
-{
-pcre_uint32 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 *
+* Match a Regular Expression - DFA engine *
*************************************************/
/* This internal function applies a compiled pattern to a subject string,
@@ -331,7 +303,7 @@ 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
+ mb the match_data block with fixed information
this_start_code the opening bracket of this subexpression's code
current_subject where we currently are in the subject string
start_offset start offset in the subject string
@@ -355,9 +327,8 @@ for the current character, one for the following character). */
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
+ else return PCRE2_ERROR_DFA_WSSIZE
#define ADD_ACTIVE_DATA(x,y,z) \
if (active_count++ < wscount) \
@@ -366,9 +337,8 @@ for the current character, one for the following character). */
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
+ else return PCRE2_ERROR_DFA_WSSIZE
#define ADD_NEW(x,y) \
if (new_count++ < wscount) \
@@ -376,9 +346,8 @@ for the current character, one for the following character). */
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
+ else return PCRE2_ERROR_DFA_WSSIZE
#define ADD_NEW_DATA(x,y,z) \
if (new_count++ < wscount) \
@@ -387,21 +356,19 @@ for the current character, one for the following character). */
next_new_state->count = (y); \
next_new_state->data = (z); \
next_new_state++; \
- DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d) line %d\n", rlevel*2-2, SP, \
- (x), (y), (z), __LINE__)); \
} \
- else return PCRE_ERROR_DFA_WSSIZE
+ else return PCRE2_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,
+internal_dfa_match(
+ dfa_match_block *mb,
+ PCRE2_SPTR this_start_code,
+ PCRE2_SPTR current_subject,
+ PCRE2_SIZE start_offset,
+ PCRE2_SIZE *offsets,
+ uint32_t offsetcount,
int *workspace,
int wscount,
int rlevel)
@@ -409,23 +376,24 @@ internal_dfa_exec(
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;
+const uint8_t *ctypes, *lcc, *fcc;
+PCRE2_SPTR ptr;
+PCRE2_SPTR end_code;
+PCRE2_SPTR 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
+/* Some fields in the mb 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;
+PCRE2_SPTR start_subject = mb->start_subject;
+PCRE2_SPTR end_subject = mb->end_subject;
+PCRE2_SPTR start_code = mb->start_code;
-#ifdef SUPPORT_UTF
-BOOL utf = (md->poptions & PCRE_UTF8) != 0;
+#ifdef SUPPORT_UNICODE
+BOOL utf = (mb->poptions & PCRE2_UTF) != 0;
#else
BOOL utf = FALSE;
#endif
@@ -433,21 +401,17 @@ BOOL utf = FALSE;
BOOL reset_could_continue = FALSE;
rlevel++;
-offsetcount &= (-2);
+offsetcount &= (uint32_t)(-2); /* Round down */
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 = mb->tables + ctypes_offset;
+lcc = mb->tables + lcc_offset;
+fcc = mb->tables + fcc_offset;
-ctypes = md->tables + ctypes_offset;
-lcc = md->tables + lcc_offset;
-fcc = md->tables + fcc_offset;
-
-match_count = PCRE_ERROR_NOMATCH; /* A negative number */
+match_count = PCRE2_ERROR_NOMATCH; /* A negative number */
active_states = (stateblock *)(workspace + 2);
next_new_state = new_states = active_states + wscount;
@@ -469,13 +433,13 @@ move back, and set up each alternative appropriately. */
if (*first_op == OP_REVERSE)
{
- int max_back = 0;
- int gone_back;
+ size_t max_back = 0;
+ size_t gone_back;
end_code = this_start_code;
do
{
- int back = GET(end_code, 2+LINK_SIZE);
+ size_t back = (size_t)GET(end_code, 2+LINK_SIZE);
if (back > max_back) max_back = back;
end_code += GET(end_code, 1);
}
@@ -484,7 +448,7 @@ if (*first_op == OP_REVERSE)
/* 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
+#ifdef SUPPORT_UNICODE
/* In character mode we have to step back character by character */
if (utf)
@@ -502,26 +466,26 @@ if (*first_op == OP_REVERSE)
/* In byte-mode we can do this quickly. */
{
- gone_back = (current_subject - max_back < start_subject)?
- (int)(current_subject - start_subject) : max_back;
+ size_t current_offset = (size_t)(current_subject - start_subject);
+ gone_back = (current_offset < max_back)? current_offset : max_back;
current_subject -= gone_back;
}
/* Save the earliest consulted character */
- if (current_subject < md->start_used_ptr)
- md->start_used_ptr = current_subject;
+ if (current_subject < mb->start_used_ptr)
+ mb->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);
+ size_t back = (size_t)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);
+ ADD_NEW_DATA(-bstate, 0, (int)(gone_back - back));
}
end_code += GET(end_code, 1);
}
@@ -540,12 +504,12 @@ else
/* Restarting */
- if (rlevel == 1 && (md->moptions & PCRE_DFA_RESTART) != 0)
+ if (rlevel == 1 && (mb->moptions & PCRE2_DFA_RESTART) != 0)
{
do { end_code += GET(end_code, 1); } while (*end_code == OP_ALT);
new_count = workspace[1];
if (!workspace[0])
- memcpy(new_states, active_states, new_count * sizeof(stateblock));
+ memcpy(new_states, active_states, (size_t)new_count * sizeof(stateblock));
}
/* Not restarting */
@@ -568,8 +532,6 @@ else
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;
@@ -577,12 +539,14 @@ for (;;)
{
int i, j;
int clen, dlen;
- pcre_uint32 c, d;
+ uint32_t c, d;
int forced_fail = 0;
BOOL partial_newline = FALSE;
BOOL could_continue = reset_could_continue;
reset_could_continue = FALSE;
+ if (ptr > mb->last_used_ptr) mb->last_used_ptr = ptr;
+
/* Make the new state list into the active state list and empty the
new state list. */
@@ -595,17 +559,6 @@ for (;;)
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;
@@ -618,11 +571,11 @@ for (;;)
if (ptr < end_subject)
{
clen = 1; /* Number of data items in the character */
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
GETCHARLENTEST(c, ptr, clen);
#else
c = *ptr;
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
}
else
{
@@ -639,18 +592,12 @@ for (;;)
{
stateblock *current_state = active_states + i;
BOOL caseless = FALSE;
- const pcre_uchar *code;
+ PCRE2_SPTR code;
+ uint32_t codevalue;
int state_offset = current_state->offset;
- int codevalue, rrc;
+ int rrc;
int count;
-#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 the could_continue flag was passed over from a previous
@@ -660,7 +607,6 @@ for (;;)
{
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);
if (could_continue) reset_could_continue = TRUE;
@@ -680,10 +626,7 @@ for (;;)
{
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 */
@@ -711,15 +654,15 @@ for (;;)
if (coptable[codevalue] > 0)
{
dlen = 1;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
d = code[coptable[codevalue]];
if (codevalue >= OP_TYPESTAR)
{
switch(d)
{
- case OP_ANYBYTE: return PCRE_ERROR_DFA_UITEM;
+ case OP_ANYBYTE: return PCRE2_ERROR_DFA_UITEM;
case OP_NOTPROP:
case OP_PROP: codevalue += OP_PROP_EXTRA; break;
case OP_ANYNL: codevalue += OP_ANYNL_EXTRA; break;
@@ -764,7 +707,7 @@ for (;;)
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
+ PCRE2_NOTEMPTY is set, or PCRE2_NOTEMPTY_ATSTART is set and we are at the
start of the subject, save the match data, shifting up all previous
matches so we always have the longest first. */
@@ -777,35 +720,28 @@ for (;;)
ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0);
if (codevalue != OP_KET)
{
- ADD_ACTIVE(state_offset - GET(code, 1), 0);
+ ADD_ACTIVE(state_offset - (int)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)))
+ ((mb->moptions & PCRE2_NOTEMPTY) == 0 &&
+ ((mb->moptions & PCRE2_NOTEMPTY_ATSTART) == 0 ||
+ current_subject > start_subject + mb->start_offset)))
{
if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0;
- else if (match_count > 0 && ++match_count * 2 > offsetcount)
+ else if (match_count > 0 && ++match_count * 2 > (int)offsetcount)
match_count = 0;
- count = ((match_count == 0)? offsetcount : match_count * 2) - 2;
- if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int));
+ count = ((match_count == 0)? (int)offsetcount : match_count * 2) - 2;
+ if (count > 0) memmove(offsets + 2, offsets,
+ (size_t)count * sizeof(PCRE2_SIZE));
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], (char *)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;
+ offsets[0] = (PCRE2_SIZE)(current_subject - start_subject);
+ offsets[1] = (PCRE2_SIZE)(ptr - start_subject);
}
+ if ((mb->moptions & PCRE2_DFA_SHORTEST) != 0) return match_count;
}
}
break;
@@ -861,14 +797,15 @@ for (;;)
/*-----------------------------------------------------------------*/
case OP_CIRC:
- if (ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0)
+ if (ptr == start_subject && (mb->moptions & PCRE2_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)))
+ if ((ptr == start_subject && (mb->moptions & PCRE2_NOTBOL) == 0) ||
+ ((ptr != end_subject || (mb->poptions & PCRE2_ALT_CIRCUMFLEX) != 0 )
+ && WAS_NEWLINE(ptr)))
{ ADD_ACTIVE(state_offset + 1, 0); }
break;
@@ -876,7 +813,7 @@ for (;;)
case OP_EOD:
if (ptr >= end_subject)
{
- if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
+ if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)
could_continue = TRUE;
else { ADD_ACTIVE(state_offset + 1, 0); }
}
@@ -903,8 +840,8 @@ for (;;)
case OP_ANY:
if (clen > 0 && !IS_NEWLINE(ptr))
{
- if (ptr + 1 >= md->end_subject &&
- (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
+ if (ptr + 1 >= mb->end_subject &&
+ (mb->moptions & (PCRE2_PARTIAL_HARD)) != 0 &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
c == NLBLOCK->nl[0])
@@ -926,30 +863,30 @@ for (;;)
/*-----------------------------------------------------------------*/
case OP_EODN:
- if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
+ if (clen == 0 && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)
could_continue = TRUE;
- else if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - md->nllen))
+ else if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - mb->nllen))
{ ADD_ACTIVE(state_offset + 1, 0); }
break;
/*-----------------------------------------------------------------*/
case OP_DOLL:
- if ((md->moptions & PCRE_NOTEOL) == 0)
+ if ((mb->moptions & PCRE2_NOTEOL) == 0)
{
- if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
+ if (clen == 0 && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)
could_continue = TRUE;
else if (clen == 0 ||
- ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&
- (ptr == end_subject - md->nllen)
+ ((mb->poptions & PCRE2_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) &&
+ (ptr == end_subject - mb->nllen)
))
{ ADD_ACTIVE(state_offset + 1, 0); }
- else if (ptr + 1 >= md->end_subject &&
- (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 &&
+ else if (ptr + 1 >= mb->end_subject &&
+ (mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0 &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
c == NLBLOCK->nl[0])
{
- if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
+ if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)
{
reset_could_continue = TRUE;
ADD_NEW_DATA(-(state_offset + 1), 0, 1);
@@ -961,20 +898,20 @@ for (;;)
/*-----------------------------------------------------------------*/
case OP_DOLLM:
- if ((md->moptions & PCRE_NOTEOL) == 0)
+ if ((mb->moptions & PCRE2_NOTEOL) == 0)
{
- if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0)
+ if (clen == 0 && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)
could_continue = TRUE;
else if (clen == 0 ||
- ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr)))
+ ((mb->poptions & PCRE2_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr)))
{ ADD_ACTIVE(state_offset + 1, 0); }
- else if (ptr + 1 >= md->end_subject &&
- (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 &&
+ else if (ptr + 1 >= mb->end_subject &&
+ (mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0 &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
c == NLBLOCK->nl[0])
{
- if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
+ if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)
{
reset_could_continue = TRUE;
ADD_NEW_DATA(-(state_offset + 1), 0, 1);
@@ -1013,18 +950,18 @@ for (;;)
if (ptr > start_subject)
{
- const pcre_uchar *temp = ptr - 1;
- if (temp < md->start_used_ptr) md->start_used_ptr = temp;
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ PCRE2_SPTR temp = ptr - 1;
+ if (temp < mb->start_used_ptr) mb->start_used_ptr = temp;
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (utf) { BACKCHAR(temp); }
#endif
GETCHARTEST(d, temp);
-#ifdef SUPPORT_UCP
- if ((md->poptions & PCRE_UCP) != 0)
+#ifdef SUPPORT_UNICODE
+ if ((mb->poptions & PCRE2_UCP) != 0)
{
if (d == '_') left_word = TRUE; else
{
- int cat = UCD_CATEGORY(d);
+ uint32_t cat = UCD_CATEGORY(d);
left_word = (cat == ucp_L || cat == ucp_N);
}
}
@@ -1036,12 +973,20 @@ for (;;)
if (clen > 0)
{
-#ifdef SUPPORT_UCP
- if ((md->poptions & PCRE_UCP) != 0)
+ if (ptr >= mb->last_used_ptr)
+ {
+ PCRE2_SPTR temp = ptr + 1;
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (utf) { FORWARDCHARTEST(temp, mb->end_subject); }
+#endif
+ mb->last_used_ptr = temp;
+ }
+#ifdef SUPPORT_UNICODE
+ if ((mb->poptions & PCRE2_UCP) != 0)
{
if (c == '_') right_word = TRUE; else
{
- int cat = UCD_CATEGORY(c);
+ uint32_t cat = UCD_CATEGORY(c);
right_word = (cat == ucp_L || cat == ucp_N);
}
}
@@ -1062,13 +1007,13 @@ for (;;)
if the support is in the binary; otherwise a compile-time error occurs.
*/
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
case OP_PROP:
case OP_NOTPROP:
if (clen > 0)
{
BOOL OK;
- const pcre_uint32 *cp;
+ const uint32_t *cp;
const ucd_record * prop = GET_UCD(c);
switch(code[1])
{
@@ -1167,8 +1112,8 @@ for (;;)
if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
if (clen > 0)
{
- if (d == OP_ANY && ptr + 1 >= md->end_subject &&
- (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
+ if (d == OP_ANY && ptr + 1 >= mb->end_subject &&
+ (mb->moptions & (PCRE2_PARTIAL_HARD)) != 0 &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
c == NLBLOCK->nl[0])
@@ -1198,8 +1143,8 @@ for (;;)
ADD_ACTIVE(state_offset + 2, 0);
if (clen > 0)
{
- if (d == OP_ANY && ptr + 1 >= md->end_subject &&
- (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
+ if (d == OP_ANY && ptr + 1 >= mb->end_subject &&
+ (mb->moptions & (PCRE2_PARTIAL_HARD)) != 0 &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
c == NLBLOCK->nl[0])
@@ -1228,8 +1173,8 @@ for (;;)
ADD_ACTIVE(state_offset + 2, 0);
if (clen > 0)
{
- if (d == OP_ANY && ptr + 1 >= md->end_subject &&
- (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
+ if (d == OP_ANY && ptr + 1 >= mb->end_subject &&
+ (mb->moptions & (PCRE2_PARTIAL_HARD)) != 0 &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
c == NLBLOCK->nl[0])
@@ -1256,8 +1201,8 @@ for (;;)
count = current_state->count; /* Number already matched */
if (clen > 0)
{
- if (d == OP_ANY && ptr + 1 >= md->end_subject &&
- (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
+ if (d == OP_ANY && ptr + 1 >= mb->end_subject &&
+ (mb->moptions & (PCRE2_PARTIAL_HARD)) != 0 &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
c == NLBLOCK->nl[0])
@@ -1285,8 +1230,8 @@ for (;;)
count = current_state->count; /* Number already matched */
if (clen > 0)
{
- if (d == OP_ANY && ptr + 1 >= md->end_subject &&
- (md->moptions & (PCRE_PARTIAL_HARD)) != 0 &&
+ if (d == OP_ANY && ptr + 1 >= mb->end_subject &&
+ (mb->moptions & (PCRE2_PARTIAL_HARD)) != 0 &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
c == NLBLOCK->nl[0])
@@ -1317,7 +1262,7 @@ for (;;)
argument. It keeps the code above fast for the other cases. The argument
is in the d variable. */
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
case OP_PROP_EXTRA + OP_TYPEPLUS:
case OP_PROP_EXTRA + OP_TYPEMINPLUS:
case OP_PROP_EXTRA + OP_TYPEPOSPLUS:
@@ -1326,7 +1271,7 @@ for (;;)
if (clen > 0)
{
BOOL OK;
- const pcre_uint32 *cp;
+ const uint32_t *cp;
const ucd_record * prop = GET_UCD(c);
switch(code[2])
{
@@ -1426,8 +1371,8 @@ for (;;)
if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); }
if (clen > 0)
{
- int lgb, rgb;
- const pcre_uchar *nptr = ptr + clen;
+ uint32_t lgb, rgb;
+ PCRE2_SPTR nptr = ptr + clen;
int ncount = 0;
if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS)
{
@@ -1440,7 +1385,7 @@ for (;;)
dlen = 1;
if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
rgb = UCD_GRAPHBREAK(d);
- if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;
ncount++;
lgb = rgb;
nptr += dlen;
@@ -1469,7 +1414,7 @@ for (;;)
case 0x2028:
case 0x2029:
#endif /* Not EBCDIC */
- if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
+ if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) break;
goto ANYNL01;
case CHAR_CR:
@@ -1560,7 +1505,7 @@ for (;;)
break;
/*-----------------------------------------------------------------*/
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
case OP_PROP_EXTRA + OP_TYPEQUERY:
case OP_PROP_EXTRA + OP_TYPEMINQUERY:
case OP_PROP_EXTRA + OP_TYPEPOSQUERY:
@@ -1578,7 +1523,7 @@ for (;;)
if (clen > 0)
{
BOOL OK;
- const pcre_uint32 *cp;
+ const uint32_t *cp;
const ucd_record * prop = GET_UCD(c);
switch(code[2])
{
@@ -1687,8 +1632,8 @@ for (;;)
ADD_ACTIVE(state_offset + 2, 0);
if (clen > 0)
{
- int lgb, rgb;
- const pcre_uchar *nptr = ptr + clen;
+ uint32_t lgb, rgb;
+ PCRE2_SPTR nptr = ptr + clen;
int ncount = 0;
if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR ||
codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY)
@@ -1702,7 +1647,7 @@ for (;;)
dlen = 1;
if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
rgb = UCD_GRAPHBREAK(d);
- if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;
ncount++;
lgb = rgb;
nptr += dlen;
@@ -1738,7 +1683,7 @@ for (;;)
case 0x2028:
case 0x2029:
#endif /* Not EBCDIC */
- if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
+ if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) break;
goto ANYNL02;
case CHAR_CR:
@@ -1844,7 +1789,7 @@ for (;;)
break;
/*-----------------------------------------------------------------*/
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
case OP_PROP_EXTRA + OP_TYPEEXACT:
case OP_PROP_EXTRA + OP_TYPEUPTO:
case OP_PROP_EXTRA + OP_TYPEMINUPTO:
@@ -1855,7 +1800,7 @@ for (;;)
if (clen > 0)
{
BOOL OK;
- const pcre_uint32 *cp;
+ const uint32_t *cp;
const ucd_record * prop = GET_UCD(c);
switch(code[1 + IMM2_SIZE + 1])
{
@@ -1959,8 +1904,8 @@ for (;;)
count = current_state->count; /* Number already matched */
if (clen > 0)
{
- int lgb, rgb;
- const pcre_uchar *nptr = ptr + clen;
+ uint32_t lgb, rgb;
+ PCRE2_SPTR nptr = ptr + clen;
int ncount = 0;
if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO)
{
@@ -1973,12 +1918,12 @@ for (;;)
dlen = 1;
if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
rgb = UCD_GRAPHBREAK(d);
- if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;
ncount++;
lgb = rgb;
nptr += dlen;
}
- if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0)
+ if (nptr >= end_subject && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)
reset_could_continue = TRUE;
if (++count >= (int)GET2(code, 1))
{ ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); }
@@ -2008,7 +1953,7 @@ for (;;)
case 0x2028:
case 0x2029:
#endif /* Not EBCDIC */
- if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
+ if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) break;
goto ANYNL03;
case CHAR_CR:
@@ -2122,7 +2067,7 @@ for (;;)
case OP_CHARI:
if (clen == 0) break;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else
@@ -2131,19 +2076,12 @@ for (;;)
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 */
+#endif /* SUPPORT_UNICODE */
/* Not UTF mode */
{
if (TABLE_GET(c, lcc, c) == TABLE_GET(d, lcc, d))
@@ -2152,7 +2090,7 @@ for (;;)
break;
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
/*-----------------------------------------------------------------*/
/* This is a tricky one because it can match more than one character.
Find out how many characters to skip, and then set up a negative state
@@ -2161,8 +2099,8 @@ for (;;)
case OP_EXTUNI:
if (clen > 0)
{
- int lgb, rgb;
- const pcre_uchar *nptr = ptr + clen;
+ uint32_t lgb, rgb;
+ PCRE2_SPTR nptr = ptr + clen;
int ncount = 0;
lgb = UCD_GRAPHBREAK(c);
while (nptr < end_subject)
@@ -2170,12 +2108,12 @@ for (;;)
dlen = 1;
if (!utf) d = *nptr; else { GETCHARLEN(d, nptr, dlen); }
rgb = UCD_GRAPHBREAK(d);
- if ((PRIV(ucp_gbtable)[lgb] & (1 << rgb)) == 0) break;
+ if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;
ncount++;
lgb = rgb;
nptr += dlen;
}
- if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0)
+ if (nptr >= end_subject && (mb->moptions & PCRE2_PARTIAL_HARD) != 0)
reset_could_continue = TRUE;
ADD_NEW_DATA(-(state_offset + 1), 0, ncount);
}
@@ -2197,7 +2135,7 @@ for (;;)
case 0x2028:
case 0x2029:
#endif /* Not EBCDIC */
- if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break;
+ if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) break;
case CHAR_LF:
ADD_NEW(state_offset + 1, 0);
@@ -2207,7 +2145,7 @@ for (;;)
if (ptr + 1 >= end_subject)
{
ADD_NEW(state_offset + 1, 0);
- if ((md->moptions & PCRE_PARTIAL_HARD) != 0)
+ if ((mb->moptions & PCRE2_PARTIAL_HARD) != 0)
reset_could_continue = TRUE;
}
else if (UCHAR21TEST(ptr + 1) == CHAR_LF)
@@ -2288,15 +2226,11 @@ for (;;)
if (clen > 0)
{
unsigned int otherd;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf && d >= 128)
- {
-#ifdef SUPPORT_UCP
otherd = UCD_OTHERCASE(d);
-#endif /* SUPPORT_UCP */
- }
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
otherd = TABLE_GET(d, fcc, d);
if (c != d && c != otherd)
{ ADD_NEW(state_offset + dlen + 1, 0); }
@@ -2324,18 +2258,14 @@ for (;;)
if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); }
if (clen > 0)
{
- pcre_uint32 otherd = NOTACHAR;
+ uint32_t otherd = NOTACHAR;
if (caseless)
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf && d >= 128)
- {
-#ifdef SUPPORT_UCP
otherd = UCD_OTHERCASE(d);
-#endif /* SUPPORT_UCP */
- }
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
otherd = TABLE_GET(d, fcc, d);
}
if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
@@ -2371,18 +2301,14 @@ for (;;)
ADD_ACTIVE(state_offset + dlen + 1, 0);
if (clen > 0)
{
- pcre_uint32 otherd = NOTACHAR;
+ uint32_t otherd = NOTACHAR;
if (caseless)
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf && d >= 128)
- {
-#ifdef SUPPORT_UCP
otherd = UCD_OTHERCASE(d);
-#endif /* SUPPORT_UCP */
- }
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
otherd = TABLE_GET(d, fcc, d);
}
if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
@@ -2416,18 +2342,14 @@ for (;;)
ADD_ACTIVE(state_offset + dlen + 1, 0);
if (clen > 0)
{
- pcre_uint32 otherd = NOTACHAR;
+ uint32_t otherd = NOTACHAR;
if (caseless)
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf && d >= 128)
- {
-#ifdef SUPPORT_UCP
otherd = UCD_OTHERCASE(d);
-#endif /* SUPPORT_UCP */
- }
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
otherd = TABLE_GET(d, fcc, d);
}
if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
@@ -2453,18 +2375,14 @@ for (;;)
count = current_state->count; /* Number already matched */
if (clen > 0)
{
- pcre_uint32 otherd = NOTACHAR;
+ uint32_t otherd = NOTACHAR;
if (caseless)
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf && d >= 128)
- {
-#ifdef SUPPORT_UCP
otherd = UCD_OTHERCASE(d);
-#endif /* SUPPORT_UCP */
- }
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
otherd = TABLE_GET(d, fcc, d);
}
if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
@@ -2497,18 +2415,14 @@ for (;;)
count = current_state->count; /* Number already matched */
if (clen > 0)
{
- pcre_uint32 otherd = NOTACHAR;
+ uint32_t otherd = NOTACHAR;
if (caseless)
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf && d >= 128)
- {
-#ifdef SUPPORT_UCP
otherd = UCD_OTHERCASE(d);
-#endif /* SUPPORT_UCP */
- }
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
otherd = TABLE_GET(d, fcc, d);
}
if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR))
@@ -2536,18 +2450,18 @@ for (;;)
{
BOOL isinclass = FALSE;
int next_state_offset;
- const pcre_uchar *ecode;
+ PCRE2_SPTR ecode;
/* For a simple class, there is always just a 32-byte table, and we
can set isinclass from it. */
if (codevalue != OP_XCLASS)
{
- ecode = code + 1 + (32 / sizeof(pcre_uchar));
+ ecode = code + 1 + (32 / sizeof(PCRE2_UCHAR));
if (clen > 0)
{
isinclass = (c > 255)? (codevalue == OP_NCLASS) :
- ((((pcre_uint8 *)(code + 1))[c/8] & (1 << (c&7))) != 0);
+ ((((uint8_t *)(code + 1))[c/8] & (1 << (c&7))) != 0);
}
}
@@ -2659,25 +2573,25 @@ for (;;)
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
{
+ PCRE2_SPTR endasscode = code + GET(code, 1);
+ PCRE2_SIZE local_offsets[2];
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 */
+ rc = internal_dfa_match(
+ mb, /* static match data */
code, /* this subexpression's code */
ptr, /* where we currently are */
- (int)(ptr - start_subject), /* start offset */
+ (PCRE2_SIZE)(ptr - start_subject), /* start offset */
local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(int), /* size of same */
+ sizeof(local_offsets)/sizeof(PCRE2_SIZE), /* 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 == PCRE2_ERROR_DFA_UITEM) return rc;
if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK))
{ ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); }
}
@@ -2687,44 +2601,59 @@ for (;;)
case OP_COND:
case OP_SCOND:
{
- int local_offsets[1000];
+ PCRE2_SIZE local_offsets[1000];
int local_workspace[1000];
- int codelink = GET(code, 1);
- int condcode;
+ int codelink = (int)GET(code, 1);
+ PCRE2_UCHAR condcode;
/* Because of the way auto-callout works during compile, a callout item
is inserted between OP_COND and an assertion condition. This does not
happen for the other conditions. */
- if (code[LINK_SIZE+1] == OP_CALLOUT)
+ if (code[LINK_SIZE + 1] == OP_CALLOUT
+ || code[LINK_SIZE + 1] == OP_CALLOUT_STR)
{
+ PCRE2_SIZE callout_length = (code[LINK_SIZE + 1] == OP_CALLOUT)?
+ (PCRE2_SIZE)PRIV(OP_lengths)[OP_CALLOUT] :
+ (PCRE2_SIZE)GET(code, 2 + 3*LINK_SIZE);
+
rrc = 0;
- if (PUBL(callout) != NULL)
+ if (mb->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;
-#if defined COMPILE_PCRE8
- cb.subject = (PCRE_SPTR)start_subject;
-#elif defined COMPILE_PCRE16
- cb.subject = (PCRE_SPTR16)start_subject;
-#elif defined COMPILE_PCRE32
- cb.subject = (PCRE_SPTR32)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);
+ pcre2_callout_block cb;
+ cb.version = 1;
cb.capture_top = 1;
- cb.capture_last = -1;
- cb.callout_data = md->callout_data;
+ cb.capture_last = 0;
+ cb.offset_vector = offsets;
cb.mark = NULL; /* No (*MARK) support */
- if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc; /* Abandon */
+ cb.subject = start_subject;
+ cb.subject_length = (PCRE2_SIZE)(end_subject - start_subject);
+ cb.start_match = (PCRE2_SIZE)(current_subject - start_subject);
+ cb.current_position = (PCRE2_SIZE)(ptr - start_subject);
+ cb.pattern_position = GET(code, LINK_SIZE + 2);
+ cb.next_item_length = GET(code, LINK_SIZE + 2 + LINK_SIZE);
+
+ if (code[LINK_SIZE + 1] == OP_CALLOUT)
+ {
+ cb.callout_number = code[2 + 3*LINK_SIZE];
+ cb.callout_string_offset = 0;
+ cb.callout_string = NULL;
+ cb.callout_string_length = 0;
+ }
+ else
+ {
+ cb.callout_number = 0;
+ cb.callout_string_offset = GET(code, 2 + 4*LINK_SIZE);
+ cb.callout_string = code + (2 + 5*LINK_SIZE) + 1;
+ cb.callout_string_length =
+ callout_length - (1 + 4*LINK_SIZE) - 2;
+ }
+
+ if ((rrc = (mb->callout)(&cb, mb->callout_data)) < 0)
+ return rrc; /* Abandon */
}
if (rrc > 0) break; /* Fail this thread */
- code += PRIV(OP_lengths)[OP_CALLOUT]; /* Skip callout data */
+ code += callout_length; /* Skip callout data */
}
condcode = code[LINK_SIZE+1];
@@ -2734,23 +2663,28 @@ for (;;)
if (condcode == OP_CREF || condcode == OP_DNCREF ||
condcode == OP_DNRREF)
- return PCRE_ERROR_DFA_UCOND;
+ return PCRE2_ERROR_DFA_UCOND;
/* The DEFINE condition is always false, and the assertion (?!) is
converted to OP_FAIL. */
- if (condcode == OP_DEF || condcode == OP_FAIL)
+ if (condcode == OP_FALSE || condcode == OP_FAIL)
{ ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
+ /* There is also an always-true condition */
+
+ else if (condcode == OP_TRUE)
+ { ADD_ACTIVE(state_offset + LINK_SIZE + 2 + IMM2_SIZE, 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)
{
- int value = GET2(code, LINK_SIZE + 2);
- if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND;
- if (md->recursive != NULL)
+ unsigned int value = GET2(code, LINK_SIZE + 2);
+ if (value != RREF_ANY) return PCRE2_ERROR_DFA_UCOND;
+ if (mb->recursive != NULL)
{ ADD_ACTIVE(state_offset + LINK_SIZE + 2 + IMM2_SIZE, 0); }
else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
}
@@ -2760,23 +2694,23 @@ for (;;)
else
{
int rc;
- const pcre_uchar *asscode = code + LINK_SIZE + 1;
- const pcre_uchar *endasscode = asscode + GET(asscode, 1);
+ PCRE2_SPTR asscode = code + LINK_SIZE + 1;
+ PCRE2_SPTR endasscode = asscode + GET(asscode, 1);
while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1);
- rc = internal_dfa_exec(
- md, /* fixed match data */
+ rc = internal_dfa_match(
+ mb, /* fixed match data */
asscode, /* this subexpression's code */
ptr, /* where we currently are */
- (int)(ptr - start_subject), /* start offset */
+ (PCRE2_SIZE)(ptr - start_subject), /* start offset */
local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(int), /* size of same */
+ sizeof(local_offsets)/sizeof(PCRE2_SIZE), /* 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 == PCRE2_ERROR_DFA_UITEM) return rc;
if ((rc >= 0) ==
(condcode == OP_ASSERT || condcode == OP_ASSERTBACK))
{ ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); }
@@ -2790,50 +2724,45 @@ for (;;)
case OP_RECURSE:
{
dfa_recursion_info *ri;
- int local_offsets[1000];
+ PCRE2_SIZE local_offsets[1000];
int local_workspace[1000];
- const pcre_uchar *callpat = start_code + GET(code, 1);
- int recno = (callpat == md->start_code)? 0 :
+ PCRE2_SPTR callpat = start_code + GET(code, 1);
+ uint32_t recno = (callpat == mb->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)
+ for (ri = mb->recursive; ri != NULL; ri = ri->prevrec)
if (recno == ri->group_num && ptr == ri->subject_position)
- return PCRE_ERROR_RECURSELOOP;
+ return PCRE2_ERROR_RECURSELOOP;
/* Remember this recursion and where we started it so as to
catch infinite loops. */
new_recursive.group_num = recno;
new_recursive.subject_position = ptr;
- new_recursive.prevrec = md->recursive;
- md->recursive = &new_recursive;
+ new_recursive.prevrec = mb->recursive;
+ mb->recursive = &new_recursive;
- rc = internal_dfa_exec(
- md, /* fixed match data */
+ rc = internal_dfa_match(
+ mb, /* fixed match data */
callpat, /* this subexpression's code */
ptr, /* where we currently are */
- (int)(ptr - start_subject), /* start offset */
+ (PCRE2_SIZE)(ptr - start_subject), /* start offset */
local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(int), /* size of same */
+ sizeof(local_offsets)/sizeof(PCRE2_SIZE), /* 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));
+ mb->recursive = new_recursive.prevrec; /* Done this recursion */
/* Ran out of internal offsets */
- if (rc == 0) return PCRE_ERROR_DFA_RECURSE;
+ if (rc == 0) return PCRE2_ERROR_DFA_RECURSE;
/* For each successful matched substring, set up the next state with a
count of characters to skip before trying it. Note that the count is in
@@ -2843,18 +2772,19 @@ for (;;)
{
for (rc = rc*2 - 2; rc >= 0; rc -= 2)
{
- int charcount = local_offsets[rc+1] - local_offsets[rc];
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+ PCRE2_SIZE charcount = local_offsets[rc+1] - local_offsets[rc];
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (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--;
+ PCRE2_SPTR p = start_subject + local_offsets[rc];
+ PCRE2_SPTR pp = start_subject + local_offsets[rc+1];
+ while (p < pp) if (NOT_FIRSTCU(*p++)) charcount--;
}
#endif
if (charcount > 0)
{
- ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0, (charcount - 1));
+ ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0,
+ (int)(charcount - 1));
}
else
{
@@ -2862,7 +2792,7 @@ for (;;)
}
}
}
- else if (rc != PCRE_ERROR_NOMATCH) return rc;
+ else if (rc != PCRE2_ERROR_NOMATCH) return rc;
}
break;
@@ -2873,8 +2803,8 @@ for (;;)
case OP_SCBRAPOS:
case OP_BRAPOSZERO:
{
- int charcount, matched_count;
- const pcre_uchar *local_ptr = ptr;
+ PCRE2_SIZE charcount, matched_count;
+ PCRE2_SPTR local_ptr = ptr;
BOOL allow_zero;
if (codevalue == OP_BRAPOSZERO)
@@ -2889,16 +2819,16 @@ for (;;)
for (matched_count = 0;; matched_count++)
{
- int local_offsets[2];
+ PCRE2_SIZE local_offsets[2];
int local_workspace[1000];
- int rc = internal_dfa_exec(
- md, /* fixed match data */
+ int rc = internal_dfa_match(
+ mb, /* fixed match data */
code, /* this subexpression's code */
local_ptr, /* where we currently are */
- (int)(ptr - start_subject), /* start offset */
+ (PCRE2_SIZE)(ptr - start_subject), /* start offset */
local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(int), /* size of same */
+ sizeof(local_offsets)/sizeof(PCRE2_SIZE), /* size of same */
local_workspace, /* workspace vector */
sizeof(local_workspace)/sizeof(int), /* size of same */
rlevel); /* function recursion level */
@@ -2907,7 +2837,7 @@ for (;;)
if (rc < 0)
{
- if (rc != PCRE_ERROR_NOMATCH) return rc;
+ if (rc != PCRE2_ERROR_NOMATCH) return rc;
break;
}
@@ -2924,7 +2854,7 @@ for (;;)
if (matched_count > 0 || allow_zero)
{
- const pcre_uchar *end_subpattern = code;
+ PCRE2_SPTR end_subpattern = code;
int next_state_offset;
do { end_subpattern += GET(end_subpattern, 1); }
@@ -2945,13 +2875,13 @@ for (;;)
}
else
{
- const pcre_uchar *p = ptr;
- const pcre_uchar *pp = local_ptr;
- charcount = (int)(pp - p);
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
- if (utf) while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--;
+ PCRE2_SPTR p = ptr;
+ PCRE2_SPTR pp = local_ptr;
+ charcount = (PCRE2_SIZE)(pp - p);
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+ if (utf) while (p < pp) if (NOT_FIRSTCU(*p++)) charcount--;
#endif
- ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));
+ ADD_NEW_DATA(-next_state_offset, 0, (int)(charcount - 1));
}
}
}
@@ -2961,24 +2891,24 @@ for (;;)
case OP_ONCE:
case OP_ONCE_NC:
{
- int local_offsets[2];
+ PCRE2_SIZE local_offsets[2];
int local_workspace[1000];
- int rc = internal_dfa_exec(
- md, /* fixed match data */
+ int rc = internal_dfa_match(
+ mb, /* fixed match data */
code, /* this subexpression's code */
ptr, /* where we currently are */
- (int)(ptr - start_subject), /* start offset */
+ (PCRE2_SIZE)(ptr - start_subject), /* start offset */
local_offsets, /* offset vector */
- sizeof(local_offsets)/sizeof(int), /* size of same */
+ sizeof(local_offsets)/sizeof(PCRE2_SIZE), /* 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];
+ PCRE2_SPTR end_subpattern = code;
+ PCRE2_SIZE charcount = local_offsets[1] - local_offsets[0];
int next_state_offset, repeat_state_offset;
do { end_subpattern += GET(end_subpattern, 1); }
@@ -3030,20 +2960,20 @@ for (;;)
}
else
{
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (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--;
+ PCRE2_SPTR p = start_subject + local_offsets[0];
+ PCRE2_SPTR pp = start_subject + local_offsets[1];
+ while (p < pp) if (NOT_FIRSTCU(*p++)) charcount--;
}
#endif
- ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1));
+ ADD_NEW_DATA(-next_state_offset, 0, (int)(charcount - 1));
if (repeat_state_offset >= 0)
- { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); }
+ { ADD_NEW_DATA(-repeat_state_offset, 0, (int)(charcount - 1)); }
}
}
- else if (rc != PCRE_ERROR_NOMATCH) return rc;
+ else if (rc != PCRE2_ERROR_NOMATCH) return rc;
}
break;
@@ -3052,39 +2982,55 @@ for (;;)
/* Handle callouts */
case OP_CALLOUT:
- rrc = 0;
- if (PUBL(callout) != NULL)
+ case OP_CALLOUT_STR:
{
- PUBL(callout_block) cb;
- cb.version = 1; /* Version 1 of the callout block */
- cb.callout_number = code[1];
- cb.offset_vector = offsets;
-#if defined COMPILE_PCRE8
- cb.subject = (PCRE_SPTR)start_subject;
-#elif defined COMPILE_PCRE16
- cb.subject = (PCRE_SPTR16)start_subject;
-#elif defined COMPILE_PCRE32
- cb.subject = (PCRE_SPTR32)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 */
+ unsigned int callout_length = (*code == OP_CALLOUT)
+ ? PRIV(OP_lengths)[OP_CALLOUT] : GET(code, 1 + 2*LINK_SIZE);
+ rrc = 0;
+
+ if (mb->callout != NULL)
+ {
+ pcre2_callout_block cb;
+ cb.version = 1;
+ cb.capture_top = 1;
+ cb.capture_last = 0;
+ cb.offset_vector = offsets;
+ cb.mark = NULL; /* No (*MARK) support */
+ cb.subject = start_subject;
+ cb.subject_length = (PCRE2_SIZE)(end_subject - start_subject);
+ cb.start_match = (PCRE2_SIZE)(current_subject - start_subject);
+ cb.current_position = (PCRE2_SIZE)(ptr - start_subject);
+ cb.pattern_position = GET(code, 1);
+ cb.next_item_length = GET(code, 1 + LINK_SIZE);
+
+ if (*code == OP_CALLOUT)
+ {
+ cb.callout_number = code[1 + 2*LINK_SIZE];
+ cb.callout_string_offset = 0;
+ cb.callout_string = NULL;
+ cb.callout_string_length = 0;
+ }
+ else
+ {
+ cb.callout_number = 0;
+ cb.callout_string_offset = GET(code, 1 + 3*LINK_SIZE);
+ cb.callout_string = code + (1 + 4*LINK_SIZE) + 1;
+ cb.callout_string_length =
+ callout_length - (1 + 4*LINK_SIZE) - 2;
+ }
+
+ if ((rrc = (mb->callout)(&cb, mb->callout_data)) < 0)
+ return rrc; /* Abandon */
+ }
+ if (rrc == 0)
+ { ADD_ACTIVE(state_offset + (int)callout_length, 0); }
}
- if (rrc == 0)
- { ADD_ACTIVE(state_offset + PRIV(OP_lengths)[OP_CALLOUT], 0); }
break;
/* ========================================================================== */
default: /* Unsupported opcode */
- return PCRE_ERROR_DFA_UITEM;
+ return PCRE2_ERROR_DFA_UITEM;
}
NEXT_ACTIVE_STATE: continue;
@@ -3110,22 +3056,19 @@ for (;;)
could_continue && /* Some could go on, and */
forced_fail != workspace[1] && /* Not all forced fail & */
( /* either... */
- (md->moptions & PCRE_PARTIAL_HARD) != 0 /* Hard partial */
+ (mb->moptions & PCRE2_PARTIAL_HARD) != 0 /* Hard partial */
|| /* or... */
- ((md->moptions & PCRE_PARTIAL_SOFT) != 0 && /* Soft partial and */
+ ((mb->moptions & PCRE2_PARTIAL_SOFT) != 0 && /* Soft partial and */
match_count < 0) /* no matches */
) && /* And... */
(
partial_newline || /* Either partial NL */
( /* or ... */
ptr >= end_subject && /* End of subject and */
- ptr > md->start_used_ptr) /* Inspected non-empty string */
+ ptr > mb->start_used_ptr) /* Inspected non-empty string */
)
)
- 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));
+ match_count = PCRE2_ERROR_PARTIAL;
break; /* In effect, "return", but see the comment below */
}
@@ -3145,285 +3088,288 @@ return match_count;
-
/*************************************************
-* Execute a Regular Expression - DFA engine *
+* Match a pattern using the DFA algorithm *
*************************************************/
-/* 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.
+/* This function matches a compiled pattern to a subject string, using the
+alternate matching algorithm that finds all matches at once.
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
+ code points to the compiled pattern
+ subject subject string
+ length length of subject string
+ startoffset where to start matching in the subject
+ options option bits
+ match_data points to a match data structure
+ gcontext points to a match context
+ workspace pointer to workspace
+ wscount size of workspace
+
+Returns: > 0 => number of match offset pairs placed in offsets
+ = 0 => offsets overflowed; longest matches are present
+ -1 => failed to match
+ < -1 => some kind of unexpected problem
*/
-#if defined 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)
-#elif defined COMPILE_PCRE16
-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)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_dfa_exec(const pcre32 *argument_re, const pcre32_extra *extra_data,
- PCRE_SPTR32 subject, int length, int start_offset, int options, int *offsets,
- int offsetcount, int *workspace, int wscount)
-#endif
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_dfa_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
+ PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext, int *workspace, size_t wscount)
{
-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;
+const pcre2_real_code *re = (const pcre2_real_code *)code;
-/* Plausibility checks */
+PCRE2_SPTR start_match;
+PCRE2_SPTR end_subject;
+PCRE2_SPTR bumpalong_limit;
+PCRE2_SPTR req_cu_ptr;
-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 (length < 0) return PCRE_ERROR_BADLENGTH;
-if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET;
+BOOL utf, anchored, startline, firstline;
-/* 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. */
+BOOL has_first_cu = FALSE;
+BOOL has_req_cu = FALSE;
+PCRE2_UCHAR first_cu = 0;
+PCRE2_UCHAR first_cu2 = 0;
+PCRE2_UCHAR req_cu = 0;
+PCRE2_UCHAR req_cu2 = 0;
-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;
+const uint8_t *start_bits = NULL;
-/* If restarting after a partial match, do some sanity checks on the contents
-of the workspace. */
+/* We need to have mb pointing to a match block, because the IS_NEWLINE macro
+is used below, and it expects NLBLOCK to be defined as a pointer. */
-if ((options & PCRE_DFA_RESTART) != 0)
- {
- if ((workspace[0] & (-2)) != 0 || workspace[1] < 1 ||
- workspace[1] > (wscount - 2)/INTS_PER_STATEBLOCK)
- return PCRE_ERROR_DFA_BADRESTART;
- }
+dfa_match_block actual_match_block;
+dfa_match_block *mb = &actual_match_block;
-/* Set up study, callout, and table data */
+/* A length equal to PCRE2_ZERO_TERMINATED implies a zero-terminated
+subject string. */
-md->tables = re->tables;
-md->callout_data = NULL;
+if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject);
-if (extra_data != NULL)
- {
- unsigned long 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;
- }
+/* Plausibility checks */
-/* Set some local values */
+if ((options & ~PUBLIC_DFA_MATCH_OPTIONS) != 0) return PCRE2_ERROR_BADOPTION;
+if (re == NULL || subject == NULL || workspace == NULL || match_data == NULL)
+ return PCRE2_ERROR_NULL;
+if (wscount < 20) return PCRE2_ERROR_DFA_WSSIZE;
+if (start_offset > length) return PCRE2_ERROR_BADOFFSET;
-current_subject = (const pcre_uchar *)subject + start_offset;
-end_subject = (const pcre_uchar *)subject + length;
-req_char_ptr = current_subject - 1;
+/* Check that the first field in the block is the magic number. If it is not,
+return with PCRE2_ERROR_BADMAGIC. */
-#ifdef SUPPORT_UTF
-/* PCRE_UTF(16|32) have the same value as PCRE_UTF8. */
-utf = (re->options & PCRE_UTF8) != 0;
-#else
-utf = FALSE;
-#endif
+if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;
-anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 ||
- (re->options & PCRE_ANCHORED) != 0;
+/* Check the code unit width. */
-/* The remaining fixed data for passing around. */
+if ((re->flags & PCRE2_MODE_MASK) != PCRE2_CODE_UNIT_WIDTH/8)
+ return PCRE2_ERROR_BADMODE;
-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;
+/* PCRE2_NOTEMPTY and PCRE2_NOTEMPTY_ATSTART are match-time flags in the
+options variable for this function. Users of PCRE2 who are not calling the
+function directly would like to have a way of setting these flags, in the same
+way that they can set pcre2_compile() flags like PCRE2_NO_AUTOPOSSESS with
+constructions like (*NO_AUTOPOSSESS). To enable this, (*NOTEMPTY) and
+(*NOTEMPTY_ATSTART) set bits in the pattern's "flag" function which can now be
+transferred to the options for this function. The bits are guaranteed to be
+adjacent, but do not have the same values. This bit of Boolean trickery assumes
+that the match-time bits are not more significant than the flag bits. If by
+accident this is not the case, a compile-time division by zero error will
+occur. */
-/* If the BSR option is not set at match time, copy what was set
-at compile time. */
+#define FF (PCRE2_NOTEMPTY_SET|PCRE2_NE_ATST_SET)
+#define OO (PCRE2_NOTEMPTY|PCRE2_NOTEMPTY_ATSTART)
+options |= (re->flags & FF) / ((FF & (~FF+1)) / (OO & (~OO+1)));
+#undef FF
+#undef OO
-if ((md->moptions & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == 0)
+/* If restarting after a partial match, do some sanity checks on the contents
+of the workspace. */
+
+if ((options & PCRE2_DFA_RESTART) != 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
+ if ((workspace[0] & (-2)) != 0 || workspace[1] < 1 ||
+ workspace[1] > (int)((wscount - 2)/INTS_PER_STATEBLOCK))
+ return PCRE2_ERROR_DFA_BADRESTART;
}
-/* 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. */
+/* Set some local values */
-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;
- }
+utf = (re->overall_options & PCRE2_UTF) != 0;
+start_match = subject + start_offset;
+end_subject = subject + length;
+req_cu_ptr = start_match - 1;
+anchored = (options & (PCRE2_ANCHORED|PCRE2_DFA_RESTART)) != 0 ||
+ (re->overall_options & PCRE2_ANCHORED) != 0;
-if (newline == -2)
- {
- md->nltype = NLTYPE_ANYCRLF;
- }
-else if (newline < 0)
+/* The "must be at the start of a line" flags are used in a loop when finding
+where to start. */
+
+startline = (re->flags & PCRE2_STARTLINE) != 0;
+firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0;
+bumpalong_limit = end_subject;
+
+/* Get data from the match context, if present, and fill in the fields in the
+match block. It is an error to set an offset limit without setting the flag at
+compile time. */
+
+if (mcontext == NULL)
{
- md->nltype = NLTYPE_ANY;
+ mb->callout = NULL;
+ mb->memctl = re->memctl;
}
else
{
- md->nltype = NLTYPE_FIXED;
- if (newline > 255)
+ if (mcontext->offset_limit != PCRE2_UNSET)
{
- md->nllen = 2;
- md->nl[0] = (newline >> 8) & 255;
- md->nl[1] = newline & 255;
- }
- else
- {
- md->nllen = 1;
- md->nl[0] = newline;
+ if ((re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0)
+ return PCRE2_ERROR_BADOFFSETLIMIT;
+ bumpalong_limit = subject + mcontext->offset_limit;
}
+ mb->callout = mcontext->callout;
+ mb->callout_data = mcontext->callout_data;
+ mb->memctl = mcontext->memctl;
+ }
+
+mb->start_code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) +
+ re->name_count * re->name_entry_size;
+mb->tables = re->tables;
+mb->start_subject = subject;
+mb->end_subject = end_subject;
+mb->start_offset = start_offset;
+mb->moptions = options;
+mb->poptions = re->overall_options;
+
+/* Process the \R and newline settings. */
+
+mb->bsr_convention = re->bsr_convention;
+mb->nltype = NLTYPE_FIXED;
+switch(re->newline_convention)
+ {
+ case PCRE2_NEWLINE_CR:
+ mb->nllen = 1;
+ mb->nl[0] = CHAR_CR;
+ break;
+
+ case PCRE2_NEWLINE_LF:
+ mb->nllen = 1;
+ mb->nl[0] = CHAR_NL;
+ break;
+
+ case PCRE2_NEWLINE_CRLF:
+ mb->nllen = 2;
+ mb->nl[0] = CHAR_CR;
+ mb->nl[1] = CHAR_NL;
+ break;
+
+ case PCRE2_NEWLINE_ANY:
+ mb->nltype = NLTYPE_ANY;
+ break;
+
+ case PCRE2_NEWLINE_ANYCRLF:
+ mb->nltype = NLTYPE_ANYCRLF;
+ break;
+
+ default: return PCRE2_ERROR_INTERNAL;
}
-/* Check a UTF-8 string if required. Unfortunately there's no way of passing
-back the character offset. */
+/* Check a UTF string for validity if required. For 8-bit and 16-bit strings,
+we must also check that a starting offset does not point into the middle of a
+multiunit character. We check only the portion of the subject that is going to
+be inspected during matching - from the offset minus the maximum back reference
+to the given length. This saves time when a small part of a large subject is
+being matched by the use of a starting offset. Note that the maximum lookbehind
+is a number of characters, not code units. */
-#ifdef SUPPORT_UTF
-if (utf && (options & PCRE_NO_UTF8_CHECK) == 0)
+#ifdef SUPPORT_UNICODE
+if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)
{
- int erroroffset;
- int errorcode = PRIV(valid_utf)((pcre_uchar *)subject, length, &erroroffset);
- if (errorcode != 0)
+ PCRE2_SPTR check_subject = start_match; /* start_match includes offset */
+
+ if (start_offset > 0)
{
- if (offsetcount >= 2)
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ unsigned int i;
+ if (start_match < end_subject && NOT_FIRSTCU(*start_match))
+ return PCRE2_ERROR_BADUTFOFFSET;
+ for (i = re->max_lookbehind; i > 0 && check_subject > subject; i--)
{
- offsets[0] = erroroffset;
- offsets[1] = errorcode;
+ check_subject--;
+ while (check_subject > subject &&
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ (*check_subject & 0xc0) == 0x80)
+#else /* 16-bit */
+ (*check_subject & 0xfc00) == 0xdc00)
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
+ check_subject--;
}
-#if defined COMPILE_PCRE8
- return (errorcode <= PCRE_UTF8_ERR5 && (options & PCRE_PARTIAL_HARD) != 0) ?
- PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
-#elif defined COMPILE_PCRE16
- return (errorcode <= PCRE_UTF16_ERR1 && (options & PCRE_PARTIAL_HARD) != 0) ?
- PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16;
-#elif defined COMPILE_PCRE32
- return PCRE_ERROR_BADUTF32;
-#endif
+#else /* In the 32-bit library, one code unit equals one character. */
+ check_subject -= re->max_lookbehind;
+ if (check_subject < subject) check_subject = subject;
+#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */
}
-#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
- if (start_offset > 0 && start_offset < length &&
- NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset]))
- return PCRE_ERROR_BADUTF8_OFFSET;
-#endif
- }
-#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);
+ /* Validate the relevant portion of the subject. After an error, adjust the
+ offset to be an absolute offset in the whole string. */
-/* 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;
+ match_data->rc = PRIV(valid_utf)(check_subject,
+ length - (PCRE2_SIZE)(check_subject - subject), &(match_data->startchar));
+ if (match_data->rc != 0)
+ {
+ match_data->startchar += (PCRE2_SIZE)(check_subject - subject);
+ return match_data->rc;
+ }
+ }
+#endif /* SUPPORT_UNICODE */
-/* Set up the first 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. */
+/* Set up the first code unit to match, if available. The first_codeunit 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 code unit may
+be unset for an unanchored pattern, of course. If there's no first code unit
+there may be a bitmap of possible first characters. */
if (!anchored)
{
- if ((re->flags & PCRE_FIRSTSET) != 0)
+ if ((re->flags & PCRE2_FIRSTSET) != 0)
{
- has_first_char = TRUE;
- first_char = first_char2 = (pcre_uchar)(re->first_char);
- if ((re->flags & PCRE_FCH_CASELESS) != 0)
+ has_first_cu = TRUE;
+ first_cu = first_cu2 = (PCRE2_UCHAR)(re->first_codeunit);
+ if ((re->flags & PCRE2_FIRSTCASELESS) != 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);
+ first_cu2 = TABLE_GET(first_cu, mb->tables + fcc_offset, first_cu);
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
+ if (utf && first_cu > 127)
+ first_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(first_cu);
#endif
}
}
else
- {
- if (!startline && study != NULL &&
- (study->flags & PCRE_STUDY_MAPPED) != 0)
- start_bits = study->start_bits;
- }
+ if (!startline && (re->flags & PCRE2_FIRSTMAPSET) != 0)
+ start_bits = re->start_bitmap;
}
/* For anchored or unanchored matches, there may be a "last known required
character" set. */
-if ((re->flags & PCRE_REQCHSET) != 0)
+if ((re->flags & PCRE2_LASTSET) != 0)
{
- has_req_char = TRUE;
- req_char = req_char2 = (pcre_uchar)(re->req_char);
- if ((re->flags & PCRE_RCH_CASELESS) != 0)
+ has_req_cu = TRUE;
+ req_cu = req_cu2 = (PCRE2_UCHAR)(re->last_codeunit);
+ if ((re->flags & PCRE2_LASTCASELESS) != 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);
+ req_cu2 = TABLE_GET(req_cu, mb->tables + fcc_offset, req_cu);
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
+ if (utf && req_cu > 127) req_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(req_cu);
#endif
}
}
+/* Fill in fields that are always returned in the match data. */
+
+match_data->code = re;
+match_data->subject = subject;
+match_data->mark = NULL;
+match_data->matchedby = PCRE2_MATCHEDBY_DFA_INTERPRETER;
+
/* Call the main matching function, looping for a non-anchored regex after a
failed match. If not restarting, perform certain optimizations at the start of
a match. */
@@ -3432,22 +3378,32 @@ for (;;)
{
int rc;
- if ((options & PCRE_DFA_RESTART) == 0)
+ /* ----------------- Start of match optimizations ---------------- */
+
+ /* There are some optimizations that avoid running the match if a known
+ starting point is not found, or if a known later code unit is not present.
+ However, there is an option (settable at compile time) that disables
+ these, for testing and for ensuring that all callouts do actually occur.
+ The optimizations must also be avoided when restarting a DFA match. */
+
+ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 &&
+ (options & PCRE2_DFA_RESTART) == 0)
{
- const pcre_uchar *save_end_subject = end_subject;
+ PCRE2_SPTR 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. */
+ 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 the optimization scans 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
+ PCRE2_SPTR t = start_match;
+#ifdef SUPPORT_UNICODE
if (utf)
{
- while (t < md->end_subject && !IS_NEWLINE(t))
+ while (t < mb->end_subject && !IS_NEWLINE(t))
{
t++;
ACROSSCHAR(t < end_subject, *t, t++);
@@ -3455,82 +3411,71 @@ for (;;)
}
else
#endif
- while (t < md->end_subject && !IS_NEWLINE(t)) t++;
+ while (t < mb->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. */
+ /* Advance to a unique first code unit if there is one. */
- if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
+ if (has_first_cu)
{
- /* Advance to a known first pcre_uchar (i.e. data item) */
-
- if (has_first_char)
- {
- if (first_char != first_char2)
- {
- pcre_uchar csc;
- while (current_subject < end_subject &&
- (csc = UCHAR21TEST(current_subject)) != first_char && csc != first_char2)
- current_subject++;
- }
- else
- while (current_subject < end_subject &&
- UCHAR21TEST(current_subject) != first_char)
- current_subject++;
- }
+ PCRE2_UCHAR smc;
+ if (first_cu != first_cu2)
+ while (start_match < end_subject &&
+ (smc = UCHAR21TEST(start_match)) != first_cu && smc != first_cu2)
+ start_match++;
+ else
+ while (start_match < end_subject && UCHAR21TEST(start_match) != first_cu)
+ start_match++;
+ }
- /* Or to just after a linebreak for a multiline match if possible */
+ /* Or to just after a linebreak for a multiline match */
- else if (startline)
+ else if (startline)
+ {
+ if (start_match > mb->start_subject + start_offset)
{
- if (current_subject > md->start_subject + start_offset)
+#ifdef SUPPORT_UNICODE
+ if (utf)
{
-#ifdef SUPPORT_UTF
- if (utf)
+ while (start_match < end_subject && !WAS_NEWLINE(start_match))
{
- while (current_subject < end_subject &&
- !WAS_NEWLINE(current_subject))
- {
- current_subject++;
- ACROSSCHAR(current_subject < end_subject, *current_subject,
- current_subject++);
- }
+ start_match++;
+ ACROSSCHAR(start_match < end_subject, *start_match,
+ start_match++);
}
- 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 (UCHAR21TEST(current_subject - 1) == CHAR_CR &&
- (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
- current_subject < end_subject &&
- UCHAR21TEST(current_subject) == CHAR_NL)
- current_subject++;
}
+ else
+#endif
+ while (start_match < end_subject && !WAS_NEWLINE(start_match))
+ start_match++;
+
+ /* If we have just passed a CR and the newline option is ANY or
+ ANYCRLF, and we are now at a LF, advance the match position by one more
+ code unit. */
+
+ if (start_match[-1] == CHAR_CR &&
+ (mb->nltype == NLTYPE_ANY || mb->nltype == NLTYPE_ANYCRLF) &&
+ start_match < end_subject &&
+ UCHAR21TEST(start_match) == CHAR_NL)
+ start_match++;
}
+ }
- /* Advance to a non-unique first pcre_uchar after study */
+ /* Or to a non-unique first code unit if any have been identified. The
+ bitmap contains only 256 bits. When code units are 16 or 32 bits wide, all
+ code units greater than 254 set the 255 bit. */
- else if (start_bits != NULL)
+ else if (start_bits != NULL)
+ {
+ while (start_match < end_subject)
{
- while (current_subject < end_subject)
- {
- register pcre_uint32 c = UCHAR21TEST(current_subject);
-#ifndef COMPILE_PCRE8
- if (c > 255) c = 255;
+ register uint32_t c = UCHAR21TEST(start_match);
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ if (c > 255) c = 255;
#endif
- if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
- current_subject++;
- }
+ if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
+ start_match++;
}
}
@@ -3538,137 +3483,142 @@ for (;;)
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). */
+ /* The following two optimizations are disabled for partial matching. */
- if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 &&
- (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0)
+ if ((mb->moptions & (PCRE2_PARTIAL_HARD|PCRE2_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
- in pcre_uchar units to avoid spending too much time in this optimization.
- */
+ /* The minimum matching length is a lower bound; no actual string of that
+ length may actually match the pattern. Although the value is, strictly,
+ in characters, we treat it as code units to avoid spending too much time
+ in this optimization. */
- if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 &&
- (pcre_uint32)(end_subject - current_subject) < study->minlength)
- return PCRE_ERROR_NOMATCH;
+ if (end_subject - start_match < re->minlength) return PCRE2_ERROR_NOMATCH;
- /* If req_char is set, we know that that pcre_uchar must appear in the
- subject for the match to succeed. If the first pcre_uchar 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.
+ /* If req_cu is set, we know that that code unit must appear in the
+ subject for the match to succeed. If the first code unit is set, req_cu
+ must be later in the subject; otherwise the test starts at the match
+ point. This optimization can save a huge amount of backtracking in
+ patterns with nested unlimited repeats that aren't going to match.
+ Writing separate code for cased/caseless versions makes it go faster, as
+ does using an autoincrement and backing off on a match.
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. */
+ 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 - current_subject < REQ_BYTE_MAX)
+ if (has_req_cu && end_subject - start_match < REQ_CU_MAX)
{
- register PCRE_PUCHAR p = current_subject + (has_first_char? 1:0);
+ register PCRE2_SPTR p = start_match + (has_first_cu? 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 (p > req_cu_ptr)
{
- if (req_char != req_char2)
+ if (req_cu != req_cu2)
{
while (p < end_subject)
{
- register pcre_uint32 pp = UCHAR21INCTEST(p);
- if (pp == req_char || pp == req_char2) { p--; break; }
+ register uint32_t pp = UCHAR21INCTEST(p);
+ if (pp == req_cu || pp == req_cu2) { p--; break; }
}
}
else
{
while (p < end_subject)
{
- if (UCHAR21INCTEST(p) == req_char) { p--; break; }
+ if (UCHAR21INCTEST(p) == req_cu) { p--; break; }
}
}
- /* If we can't find the required pcre_uchar, break the matching loop,
- which will cause a return or PCRE_ERROR_NOMATCH. */
+ /* If we can't find the required code unit, break the matching loop,
+ forcing a match failure. */
if (p >= end_subject) break;
- /* If we have found the required pcre_uchar, save the point where we
+ /* If we have found the required code unit, save the point where we
found it, so that we don't search again next time round the loop if
- the start hasn't passed this point yet. */
+ the start hasn't passed this code unit yet. */
- req_char_ptr = p;
+ req_cu_ptr = p;
}
}
}
- } /* End of optimizations that are done when not restarting */
+ }
- /* OK, now we can do the business */
+ /* ------------ End of start of match optimizations ------------ */
+
+ /* Give no match if we have passed the bumpalong limit. */
- md->start_used_ptr = current_subject;
- md->recursive = NULL;
+ if (start_match > bumpalong_limit) break;
- 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 */
+ /* OK, now we can do the business */
+
+ mb->start_used_ptr = start_match;
+ mb->last_used_ptr = start_match;
+ mb->recursive = NULL;
+
+ rc = internal_dfa_match(
+ mb, /* fixed match data */
+ mb->start_code, /* this subexpression's code */
+ start_match, /* where we currently are */
+ start_offset, /* start offset in subject */
+ match_data->ovector, /* offset vector */
+ (uint32_t)match_data->oveccount * 2, /* actual size of same */
+ workspace, /* workspace vector */
+ (int)wscount, /* size of same */
+ 0); /* function recurse level */
/* Anything other than "no match" means we are done, always; otherwise, carry
on only if not anchored. */
- if (rc != PCRE_ERROR_NOMATCH || anchored)
+ if (rc != PCRE2_ERROR_NOMATCH || anchored)
{
- if (rc == PCRE_ERROR_PARTIAL && offsetcount >= 2)
+ if (rc == PCRE2_ERROR_PARTIAL && match_data->oveccount > 0)
{
- offsets[0] = (int)(md->start_used_ptr - (PCRE_PUCHAR)subject);
- offsets[1] = (int)(end_subject - (PCRE_PUCHAR)subject);
- if (offsetcount > 2)
- offsets[2] = (int)(current_subject - (PCRE_PUCHAR)subject);
+ match_data->ovector[0] = (PCRE2_SIZE)(start_match - subject);
+ match_data->ovector[1] = (PCRE2_SIZE)(end_subject - subject);
}
+ match_data->leftchar = (PCRE2_SIZE)(mb->start_used_ptr - subject);
+ match_data->rightchar = (PCRE2_SIZE)( mb->last_used_ptr - subject);
+ match_data->startchar = (PCRE2_SIZE)(start_match - subject);
+ match_data->rc = rc;
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 (firstline && IS_NEWLINE(start_match)) break;
+ start_match++;
+#ifdef SUPPORT_UNICODE
if (utf)
{
- ACROSSCHAR(current_subject < end_subject, *current_subject,
- current_subject++);
+ ACROSSCHAR(start_match < end_subject, *start_match,
+ start_match++);
}
#endif
- if (current_subject > end_subject) break;
+ if (start_match > end_subject) break;
/* If we have just passed a CR and we are now at a LF, and the pattern does
not contain any explicit matches for \r or \n, and the newline option is CRLF
or ANY or ANYCRLF, advance the match position by one more character. */
- if (UCHAR21TEST(current_subject - 1) == CHAR_CR &&
- current_subject < end_subject &&
- UCHAR21TEST(current_subject) == CHAR_NL &&
- (re->flags & PCRE_HASCRORLF) == 0 &&
- (md->nltype == NLTYPE_ANY ||
- md->nltype == NLTYPE_ANYCRLF ||
- md->nllen == 2))
- current_subject++;
+ if (UCHAR21TEST(start_match - 1) == CHAR_CR &&
+ start_match < end_subject &&
+ UCHAR21TEST(start_match) == CHAR_NL &&
+ (re->flags & PCRE2_HASCRORLF) == 0 &&
+ (mb->nltype == NLTYPE_ANY ||
+ mb->nltype == NLTYPE_ANYCRLF ||
+ mb->nllen == 2))
+ start_match++;
} /* "Bumpalong" loop */
-return PCRE_ERROR_NOMATCH;
+
+return PCRE2_ERROR_NOMATCH;
}
-/* End of pcre_dfa_exec.c */
+/* End of pcre2_dfa_match.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_error.c b/src/3rdparty/pcre2/src/pcre2_error.c
new file mode 100644
index 0000000000..77fd5f4124
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_error.c
@@ -0,0 +1,322 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre2_internal.h"
+
+#define STRING(a) # a
+#define XSTRING(s) STRING(s)
+
+/* The texts of compile-time error messages. Compile-time error numbers start
+at COMPILE_ERROR_BASE (100).
+
+This used to be a table of strings, but in order to reduce the number of
+relocations needed when a shared library is loaded dynamically, it is now one
+long string. We cannot use a table of offsets, because the lengths of inserts
+such as XSTRING(MAX_NAME_SIZE) are not known. Instead,
+pcre2_get_error_message() counts through to the one it wants - this isn't a
+performance issue because these strings are used only when there is an error.
+
+Each substring ends with \0 to insert a null character. This includes the final
+substring, so that the whole string ends with \0\0, which can be detected when
+counting through. */
+
+static const unsigned char compile_error_texts[] =
+ "no error\0"
+ "\\ at end of pattern\0"
+ "\\c at end of pattern\0"
+ "unrecognized character follows \\\0"
+ "numbers out of order in {} quantifier\0"
+ /* 5 */
+ "number too big in {} quantifier\0"
+ "missing terminating ] for character class\0"
+ "invalid escape sequence in character class\0"
+ "range out of order in character class\0"
+ "quantifier does not follow a repeatable item\0"
+ /* 10 */
+ "internal error: unexpected repeat\0"
+ "unrecognized character after (? or (?-\0"
+ "POSIX named classes are supported only within a class\0"
+ "POSIX collating elements are not supported\0"
+ "missing closing parenthesis\0"
+ /* 15 */
+ "reference to non-existent subpattern\0"
+ "pattern passed as NULL\0"
+ "unrecognised compile-time option bit(s)\0"
+ "missing ) after (?# comment\0"
+ "parentheses are too deeply nested\0"
+ /* 20 */
+ "regular expression is too large\0"
+ "failed to allocate heap memory\0"
+ "unmatched closing parenthesis\0"
+ "internal error: code overflow\0"
+ "letter or underscore expected after (?< or (?'\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 (?( or (?(?C)\0"
+ "(?R or (?[+-]digits must be followed by )\0"
+ /* 30 */
+ "unknown POSIX class name\0"
+ "internal error in pcre2_study(): should not occur\0"
+ "this version of PCRE2 does not have Unicode support\0"
+ "parentheses are too deeply nested (stack check)\0"
+ "character code point value in \\x{} or \\o{} is too large\0"
+ /* 35 */
+ "invalid condition (?(0)\0"
+ "\\C is not allowed in a lookbehind assertion in UTF-" XSTRING(PCRE2_CODE_UNIT_WIDTH) " mode\0"
+ "PCRE does not support \\L, \\l, \\N{name}, \\U, or \\u\0"
+ "number after (?C is greater than 255\0"
+ "closing parenthesis for (?C expected\0"
+ /* 40 */
+ "invalid escape sequence in (*VERB) name\0"
+ "unrecognized character after (?P\0"
+ "syntax error in subpattern name (missing terminator)\0"
+ "two named subpatterns have the same name (PCRE2_DUPNAMES not set)\0"
+ "group name must start with a non-digit\0"
+ /* 45 */
+ "this version of PCRE2 does not have support for \\P, \\p, or \\X\0"
+ "malformed \\P or \\p sequence\0"
+ "unknown property name after \\P or \\p\0"
+ "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " characters)\0"
+ "too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")\0"
+ /* 50 */
+ "invalid range in character class\0"
+ "octal value is greater than \\377 in 8-bit non-UTF-8 mode\0"
+ "internal error: overran compiling workspace\0"
+ "internal error: previously-checked referenced subpattern not found\0"
+ "DEFINE group contains more than one branch\0"
+ /* 55 */
+ "missing opening brace after \\o\0"
+ "internal error: unknown newline setting\0"
+ "\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number\0"
+ "a numbered reference must not be zero\0"
+ "an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)\0"
+ /* 60 */
+ "(*VERB) not recognized or malformed\0"
+ "number is too big\0"
+ "subpattern name expected\0"
+ "digit expected after (?+\0"
+ "non-octal character in \\o{} (closing brace missing?)\0"
+ /* 65 */
+ "different names for subpatterns of the same number are not allowed\0"
+ "(*MARK) must have an argument\0"
+ "non-hex character in \\x{} (closing brace missing?)\0"
+#ifndef EBCDIC
+ "\\c must be followed by a printable ASCII character\0"
+#else
+ "\\c must be followed by a letter or one of [\\]^_?\0"
+#endif
+ "\\k is not followed by a braced, angle-bracketed, or quoted name\0"
+ /* 70 */
+ "internal error: unknown opcode in find_fixedlength()\0"
+ "\\N is not supported in a class\0"
+ "SPARE ERROR\0"
+ "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)\0"
+ "using UTF is disabled by the application\0"
+ /* 75 */
+ "using UCP is disabled by the application\0"
+ "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)\0"
+ "character code point value in \\u.... sequence is too large\0"
+ "digits missing in \\x{} or \\o{}\0"
+ "syntax error in (?(VERSION condition\0"
+ /* 80 */
+ "internal error: unknown opcode in auto_possessify()\0"
+ "missing terminating delimiter for callout with string argument\0"
+ "unrecognized string delimiter follows (?C\0"
+ "using \\C is disabled by the application\0"
+ "(?| and/or (?J: or (?x: parentheses are too deeply nested\0"
+ /* 85 */
+ "using \\C is disabled in this PCRE2 library\0"
+ "regular expression is too complicated\0"
+ "lookbehind assertion is too long\0"
+ "pattern string is longer than the limit set by the application\0"
+ ;
+
+/* Match-time and UTF error texts are in the same format. */
+
+static const unsigned char match_error_texts[] =
+ "no error\0"
+ "no match\0"
+ "partial match\0"
+ "UTF-8 error: 1 byte missing at end\0"
+ "UTF-8 error: 2 bytes missing at end\0"
+ /* 5 */
+ "UTF-8 error: 3 bytes missing at end\0"
+ "UTF-8 error: 4 bytes missing at end\0"
+ "UTF-8 error: 5 bytes missing at end\0"
+ "UTF-8 error: byte 2 top bits not 0x80\0"
+ "UTF-8 error: byte 3 top bits not 0x80\0"
+ /* 10 */
+ "UTF-8 error: byte 4 top bits not 0x80\0"
+ "UTF-8 error: byte 5 top bits not 0x80\0"
+ "UTF-8 error: byte 6 top bits not 0x80\0"
+ "UTF-8 error: 5-byte character is not allowed (RFC 3629)\0"
+ "UTF-8 error: 6-byte character is not allowed (RFC 3629)\0"
+ /* 15 */
+ "UTF-8 error: code points greater than 0x10ffff are not defined\0"
+ "UTF-8 error: code points 0xd800-0xdfff are not defined\0"
+ "UTF-8 error: overlong 2-byte sequence\0"
+ "UTF-8 error: overlong 3-byte sequence\0"
+ "UTF-8 error: overlong 4-byte sequence\0"
+ /* 20 */
+ "UTF-8 error: overlong 5-byte sequence\0"
+ "UTF-8 error: overlong 6-byte sequence\0"
+ "UTF-8 error: isolated byte with 0x80 bit set\0"
+ "UTF-8 error: illegal byte (0xfe or 0xff)\0"
+ "UTF-16 error: missing low surrogate at end\0"
+ /* 25 */
+ "UTF-16 error: invalid low surrogate\0"
+ "UTF-16 error: isolated low surrogate\0"
+ "UTF-32 error: code points 0xd800-0xdfff are not defined\0"
+ "UTF-32 error: code points greater than 0x10ffff are not defined\0"
+ "bad data value\0"
+ /* 30 */
+ "patterns do not all use the same character tables\0"
+ "magic number missing\0"
+ "pattern compiled in wrong mode: 8/16/32-bit error\0"
+ "bad offset value\0"
+ "bad option value\0"
+ /* 35 */
+ "invalid replacement string\0"
+ "bad offset into UTF string\0"
+ "callout error code\0" /* Never returned by PCRE2 itself */
+ "invalid data in workspace for DFA restart\0"
+ "too much recursion for DFA matching\0"
+ /* 40 */
+ "backreference condition or recursion test is not supported for DFA matching\0"
+ "function is not supported for DFA matching\0"
+ "pattern contains an item that is not supported for DFA matching\0"
+ "workspace size exceeded in DFA matching\0"
+ "internal error - pattern overwritten?\0"
+ /* 45 */
+ "bad JIT option\0"
+ "JIT stack limit reached\0"
+ "match limit exceeded\0"
+ "no more memory\0"
+ "unknown substring\0"
+ /* 50 */
+ "non-unique substring name\0"
+ "NULL argument passed\0"
+ "nested recursion at the same subject position\0"
+ "recursion limit exceeded\0"
+ "requested value is not available\0"
+ /* 55 */
+ "requested value is not set\0"
+ "offset limit set without PCRE2_USE_OFFSET_LIMIT\0"
+ "bad escape sequence in replacement string\0"
+ "expected closing curly bracket in replacement string\0"
+ "bad substitution in replacement string\0"
+ /* 60 */
+ "match with end before start is not supported\0"
+ "too many replacements (more than INT_MAX)\0"
+ "bad serialized data\0"
+ ;
+
+
+/*************************************************
+* Return error message *
+*************************************************/
+
+/* This function copies an error message into a buffer whose units are of an
+appropriate width. Error numbers are positive for compile-time errors, and
+negative for match-time errors (except for UTF errors), but the numbers are all
+distinct.
+
+Arguments:
+ enumber error number
+ buffer where to put the message (zero terminated)
+ size size of the buffer
+
+Returns: length of message if all is well
+ negative on error
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_get_error_message(int enumber, PCRE2_UCHAR *buffer, size_t size)
+{
+const unsigned char *message;
+size_t i;
+int n;
+
+if (size == 0) return PCRE2_ERROR_NOMEMORY;
+
+if (enumber >= COMPILE_ERROR_BASE) /* Compile error */
+ {
+ message = compile_error_texts;
+ n = enumber - COMPILE_ERROR_BASE;
+ }
+else if (enumber < 0) /* Match or UTF error */
+ {
+ message = match_error_texts;
+ n = -enumber;
+ }
+else /* Invalid error number */
+ {
+ message = (unsigned char *)"\0"; /* Empty message list */
+ n = 1;
+ }
+
+for (; n > 0; n--)
+ {
+ while (*message++ != CHAR_NULL) {};
+ if (*message == CHAR_NULL) return PCRE2_ERROR_BADDATA;
+ }
+
+for (i = 0; *message != 0; i++)
+ {
+ if (i >= size - 1)
+ {
+ buffer[i] = 0; /* Terminate partial message */
+ return PCRE2_ERROR_NOMEMORY;
+ }
+ buffer[i] = *message++;
+ }
+
+buffer[i] = 0;
+return (int)i;
+}
+
+/* End of pcre2_error.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_find_bracket.c b/src/3rdparty/pcre2/src/pcre2_find_bracket.c
new file mode 100644
index 0000000000..803e719765
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_find_bracket.c
@@ -0,0 +1,218 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+/* This module contains a single function that scans through a compiled pattern
+until it finds a capturing bracket with the given number, or, if the number is
+negative, an instance of OP_REVERSE for a lookbehind. The function is called
+from pcre2_compile.c and also from pcre2_study.c when finding the minimum
+matching length. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre2_internal.h"
+
+
+/*************************************************
+* Scan compiled regex for specific bracket *
+*************************************************/
+
+/*
+Arguments:
+ code points to start of expression
+ utf TRUE in UTF mode
+ number the required bracket number or negative to find a lookbehind
+
+Returns: pointer to the opcode for the bracket, or NULL if not found
+*/
+
+PCRE2_SPTR
+PRIV(find_bracket)(PCRE2_SPTR code, BOOL utf, int number)
+{
+for (;;)
+ {
+ register PCRE2_UCHAR c = *code;
+
+ if (c == OP_END) return NULL;
+
+ /* XCLASS is used for classes that cannot be represented just by a bit map.
+ This includes negated single high-valued characters. CALLOUT_STR is used for
+ callouts with string arguments. In both cases the length in the table is
+ zero; the actual length is stored in the compiled code. */
+
+ if (c == OP_XCLASS) code += GET(code, 1);
+ else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE);
+
+ /* Handle lookbehind */
+
+ else if (c == OP_REVERSE)
+ {
+ if (number < 0) return (PCRE2_UCHAR *)code;
+ code += PRIV(OP_lengths)[c];
+ }
+
+ /* Handle capturing bracket */
+
+ else if (c == OP_CBRA || c == OP_SCBRA ||
+ c == OP_CBRAPOS || c == OP_SCBRAPOS)
+ {
+ int n = (int)GET2(code, 1+LINK_SIZE);
+ if (n == number) return (PCRE2_UCHAR *)code;
+ code += PRIV(OP_lengths)[c];
+ }
+
+ /* Otherwise, we can get the item's length from the table, except that for
+ repeated character types, we have to test for \p and \P, which have an extra
+ two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we
+ must add in its length. */
+
+ else
+ {
+ switch(c)
+ {
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEPOSQUERY:
+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
+ break;
+
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEEXACT:
+ case OP_TYPEPOSUPTO:
+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
+ code += 2;
+ break;
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ code += code[1];
+ break;
+ }
+
+ /* Add in the fixed length from the table */
+
+ code += PRIV(OP_lengths)[c];
+
+ /* In UTF-8 and UTF-16 modes, opcodes that are followed by a character may be
+ followed by a multi-byte character. The length in the table is a minimum, so
+ we have to arrange to skip the extra bytes. */
+
+#ifdef MAYBE_UTF_MULTI
+ if (utf) switch(c)
+ {
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+ case OP_EXACT:
+ case OP_EXACTI:
+ case OP_NOTEXACT:
+ case OP_NOTEXACTI:
+ case OP_UPTO:
+ case OP_UPTOI:
+ case OP_NOTUPTO:
+ case OP_NOTUPTOI:
+ case OP_MINUPTO:
+ case OP_MINUPTOI:
+ case OP_NOTMINUPTO:
+ case OP_NOTMINUPTOI:
+ case OP_POSUPTO:
+ case OP_POSUPTOI:
+ case OP_NOTPOSUPTO:
+ case OP_NOTPOSUPTOI:
+ case OP_STAR:
+ case OP_STARI:
+ case OP_NOTSTAR:
+ case OP_NOTSTARI:
+ case OP_MINSTAR:
+ case OP_MINSTARI:
+ case OP_NOTMINSTAR:
+ case OP_NOTMINSTARI:
+ case OP_POSSTAR:
+ case OP_POSSTARI:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSSTARI:
+ case OP_PLUS:
+ case OP_PLUSI:
+ case OP_NOTPLUS:
+ case OP_NOTPLUSI:
+ case OP_MINPLUS:
+ case OP_MINPLUSI:
+ case OP_NOTMINPLUS:
+ case OP_NOTMINPLUSI:
+ case OP_POSPLUS:
+ case OP_POSPLUSI:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSPLUSI:
+ case OP_QUERY:
+ case OP_QUERYI:
+ case OP_NOTQUERY:
+ case OP_NOTQUERYI:
+ case OP_MINQUERY:
+ case OP_MINQUERYI:
+ case OP_NOTMINQUERY:
+ case OP_NOTMINQUERYI:
+ case OP_POSQUERY:
+ case OP_POSQUERYI:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSQUERYI:
+ if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]);
+ break;
+ }
+#else
+ (void)(utf); /* Keep compiler happy by referencing function argument */
+#endif /* MAYBE_UTF_MULTI */
+ }
+ }
+}
+
+/* End of pcre2_find_bracket.c */
diff --git a/src/3rdparty/pcre/pcre_internal.h b/src/3rdparty/pcre2/src/pcre2_internal.h
index 2923b29f82..56908708aa 100644
--- a/src/3rdparty/pcre/pcre_internal.h
+++ b/src/3rdparty/pcre2/src/pcre2_internal.h
@@ -2,12 +2,12 @@
* Perl-Compatible Regular Expressions *
*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
+/* PCRE2 is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2016 University of Cambridge
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -38,72 +38,17 @@ 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_", "_pcre16_" or "_pcre32_"
-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. */
-
-#if !defined COMPILE_PCRE16 && !defined COMPILE_PCRE32
-#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/32 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_UTF 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...
+/* We do not support both EBCDIC and Unicode at the same time. The "configure"
+script prevents both being selected, but not everybody uses "configure". EBCDIC
+is only supported for the 8-bit library, but the check for this has to be later
+in this file, because the first part is not width-dependent, and is included by
+pcre2test.c with CODE_UNIT_WIDTH == 0. */
-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 */
+#if defined EBCDIC && defined SUPPORT_UNICODE
+#error The use of both EBCDIC and SUPPORT_UNICODE is not supported.
#endif
-
-/* Standard C headers plus the external interface definition. The only time
-setjmp and stdarg are used is when NO_RECURSE is set. */
+/* Standard C headers */
#include <ctype.h>
#include <limits.h>
@@ -112,65 +57,91 @@ setjmp and stdarg are used is when NO_RECURSE is set. */
#include <stdlib.h>
#include <string.h>
+/* Macros to make boolean values more obvious. The #ifndef is to pacify
+compiler warnings in environments where these macros are defined elsewhere.
+Unfortunately, there is no way to do the same for the typedef. */
+
+typedef int BOOL;
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
/* Valgrind (memcheck) support */
#ifdef SUPPORT_VALGRIND
#include <valgrind/memcheck.h>
#endif
+/* Older versions of MSVC lack snprintf(). This define allows for
+warning/error-free compilation and testing with MSVC compilers back to at least
+MSVC 10/2010. Except for VC6 (which is missing some fundamentals and fails). */
+
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+#define snprintf _snprintf
+#endif
+
/* When compiling a DLL for Windows, the exported symbols have to be declared
using some MS magic. I found some useful information on this web page:
http://msdn2.microsoft.com/en-us/library/y4h7bcy6(VS.80).aspx. According to the
information there, using __declspec(dllexport) without "extern" we have a
definition; with "extern" we have a declaration. The settings here override the
-setting in pcre.h (which is included below); it defines only PCRE_EXP_DECL,
+setting in pcre2.h (which is included below); it defines only PCRE2_EXP_DECL,
which is all that is needed for applications (they just import the symbols). We
use:
- 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.
+ PCRE2_EXP_DECL for declarations
+ PCRE2_EXP_DEFN for definitions
-The reason for wrapping this in #ifndef PCRE_EXP_DECL is so that pcretest,
+The reason for wrapping this in #ifndef PCRE2_EXP_DECL is so that pcre2test,
which is an application, but needs to import this file in order to "peek" at
-internals, can #include pcre.h first to get an application's-eye view.
+internals, can #include pcre2.h first to get an application's-eye view.
In principle, people compiling for non-Windows, non-Unix-like (i.e. uncommon,
special-purpose environments) might want to stick other stuff in front of
-exported symbols. That's why, in the non-Windows case, we set PCRE_EXP_DEFN and
-PCRE_EXP_DATA_DEFN only if they are not already set. */
+exported symbols. That's why, in the non-Windows case, we set PCRE2_EXP_DEFN
+only if it is not already set. */
-#ifndef PCRE_EXP_DECL
+#ifndef PCRE2_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)
+# ifndef PCRE2_STATIC
+# define PCRE2_EXP_DECL extern __declspec(dllexport)
+# define PCRE2_EXP_DEFN __declspec(dllexport)
# else
-# define PCRE_EXP_DECL extern
-# define PCRE_EXP_DEFN
-# define PCRE_EXP_DATA_DEFN
+# define PCRE2_EXP_DECL extern
+# define PCRE2_EXP_DEFN
# endif
# else
# ifdef __cplusplus
-# define PCRE_EXP_DECL extern "C"
+# define PCRE2_EXP_DECL extern "C"
# else
-# define PCRE_EXP_DECL extern
+# define PCRE2_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
+# ifndef PCRE2_EXP_DEFN
+# define PCRE2_EXP_DEFN PCRE2_EXP_DECL
# endif
# endif
#endif
+/* Include the public PCRE2 header and the definitions of UCP character
+property values. This must follow the setting of PCRE2_EXP_DECL above. */
+
+#include "pcre2.h"
+#include "pcre2_ucp.h"
+
+/* When PCRE2 is compiled as a C++ library, the subject pointer can be replaced
+with a custom type. This makes it possible, for example, to allow pcre2_match()
+to process subject strings that are discontinuous by using a smart pointer
+class. It must always be possible to inspect all of the subject string in
+pcre2_match() because of the way it backtracks. */
+
+/* WARNING: This is as yet untested for PCRE2. */
+
+#ifdef CUSTOM_SUBJECT_PTR
+#undef PCRE2_SPTR
+#define PCRE2_SPTR CUSTOM_SUBJECT_PTR
+#endif
+
/* When 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
@@ -178,50 +149,14 @@ 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
+PCRE2_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
+#ifndef PCRE2_CALL_CONVENTION
+#define PCRE2_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;
-#define PCRE_UINT16_MAX USHRT_MAX
-#define PCRE_INT16_MAX SHRT_MAX
-#elif UINT_MAX == 65535
-typedef unsigned int pcre_uint16;
-typedef int pcre_int16;
-#define PCRE_UINT16_MAX UINT_MAX
-#define PCRE_INT16_MAX INT_MAX
-#else
-#error Cannot determine a type for 16-bit integers
-#endif
-
-#if UINT_MAX == 4294967295U
-typedef unsigned int pcre_uint32;
-typedef int pcre_int32;
-#define PCRE_UINT32_MAX UINT_MAX
-#define PCRE_INT32_MAX INT_MAX
-#elif ULONG_MAX == 4294967295UL
-typedef unsigned long int pcre_uint32;
-typedef long int pcre_int32;
-#define PCRE_UINT32_MAX ULONG_MAX
-#define PCRE_INT32_MAX LONG_MAX
-#else
-#error Cannot determine a type for 32-bit integers
-#endif
-
-/* When checking for integer overflow in pcre_compile(), we need to handle
+/* When checking for integer overflow in pcre2_compile(), we need to handle
large integers. If a 64-bit integer type is available, we can use that.
Otherwise we have to cast to double, which of course requires floating point
arithmetic. Handle this by defining a macro for the appropriate type. If
@@ -241,128 +176,8 @@ by "configure". */
#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.
-*/
-
-#if defined 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])
-
-#elif defined 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 UCHAR_SHIFT (1)
-#define IN_UCHARS(x) ((x) * 2)
-#define MAX_255(c) ((c) <= 255u)
-#define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default))
-
-#elif defined COMPILE_PCRE32
-
-typedef pcre_uint32 pcre_uchar;
-#define UCHAR_SHIFT (2)
-#define IN_UCHARS(x) ((x) * 4)
-#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_PCRE[8|16|32] */
-
-/* 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 && \
- UCHAR21TEST(p) == NLBLOCK->nl[0] && \
- (NLBLOCK->nllen == 1 || UCHAR21TEST(p+1) == NLBLOCK->nl[1]) \
- ) \
- )
-
-/* This macro checks for a newline immediately preceding the given position */
-
-#define WAS_NEWLINE(p) \
- ((NLBLOCK->nltype != NLTYPE_FIXED)? \
- ((p) > NLBLOCK->PSSTART && \
- PRIV(was_newline)((p), NLBLOCK->nltype, NLBLOCK->PSSTART, \
- &(NLBLOCK->nllen), utf)) \
- : \
- ((p) >= NLBLOCK->PSSTART + NLBLOCK->nllen && \
- UCHAR21TEST(p - NLBLOCK->nllen) == NLBLOCK->nl[0] && \
- (NLBLOCK->nllen == 1 || UCHAR21TEST(p - NLBLOCK->nllen + 1) == NLBLOCK->nl[1]) \
- ) \
- )
-
-/* 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"
-
-#ifdef COMPILE_PCRE32
-/* Assert that the public PCRE_UCHAR32 is a 32-bit type */
-typedef int __assert_pcre_uchar32_size[sizeof(PCRE_UCHAR32) == 4 ? 1 : -1];
-#endif
-
/* When compiling for use with the Virtual Pascal compiler, these functions
-need to have their names changed. PCRE must be compiled with the -DVPCOMPAT
+need to have their names changed. PCRE2 must be compiled with the -DVPCOMPAT
option on the command line. */
#ifdef VPCOMPAT
@@ -385,7 +200,7 @@ neither (there some non-Unix environments where this is the case). */
#define memmove(a, b, c) bcopy(b, a, c)
#else /* HAVE_BCOPY */
static void *
-pcre_memmove(void *d, const void *s, size_t n)
+pcre2_memmove(void *d, const void *s, size_t n)
{
size_t i;
unsigned char *dest = (unsigned char *)d;
@@ -403,249 +218,87 @@ else
return (void *)(dest - n);
}
}
-#define memmove(a, b, c) pcre_memmove(a, b, c)
+#define memmove(a, b, c) pcre2_memmove(a, b, c)
#endif /* not HAVE_BCOPY */
#endif /* not HAVE_MEMMOVE */
#endif /* not VPCOMPAT */
+/* External (in the C sense) functions and tables that are private to the
+libraries are always referenced using the PRIV macro. This makes it possible
+for pcre2test.c to include some of the source files from the libraries using a
+different PRIV definition to avoid name clashes. It also makes it clear in the
+code that a non-static object is being referenced. */
-/* 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. */
-
-#if defined 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
+#ifndef PRIV
+#define PRIV(name) _pcre2_##name
#endif
-#elif defined COMPILE_PCRE16
+/* This is an unsigned int value that no UTF character can ever have, as
+Unicode doesn't go beyond 0x0010ffff. */
-#if LINK_SIZE == 2
-
-/* Redefine LINK_SIZE as a multiple of sizeof(pcre_uchar) */
-#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)
+#define NOTACHAR 0xffffffff
-#elif LINK_SIZE == 3 || LINK_SIZE == 4
+/* This is the largest valid UTF/Unicode code point. */
-/* Redefine LINK_SIZE as a multiple of sizeof(pcre_uchar) */
-#undef LINK_SIZE
-#define LINK_SIZE 2
+#define MAX_UTF_CODE_POINT 0x10ffff
-#define PUT(a,n,d) \
- (a[n] = (d) >> 16), \
- (a[(n)+1] = (d) & 65535)
+/* Compile-time positive error numbers (all except UTF errors, which are
+negative) start at this value. It should probably never be changed, in case
+some application is checking for specific numbers. There is a copy of this
+#define in pcre2posix.c (which now no longer includes this file). Ideally, a
+way of having a single definition should be found, but as the number is
+unlikely to change, this is not a pressing issue. The original reason for
+having a base other than 0 was to keep the absolute values of compile-time and
+run-time error numbers numerically different, but in the event the code does
+not rely on this. */
-#define GET(a,n) \
- (((a)[n] << 16) | (a)[(n)+1])
+#define COMPILE_ERROR_BASE 100
-/* Keep it positive */
-#define MAX_PATTERN_SIZE (1 << 30)
+/* Define the default BSR convention. */
+#ifdef BSR_ANYCRLF
+#define BSR_DEFAULT PCRE2_BSR_ANYCRLF
#else
-#error LINK_SIZE must be either 2, 3, or 4
+#define BSR_DEFAULT PCRE2_BSR_UNICODE
#endif
-#elif defined COMPILE_PCRE32
-
-/* Only supported LINK_SIZE is 4 */
-/* Redefine LINK_SIZE as a multiple of sizeof(pcre_uchar) */
-#undef LINK_SIZE
-#define LINK_SIZE 1
-
-#define PUT(a,n,d) \
- (a[n] = (d))
-
-#define GET(a,n) \
- (a[n])
-
-/* Keep it positive */
-#define MAX_PATTERN_SIZE (1 << 30)
-
-#else
-#error Unsupported compiling mode
-#endif /* COMPILE_PCRE[8|16|32] */
-
-/* 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. */
-
-#if defined COMPILE_PCRE8
-
-#define IMM2_SIZE 2
-
-#define PUT2(a,n,d) \
- a[n] = (d) >> 8; \
- a[(n)+1] = (d) & 255
-
-/* For reasons that I do not understand, the expression in this GET2 macro is
-treated by gcc as a signed expression, even when a is declared as unsigned. It
-seems that any kind of arithmetic results in a signed value. */
-
-#define GET2(a,n) \
- (unsigned int)(((a)[n] << 8) | (a)[(n)+1])
-
-#elif defined COMPILE_PCRE16
-
-#define IMM2_SIZE 1
-
-#define PUT2(a,n,d) \
- a[n] = d
-
-#define GET2(a,n) \
- a[n]
-
-#elif defined COMPILE_PCRE32
-
-#define IMM2_SIZE 1
-
-#define PUT2(a,n,d) \
- a[n] = d
-#define GET2(a,n) \
- a[n]
+/* ---------------- Basic UTF-8 macros ---------------- */
-#else
-#error Unsupported compiling mode
-#endif /* COMPILE_PCRE[8|16|32] */
-
-#define PUT2INC(a,n,d) PUT2(a,n,d), a += IMM2_SIZE
+/* These UTF-8 macros are always defined because they are used in pcre2test for
+handling wide characters in 16-bit and 32-bit modes, even if an 8-bit library
+is not supported. */
-/* The maximum length of a MARK name is currently one data unit; it may be
-changed in future to be a fixed number of bytes or to depend on LINK_SIZE. */
-
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
-#define MAX_MARK ((1u << 16) - 1)
-#else
-#define MAX_MARK ((1u << 8) - 1)
-#endif
-
-/* There is a proposed future special "UTF-21" mode, in which only the lowest
-21 bits of a 32-bit character are interpreted as UTF, with the remaining 11
-high-order bits available to the application for other uses. In preparation for
-the future implementation of this mode, there are macros that load a data item
-and, if in this special mode, mask it to 21 bits. These macros all have names
-starting with UCHAR21. In all other modes, including the normal 32-bit
-library, the macros all have the same simple definitions. When the new mode is
-implemented, it is expected that these definitions will be varied appropriately
-using #ifdef when compiling the library that supports the special mode. */
-
-#define UCHAR21(eptr) (*(eptr))
-#define UCHAR21TEST(eptr) (*(eptr))
-#define UCHAR21INC(eptr) (*(eptr)++)
-#define UCHAR21INCTEST(eptr) (*(eptr)++)
-
-/* When UTF encoding is being used, a character is no longer just a single
-byte in 8-bit mode or a single short in 16-bit mode. The macros for character
-handling generate simple sequences when used in the basic mode, and more
-complicated ones for UTF characters. GETCHARLENTEST and other macros are not
-used when UTF is not supported. To make sure they can never even appear when
-UTF support is omitted, we don't even define them. */
-
-#ifndef SUPPORT_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 */
-
-/* Tests whether the code point needs extra characters to decode. */
+/* Tests whether a UTF-8 code point needs extra bytes to decode. */
#define HASUTF8EXTRALEN(c) ((c) >= 0xc0)
+/* The following macros were originally written in the form of loops that used
+data from the tables whose names start with PRIV(utf8_table). They were
+rewritten by a user so as not to use loops, because in some environments this
+gives a significant performance advantage, and it seems never to do any harm.
+*/
+
/* Base macro to pick up the remaining bytes of a UTF-8 character, not
advancing the pointer. */
#define GETUTF8(c, eptr) \
{ \
- if ((c & 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); \
+ if ((c & 0x20u) == 0) \
+ c = ((c & 0x1fu) << 6) | (eptr[1] & 0x3fu); \
+ else if ((c & 0x10u) == 0) \
+ c = ((c & 0x0fu) << 12) | ((eptr[1] & 0x3fu) << 6) | (eptr[2] & 0x3fu); \
+ else if ((c & 0x08u) == 0) \
+ c = ((c & 0x07u) << 18) | ((eptr[1] & 0x3fu) << 12) | \
+ ((eptr[2] & 0x3fu) << 6) | (eptr[3] & 0x3fu); \
+ else if ((c & 0x04u) == 0) \
+ c = ((c & 0x03u) << 24) | ((eptr[1] & 0x3fu) << 18) | \
+ ((eptr[2] & 0x3fu) << 12) | ((eptr[3] & 0x3fu) << 6) | \
+ (eptr[4] & 0x3fu); \
else \
- c = ((c & 0x01) << 30) | ((eptr[1] & 0x3f) << 24) | \
- ((eptr[2] & 0x3f) << 18) | ((eptr[3] & 0x3f) << 12) | \
- ((eptr[4] & 0x3f) << 6) | (eptr[5] & 0x3f); \
+ c = ((c & 0x01u) << 30) | ((eptr[1] & 0x3fu) << 24) | \
+ ((eptr[2] & 0x3fu) << 18) | ((eptr[3] & 0x3fu) << 12) | \
+ ((eptr[4] & 0x3fu) << 6) | (eptr[5] & 0x3fu); \
}
/* Base macro to pick up the remaining bytes of a UTF-8 character, advancing
@@ -653,315 +306,73 @@ the pointer. */
#define GETUTF8INC(c, eptr) \
{ \
- if ((c & 0x20) == 0) \
- c = ((c & 0x1f) << 6) | (*eptr++ & 0x3f); \
- else if ((c & 0x10) == 0) \
+ if ((c & 0x20u) == 0) \
+ c = ((c & 0x1fu) << 6) | (*eptr++ & 0x3fu); \
+ else if ((c & 0x10u) == 0) \
{ \
- c = ((c & 0x0f) << 12) | ((*eptr & 0x3f) << 6) | (eptr[1] & 0x3f); \
+ c = ((c & 0x0fu) << 12) | ((*eptr & 0x3fu) << 6) | (eptr[1] & 0x3fu); \
eptr += 2; \
} \
- else if ((c & 0x08) == 0) \
+ else if ((c & 0x08u) == 0) \
{ \
- c = ((c & 0x07) << 18) | ((*eptr & 0x3f) << 12) | \
- ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \
+ c = ((c & 0x07u) << 18) | ((*eptr & 0x3fu) << 12) | \
+ ((eptr[1] & 0x3fu) << 6) | (eptr[2] & 0x3fu); \
eptr += 3; \
} \
- else if ((c & 0x04) == 0) \
+ else if ((c & 0x04u) == 0) \
{ \
- c = ((c & 0x03) << 24) | ((*eptr & 0x3f) << 18) | \
- ((eptr[1] & 0x3f) << 12) | ((eptr[2] & 0x3f) << 6) | \
- (eptr[3] & 0x3f); \
+ c = ((c & 0x03u) << 24) | ((*eptr & 0x3fu) << 18) | \
+ ((eptr[1] & 0x3fu) << 12) | ((eptr[2] & 0x3fu) << 6) | \
+ (eptr[3] & 0x3fu); \
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); \
+ c = ((c & 0x01u) << 30) | ((*eptr & 0x3fu) << 24) | \
+ ((eptr[1] & 0x3fu) << 18) | ((eptr[2] & 0x3fu) << 12) | \
+ ((eptr[3] & 0x3fu) << 6) | (eptr[4] & 0x3fu); \
eptr += 5; \
} \
}
-#if defined 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)
-
-/* 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);
-
-/* 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) \
+ if ((c & 0x20u) == 0) \
{ \
- c = ((c & 0x1f) << 6) | (eptr[1] & 0x3f); \
+ c = ((c & 0x1fu) << 6) | (eptr[1] & 0x3fu); \
len++; \
} \
- else if ((c & 0x10) == 0) \
+ else if ((c & 0x10u) == 0) \
{ \
- c = ((c & 0x0f) << 12) | ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \
+ c = ((c & 0x0fu) << 12) | ((eptr[1] & 0x3fu) << 6) | (eptr[2] & 0x3fu); \
len += 2; \
} \
- else if ((c & 0x08) == 0) \
+ else if ((c & 0x08u) == 0) \
{\
- c = ((c & 0x07) << 18) | ((eptr[1] & 0x3f) << 12) | \
- ((eptr[2] & 0x3f) << 6) | (eptr[3] & 0x3f); \
+ c = ((c & 0x07u) << 18) | ((eptr[1] & 0x3fu) << 12) | \
+ ((eptr[2] & 0x3fu) << 6) | (eptr[3] & 0x3fu); \
len += 3; \
} \
- else if ((c & 0x04) == 0) \
+ else if ((c & 0x04u) == 0) \
{ \
- c = ((c & 0x03) << 24) | ((eptr[1] & 0x3f) << 18) | \
- ((eptr[2] & 0x3f) << 12) | ((eptr[3] & 0x3f) << 6) | \
- (eptr[4] & 0x3f); \
+ c = ((c & 0x03u) << 24) | ((eptr[1] & 0x3fu) << 18) | \
+ ((eptr[2] & 0x3fu) << 12) | ((eptr[3] & 0x3fu) << 6) | \
+ (eptr[4] & 0x3fu); \
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); \
+ c = ((c & 0x01u) << 30) | ((eptr[1] & 0x3fu) << 24) | \
+ ((eptr[2] & 0x3fu) << 18) | ((eptr[3] & 0x3fu) << 12) | \
+ ((eptr[4] & 0x3fu) << 6) | (eptr[5] & 0x3fu); \
len += 5; \
} \
}
-/* 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
-
-#elif defined 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
-
-#elif defined COMPILE_PCRE32
-
-/* These are trivial for the 32-bit library, since all UTF-32 characters fit
-into one pcre_uchar unit. */
-#define MAX_VALUE_FOR_SINGLE_CHAR (0x10ffffu)
-#define HAS_EXTRALEN(c) (0)
-#define GET_EXTRALEN(c) (0)
-#define NOT_FIRSTCHAR(c) (0)
-
-/* Get the next UTF-32 character, not advancing the pointer. This is called when
-we know we are in UTF-32 mode. */
-
-#define GETCHAR(c, eptr) \
- c = *(eptr);
-
-/* Get the next UTF-32 character, testing for UTF-32 mode, and not advancing the
-pointer. */
-
-#define GETCHARTEST(c, eptr) \
- c = *(eptr);
-
-/* Get the next UTF-32 character, advancing the pointer. This is called when we
-know we are in UTF-32 mode. */
-
-#define GETCHARINC(c, eptr) \
- c = *((eptr)++);
-
-/* Get the next character, testing for UTF-32 mode, and advancing the pointer.
-This is called when we don't know if we are in UTF-32 mode. */
-
-#define GETCHARINCTEST(c, eptr) \
- c = *((eptr)++);
-
-/* Get the next UTF-32 character, not advancing the pointer, not incrementing
-length (since all UTF-32 is of length 1). This is called when we know we are in
-UTF-32 mode. */
-
-#define GETCHARLEN(c, eptr, len) \
- GETCHAR(c, eptr)
-
-/* Get the next UTF-32character, testing for UTF-32 mode, not advancing the
-pointer, not incrementing the length (since all UTF-32 is of length 1).
-This is called when we do not know if we are in UTF-32 mode. */
-
-#define GETCHARLENTEST(c, eptr, len) \
- GETCHARTEST(c, eptr)
-
-/* If the pointer is not at the start of a character, move it back until
-it is. This is called only in UTF-32 mode - we don't put a test within the
-macro because almost all calls are already within a block of UTF-32 only
-code.
-These are all no-ops since all UTF-32 characters fit into one pcre_uchar. */
-
-#define BACKCHAR(eptr) do { } while (0)
-
-/* Same as above, just in the other direction. */
-#define FORWARDCHAR(eptr) do { } while (0)
-
-/* Same as above, but it allows a fully customizable form. */
-#define ACROSSCHAR(condition, eptr, action) do { } while (0)
-
-#else
-#error Unsupported compiling mode
-#endif /* COMPILE_PCRE[8|16|32] */
-
-#endif /* SUPPORT_UTF */
+/* --------------- Whitespace macros ---------------- */
/* Tests for Unicode horizontal and vertical whitespace characters must check a
number of different values. Using a switch statement for this generates the
@@ -970,19 +381,24 @@ interpreter code where this happens. In order to ensure that all the case lists
remain in step, we use macros so that there is only one place where the lists
are defined.
-These values are also required as lists in pcre_compile.c when processing \h,
-\H, \v and \V in a character class. The lists are defined in pcre_tables.c, but
-macros that define the values are here so that all the definitions are
+These values are also required as lists in pcre2_compile.c when processing \h,
+\H, \v and \V in a character class. The lists are defined in pcre2_tables.c,
+but macros that define the values are here so that all the definitions are
together. The lists must be in ascending character order, terminated by
NOTACHAR (which is 0xffffffff).
Any changes should ensure that the various macros are kept in step with each
-other. NOTE: The values also appear in pcre_jit_compile.c. */
+other. NOTE: The values also appear in pcre2_jit_compile.c. */
-/* ------ ASCII/Unicode environments ------ */
+/* -------------- ASCII/Unicode environments -------------- */
#ifndef EBCDIC
+/* Character U+180E (Mongolian Vowel Separator) is not included in the list of
+spaces in the Unicode file PropList.txt, and Perl does not recognize it as a
+space. However, in many other sources it is listed as a space and has been in
+PCRE (both APIs) for a long time. */
+
#define HSPACE_LIST \
CHAR_HT, CHAR_SPACE, CHAR_NBSP, \
0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, \
@@ -1034,7 +450,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */
VSPACE_BYTE_CASES: \
VSPACE_MULTIBYTE_CASES
-/* ------ EBCDIC environments ------ */
+/* -------------- EBCDIC environments -------------- */
#else
#define HSPACE_LIST CHAR_HT, CHAR_SPACE, CHAR_NBSP, NOTACHAR
@@ -1064,106 +480,129 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */
#define VSPACE_CASES VSPACE_BYTE_CASES
#endif /* EBCDIC */
-/* ------ End of whitespace macros ------ */
-
-
-
-/* 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 they were
-moved to a 16-bit flags word - which got almost full, so now they are in a
-32-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. */
-
-#define PCRE_MODE8 0x00000001 /* compiled in 8 bit mode */
-#define PCRE_MODE16 0x00000002 /* compiled in 16 bit mode */
-#define PCRE_MODE32 0x00000004 /* compiled in 32 bit mode */
-#define PCRE_FIRSTSET 0x00000010 /* first_char is set */
-#define PCRE_FCH_CASELESS 0x00000020 /* caseless first char */
-#define PCRE_REQCHSET 0x00000040 /* req_byte is set */
-#define PCRE_RCH_CASELESS 0x00000080 /* caseless requested char */
-#define PCRE_STARTLINE 0x00000100 /* start after \n for multiline */
-#define PCRE_NOPARTIAL 0x00000200 /* can't use partial with this regex */
-#define PCRE_JCHANGED 0x00000400 /* j option used in regex */
-#define PCRE_HASCRORLF 0x00000800 /* explicit \r or \n in pattern */
-#define PCRE_HASTHEN 0x00001000 /* pattern contains (*THEN) */
-#define PCRE_MLSET 0x00002000 /* match limit set by regex */
-#define PCRE_RLSET 0x00004000 /* recursion limit set by regex */
-#define PCRE_MATCH_EMPTY 0x00008000 /* pattern can match empty string */
-
-#if defined COMPILE_PCRE8
-#define PCRE_MODE PCRE_MODE8
-#elif defined COMPILE_PCRE16
-#define PCRE_MODE PCRE_MODE16
-#elif defined COMPILE_PCRE32
-#define PCRE_MODE PCRE_MODE32
-#endif
-#define PCRE_MODE_MASK (PCRE_MODE8 | PCRE_MODE16 | PCRE_MODE32)
-
-/* Flags for the "extra" block produced by pcre_study(). */
+/* -------------- End of whitespace macros -------------- */
-#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. */
+/* PCRE2 is able to support several different kinds of newline (CR, LF, CRLF,
+"any" and "anycrlf" at present). The following macros are used to package up
+testing for newlines. NLBLOCK, PSSTART, and PSEND are defined in the various
+modules to indicate in which datablock the parameters exist, and what the
+start/end of string field names are. */
-#define PCRE_NEWLINE_BITS (PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|PCRE_NEWLINE_ANY| \
- PCRE_NEWLINE_ANYCRLF)
+#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 */
-#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_AUTO_POSSESS| \
- 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|PCRE_NEVER_UTF)
+/* This macro checks for a newline at the given position */
-#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 IS_NEWLINE(p) \
+ ((NLBLOCK->nltype != NLTYPE_FIXED)? \
+ ((p) < NLBLOCK->PSEND && \
+ PRIV(is_newline)((p), NLBLOCK->nltype, NLBLOCK->PSEND, \
+ &(NLBLOCK->nllen), utf)) \
+ : \
+ ((p) <= NLBLOCK->PSEND - NLBLOCK->nllen && \
+ UCHAR21TEST(p) == NLBLOCK->nl[0] && \
+ (NLBLOCK->nllen == 1 || UCHAR21TEST(p+1) == NLBLOCK->nl[1]) \
+ ) \
+ )
-#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)
+/* This macro checks for a newline immediately preceding the given position */
-#define PUBLIC_STUDY_OPTIONS \
- (PCRE_STUDY_JIT_COMPILE|PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE| \
- PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE|PCRE_STUDY_EXTRA_NEEDED)
+#define WAS_NEWLINE(p) \
+ ((NLBLOCK->nltype != NLTYPE_FIXED)? \
+ ((p) > NLBLOCK->PSSTART && \
+ PRIV(was_newline)((p), NLBLOCK->nltype, NLBLOCK->PSSTART, \
+ &(NLBLOCK->nllen), utf)) \
+ : \
+ ((p) >= NLBLOCK->PSSTART + NLBLOCK->nllen && \
+ UCHAR21TEST(p - NLBLOCK->nllen) == NLBLOCK->nl[0] && \
+ (NLBLOCK->nllen == 1 || UCHAR21TEST(p - NLBLOCK->nllen + 1) == NLBLOCK->nl[1]) \
+ ) \
+ )
-#define PUBLIC_JIT_EXEC_OPTIONS \
- (PCRE_NO_UTF8_CHECK|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|\
- PCRE_NOTEMPTY_ATSTART|PCRE_PARTIAL_SOFT|PCRE_PARTIAL_HARD)
+/* Private flags containing information about the compiled pattern. The first
+three must not be changed, because whichever is set is actually the number of
+bytes in a code unit in that mode. */
+
+#define PCRE2_MODE8 0x00000001 /* compiled in 8 bit mode */
+#define PCRE2_MODE16 0x00000002 /* compiled in 16 bit mode */
+#define PCRE2_MODE32 0x00000004 /* compiled in 32 bit mode */
+#define PCRE2_FIRSTSET 0x00000010 /* first_code unit is set */
+#define PCRE2_FIRSTCASELESS 0x00000020 /* caseless first code unit */
+#define PCRE2_FIRSTMAPSET 0x00000040 /* bitmap of first code units is set */
+#define PCRE2_LASTSET 0x00000080 /* last code unit is set */
+#define PCRE2_LASTCASELESS 0x00000100 /* caseless last code unit */
+#define PCRE2_STARTLINE 0x00000200 /* start after \n for multiline */
+#define PCRE2_JCHANGED 0x00000400 /* j option used in pattern */
+#define PCRE2_HASCRORLF 0x00000800 /* explicit \r or \n in pattern */
+#define PCRE2_HASTHEN 0x00001000 /* pattern contains (*THEN) */
+#define PCRE2_MATCH_EMPTY 0x00002000 /* pattern can match empty string */
+#define PCRE2_BSR_SET 0x00004000 /* BSR was set in the pattern */
+#define PCRE2_NL_SET 0x00008000 /* newline was set in the pattern */
+#define PCRE2_NOTEMPTY_SET 0x00010000 /* (*NOTEMPTY) used ) keep */
+#define PCRE2_NE_ATST_SET 0x00020000 /* (*NOTEMPTY_ATSTART) used) together */
+#define PCRE2_DEREF_TABLES 0x00040000 /* release character tables */
+#define PCRE2_NOJIT 0x00080000 /* (*NOJIT) used */
+#define PCRE2_HASBKPORX 0x00100000 /* contains \P, \p, or \X */
+#define PCRE2_DUPCAPUSED 0x00200000 /* contains (?| */
+#define PCRE2_HASBKC 0x00400000 /* contains \C */
+
+#define PCRE2_MODE_MASK (PCRE2_MODE8 | PCRE2_MODE16 | PCRE2_MODE32)
+
+/* Values for the matchedby field in a match data block. */
+
+enum { PCRE2_MATCHEDBY_INTERPRETER, /* pcre2_match() */
+ PCRE2_MATCHEDBY_DFA_INTERPRETER, /* pcre2_dfa_match() */
+ PCRE2_MATCHEDBY_JIT }; /* pcre2_jit_match() */
/* 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. */
+/* The maximum remaining length of subject we are prepared to search for a
+req_unit match. */
-#define REVERSED_MAGIC_NUMBER 0x45524350UL /* 'ERCP' */
+#define REQ_CU_MAX 1000
-/* The maximum remaining length of subject we are prepared to search for a
-req_byte match. */
+/* Offsets for the bitmap tables in the cbits set of tables. Each table
+contains a set of bits for a class map. Some classes are built by combining
+these tables. */
-#define REQ_BYTE_MAX 1000
+#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 */
-/* 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. */
+/* Bit definitions for entries in the ctypes table. */
-typedef int BOOL;
+#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) */
-#ifndef FALSE
-#define FALSE 0
-#define TRUE 1
-#endif
+/* Offsets of the various tables from the base tables pointer, and
+total length of the tables. */
+
+#define lcc_offset 0 /* Lower case */
+#define fcc_offset 256 /* Flip case */
+#define cbits_offset 512 /* Character classes */
+#define ctypes_offset (cbits_offset + cbit_length) /* Character types */
+#define tables_length (ctypes_offset + 256)
-/* If PCRE is to support UTF-8 on EBCDIC platforms, we cannot use normal
+
+/* -------------------- Character and string names ------------------------ */
+
+/* If PCRE2 is to support UTF-8 on EBCDIC platforms, we cannot use normal
character constants like '*' because the compiler would emit their EBCDIC code,
which is different from their ASCII/UTF-8 code. Instead we define macros for
the characters so that they always use the ASCII/UTF-8 code when UTF-8 support
@@ -1171,19 +610,19 @@ 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
+This means that, on EBCDIC platforms, the PCRE2 library can handle either
EBCDIC, or UTF-8, but not both. To support both in the same compiled library
-would need different lookups depending on whether PCRE_UTF8 was set or not.
+would need different lookups depending on whether PCRE2_UTF was set or not.
This would make it impossible to use characters in switch/case statements,
which would reduce performance. For a theoretical use (which nobody has asked
for) in a minority area (EBCDIC platforms), this is not sensible. Any
application that did need both could compile two versions of the library, using
macros to give the functions distinct names. */
-#ifndef SUPPORT_UTF
+#ifndef SUPPORT_UNICODE
/* UTF-8 support is not enabled; use the platform-dependent character literals
-so that PCRE works in both ASCII and EBCDIC environments, but only in non-UTF
+so that PCRE2 works in both ASCII and EBCDIC environments, but only in non-UTF
mode. Newline characters are problematic in EBCDIC. Though it has CR and LF
characters, a common practice has been to use its NL (0x15) character as the
line terminator in C-like processing environments. However, sometimes the LF
@@ -1191,7 +630,7 @@ line terminator in C-like processing environments. However, sometimes the LF
http://unicode.org/standard/reports/tr13/tr13-5.html
-PCRE defaults EBCDIC NL to 0x15, but has a build-time option to select 0x25
+PCRE2 defaults EBCDIC NL to 0x15, but has a build-time option to select 0x25
instead. Whichever is *not* chosen is defined as NEL.
In both ASCII and EBCDIC environments, CHAR_NL and CHAR_LF are synonyms for the
@@ -1216,7 +655,7 @@ same code point. */
#define CHAR_ESC '\047'
#define CHAR_DEL '\007'
-#define CHAR_NBSP '\x41'
+#define CHAR_NBSP ((unsigned char)'\x41')
#define STR_ESC "\047"
#define STR_DEL "\007"
@@ -1475,27 +914,33 @@ a positive value. */
#define STRING_xdigit "xdigit"
#define STRING_DEFINE "DEFINE"
+#define STRING_VERSION "VERSION"
#define STRING_WEIRD_STARTWORD "[:<:]]"
#define STRING_WEIRD_ENDWORD "[:>:]]"
-#define STRING_CR_RIGHTPAR "CR)"
-#define STRING_LF_RIGHTPAR "LF)"
-#define STRING_CRLF_RIGHTPAR "CRLF)"
-#define STRING_ANY_RIGHTPAR "ANY)"
-#define STRING_ANYCRLF_RIGHTPAR "ANYCRLF)"
-#define STRING_BSR_ANYCRLF_RIGHTPAR "BSR_ANYCRLF)"
-#define STRING_BSR_UNICODE_RIGHTPAR "BSR_UNICODE)"
-#define STRING_UTF8_RIGHTPAR "UTF8)"
-#define STRING_UTF16_RIGHTPAR "UTF16)"
-#define STRING_UTF32_RIGHTPAR "UTF32)"
-#define STRING_UTF_RIGHTPAR "UTF)"
-#define STRING_UCP_RIGHTPAR "UCP)"
-#define STRING_NO_AUTO_POSSESS_RIGHTPAR "NO_AUTO_POSSESS)"
-#define STRING_NO_START_OPT_RIGHTPAR "NO_START_OPT)"
-#define STRING_LIMIT_MATCH_EQ "LIMIT_MATCH="
-#define STRING_LIMIT_RECURSION_EQ "LIMIT_RECURSION="
-
-#else /* SUPPORT_UTF */
+#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)"
+#define STRING_UTF8_RIGHTPAR "UTF8)"
+#define STRING_UTF16_RIGHTPAR "UTF16)"
+#define STRING_UTF32_RIGHTPAR "UTF32)"
+#define STRING_UTF_RIGHTPAR "UTF)"
+#define STRING_UCP_RIGHTPAR "UCP)"
+#define STRING_NO_AUTO_POSSESS_RIGHTPAR "NO_AUTO_POSSESS)"
+#define STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR "NO_DOTSTAR_ANCHOR)"
+#define STRING_NO_JIT_RIGHTPAR "NO_JIT)"
+#define STRING_NO_START_OPT_RIGHTPAR "NO_START_OPT)"
+#define STRING_NOTEMPTY_RIGHTPAR "NOTEMPTY)"
+#define STRING_NOTEMPTY_ATSTART_RIGHTPAR "NOTEMPTY_ATSTART)"
+#define STRING_LIMIT_MATCH_EQ "LIMIT_MATCH="
+#define STRING_LIMIT_RECURSION_EQ "LIMIT_RECURSION="
+#define STRING_MARK "MARK"
+
+#else /* SUPPORT_UNICODE */
/* UTF-8 support is enabled; always use UTF-8 (=ASCII) character codes. This
works in both modes non-EBCDIC platforms, and on EBCDIC platforms in UTF-8 mode
@@ -1742,56 +1187,37 @@ only. */
#define STRING_xdigit STR_x STR_d STR_i STR_g STR_i STR_t
#define STRING_DEFINE STR_D STR_E STR_F STR_I STR_N STR_E
+#define STRING_VERSION STR_V STR_E STR_R STR_S STR_I STR_O STR_N
#define STRING_WEIRD_STARTWORD STR_LEFT_SQUARE_BRACKET STR_COLON STR_LESS_THAN_SIGN STR_COLON STR_RIGHT_SQUARE_BRACKET STR_RIGHT_SQUARE_BRACKET
#define STRING_WEIRD_ENDWORD STR_LEFT_SQUARE_BRACKET STR_COLON STR_GREATER_THAN_SIGN STR_COLON STR_RIGHT_SQUARE_BRACKET STR_RIGHT_SQUARE_BRACKET
-#define STRING_CR_RIGHTPAR STR_C STR_R STR_RIGHT_PARENTHESIS
-#define STRING_LF_RIGHTPAR STR_L STR_F STR_RIGHT_PARENTHESIS
-#define STRING_CRLF_RIGHTPAR STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS
-#define STRING_ANY_RIGHTPAR STR_A STR_N STR_Y STR_RIGHT_PARENTHESIS
-#define STRING_ANYCRLF_RIGHTPAR STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS
-#define STRING_BSR_ANYCRLF_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS
-#define STRING_BSR_UNICODE_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_U STR_N STR_I STR_C STR_O STR_D STR_E STR_RIGHT_PARENTHESIS
-#define STRING_UTF8_RIGHTPAR STR_U STR_T STR_F STR_8 STR_RIGHT_PARENTHESIS
-#define STRING_UTF16_RIGHTPAR STR_U STR_T STR_F STR_1 STR_6 STR_RIGHT_PARENTHESIS
-#define STRING_UTF32_RIGHTPAR STR_U STR_T STR_F STR_3 STR_2 STR_RIGHT_PARENTHESIS
-#define STRING_UTF_RIGHTPAR STR_U STR_T STR_F STR_RIGHT_PARENTHESIS
-#define STRING_UCP_RIGHTPAR STR_U STR_C STR_P STR_RIGHT_PARENTHESIS
-#define STRING_NO_AUTO_POSSESS_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_A STR_U STR_T STR_O STR_UNDERSCORE STR_P STR_O STR_S STR_S STR_E STR_S STR_S STR_RIGHT_PARENTHESIS
-#define STRING_NO_START_OPT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_S STR_T STR_A STR_R STR_T STR_UNDERSCORE STR_O STR_P STR_T STR_RIGHT_PARENTHESIS
-#define STRING_LIMIT_MATCH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_M STR_A STR_T STR_C STR_H STR_EQUALS_SIGN
-#define STRING_LIMIT_RECURSION_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_R STR_E STR_C STR_U STR_R STR_S STR_I STR_O STR_N STR_EQUALS_SIGN
-
-#endif /* SUPPORT_UTF */
-
-/* Escape items that are just an encoding of a particular data value. */
-
-#ifndef ESC_a
-#define ESC_a CHAR_BEL
-#endif
-
-#ifndef ESC_e
-#define ESC_e CHAR_ESC
-#endif
-
-#ifndef ESC_f
-#define ESC_f CHAR_FF
-#endif
-
-#ifndef ESC_n
-#define ESC_n CHAR_LF
-#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
+#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
+#define STRING_UTF8_RIGHTPAR STR_U STR_T STR_F STR_8 STR_RIGHT_PARENTHESIS
+#define STRING_UTF16_RIGHTPAR STR_U STR_T STR_F STR_1 STR_6 STR_RIGHT_PARENTHESIS
+#define STRING_UTF32_RIGHTPAR STR_U STR_T STR_F STR_3 STR_2 STR_RIGHT_PARENTHESIS
+#define STRING_UTF_RIGHTPAR STR_U STR_T STR_F STR_RIGHT_PARENTHESIS
+#define STRING_UCP_RIGHTPAR STR_U STR_C STR_P STR_RIGHT_PARENTHESIS
+#define STRING_NO_AUTO_POSSESS_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_A STR_U STR_T STR_O STR_UNDERSCORE STR_P STR_O STR_S STR_S STR_E STR_S STR_S STR_RIGHT_PARENTHESIS
+#define STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_D STR_O STR_T STR_S STR_T STR_A STR_R STR_UNDERSCORE STR_A STR_N STR_C STR_H STR_O STR_R STR_RIGHT_PARENTHESIS
+#define STRING_NO_JIT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_J STR_I STR_T STR_RIGHT_PARENTHESIS
+#define STRING_NO_START_OPT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_S STR_T STR_A STR_R STR_T STR_UNDERSCORE STR_O STR_P STR_T STR_RIGHT_PARENTHESIS
+#define STRING_NOTEMPTY_RIGHTPAR STR_N STR_O STR_T STR_E STR_M STR_P STR_T STR_Y STR_RIGHT_PARENTHESIS
+#define STRING_NOTEMPTY_ATSTART_RIGHTPAR STR_N STR_O STR_T STR_E STR_M STR_P STR_T STR_Y STR_UNDERSCORE STR_A STR_T STR_S STR_T STR_A STR_R STR_T STR_RIGHT_PARENTHESIS
+#define STRING_LIMIT_MATCH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_M STR_A STR_T STR_C STR_H STR_EQUALS_SIGN
+#define STRING_LIMIT_RECURSION_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_R STR_E STR_C STR_U STR_R STR_S STR_I STR_O STR_N STR_EQUALS_SIGN
+#define STRING_MARK STR_M STR_A STR_R STR_K
+
+#endif /* SUPPORT_UNICODE */
+
+/* -------------------- End of character and string names -------------------*/
+
+/* -------------------- Definitions for compiled patterns -------------------*/
/* Codes for different types of Unicode property */
@@ -1809,7 +1235,7 @@ only. */
#define PT_TABSIZE 11 /* Size of square table for autopossessify tests */
/* The following special properties are used only in XCLASS items, when POSIX
-classes are specified and PCRE_UCP is set - in other words, for Unicode
+classes are specified and PCRE2_UCP is set - in other words, for Unicode
handling of these classes. They are not available via the \p or \P escapes like
those in the above list, and so they do not take part in the autopossessifying
table. */
@@ -1831,16 +1257,49 @@ contain characters with values greater than 255. */
#define XCL_PROP 3 /* Unicode property (2-byte property code follows) */
#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */
+/* Escape items that are just an encoding of a particular data value. These
+appear in the escapes[] table in pcre2_compile.c as positive numbers. */
+
+#ifndef ESC_a
+#define ESC_a CHAR_BEL
+#endif
+
+#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_LF
+#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
+
/* These are escaped items that aren't just an encoding of a particular data
value such as \n. They must have non-zero values, as check_escape() returns 0
-for a data character. 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.
+for a data character. In the escapes[] table in pcre2_compile.c their values
+are negated in order to distinguish them from data values.
+
+They must appear here in the same order as in the opcode definitions below, up
+to ESC_z. There's a dummy for OP_ALLANY because it corresponds to "." in DOTALL
+mode rather than an escape sequence. It is also used for [^] in JavaScript
+compatibility mode, and for \C in non-utf mode. In non-DOTALL mode, "." behaves
+like \N.
The special values ESC_DU, ESC_du, etc. are used instead of ESC_D, ESC_d, etc.
-when PCRE_UCP is set and replacement of \d etc by \p sequences is required.
+when PCRE2_UCP is set and 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.
@@ -1865,12 +1324,12 @@ enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s,
Starting from 1 (i.e. after OP_END), the values up to OP_EOD must correspond in
order to the list of escapes immediately above. Furthermore, values up to
OP_DOLLM must not be changed without adjusting the table called autoposstab in
-pcre_compile.c
+pcre2_auto_possess.c
Whenever this list is updated, the two macro definitions that follow must be
updated to match. The possessification table called "opcode_possessify" in
-pcre_compile.c must also be updated, and also the tables called "coptable"
-and "poptable" in pcre_dfa_exec.c.
+pcre2_compile.c must also be updated, and also the tables called "coptable"
+and "poptable" in pcre2_dfa_match.c.
****** NOTE NOTE NOTE ******/
@@ -2054,94 +1513,103 @@ enum {
OP_DNREFI, /* 116 Match a duplicate name backref, caselessly */
OP_RECURSE, /* 117 Match a numbered subpattern (possibly recursive) */
OP_CALLOUT, /* 118 Call out to external function if provided */
+ OP_CALLOUT_STR, /* 119 Call out with string argument */
- OP_ALT, /* 119 Start of alternation */
- OP_KET, /* 120 End of group that doesn't have an unbounded repeat */
- OP_KETRMAX, /* 121 These two must remain together and in this */
- OP_KETRMIN, /* 122 order. They are for groups the repeat for ever. */
- OP_KETRPOS, /* 123 Possessive unlimited repeat. */
+ OP_ALT, /* 120 Start of alternation */
+ OP_KET, /* 121 End of group that doesn't have an unbounded repeat */
+ OP_KETRMAX, /* 122 These two must remain together and in this */
+ OP_KETRMIN, /* 123 order. They are for groups the repeat for ever. */
+ OP_KETRPOS, /* 124 Possessive unlimited repeat. */
/* The assertions must come before BRA, CBRA, ONCE, and COND, and the four
asserts must remain in order. */
- OP_REVERSE, /* 124 Move pointer back - used in lookbehind assertions */
- OP_ASSERT, /* 125 Positive lookahead */
- OP_ASSERT_NOT, /* 126 Negative lookahead */
- OP_ASSERTBACK, /* 127 Positive lookbehind */
- OP_ASSERTBACK_NOT, /* 128 Negative lookbehind */
+ OP_REVERSE, /* 125 Move pointer back - used in lookbehind assertions */
+ OP_ASSERT, /* 126 Positive lookahead */
+ OP_ASSERT_NOT, /* 127 Negative lookahead */
+ OP_ASSERTBACK, /* 128 Positive lookbehind */
+ OP_ASSERTBACK_NOT, /* 129 Negative lookbehind */
/* 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, /* 129 Atomic group, contains captures */
- OP_ONCE_NC, /* 130 Atomic group containing no captures */
- OP_BRA, /* 131 Start of non-capturing bracket */
- OP_BRAPOS, /* 132 Ditto, with unlimited, possessive repeat */
- OP_CBRA, /* 133 Start of capturing bracket */
- OP_CBRAPOS, /* 134 Ditto, with unlimited, possessive repeat */
- OP_COND, /* 135 Conditional group */
+ OP_ONCE, /* 130 Atomic group, contains captures */
+ OP_ONCE_NC, /* 131 Atomic group containing no captures */
+ OP_BRA, /* 132 Start of non-capturing bracket */
+ OP_BRAPOS, /* 133 Ditto, with unlimited, possessive repeat */
+ OP_CBRA, /* 134 Start of capturing bracket */
+ OP_CBRAPOS, /* 135 Ditto, with unlimited, possessive repeat */
+ OP_COND, /* 136 Conditional group */
/* These five must follow the previous five, in the same order. There's a
check for >= SBRA to distinguish the two sets. */
- OP_SBRA, /* 136 Start of non-capturing bracket, check empty */
- OP_SBRAPOS, /* 137 Ditto, with unlimited, possessive repeat */
- OP_SCBRA, /* 138 Start of capturing bracket, check empty */
- OP_SCBRAPOS, /* 139 Ditto, with unlimited, possessive repeat */
- OP_SCOND, /* 140 Conditional group, check empty */
+ OP_SBRA, /* 137 Start of non-capturing bracket, check empty */
+ OP_SBRAPOS, /* 138 Ditto, with unlimited, possessive repeat */
+ OP_SCBRA, /* 139 Start of capturing bracket, check empty */
+ OP_SCBRAPOS, /* 140 Ditto, with unlimited, possessive repeat */
+ OP_SCOND, /* 141 Conditional group, check empty */
/* The next two pairs must (respectively) be kept together. */
- OP_CREF, /* 141 Used to hold a capture number as condition */
- OP_DNCREF, /* 142 Used to point to duplicate names as a condition */
- OP_RREF, /* 143 Used to hold a recursion number as condition */
- OP_DNRREF, /* 144 Used to point to duplicate names as a condition */
- OP_DEF, /* 145 The DEFINE condition */
+ OP_CREF, /* 142 Used to hold a capture number as condition */
+ OP_DNCREF, /* 143 Used to point to duplicate names as a condition */
+ OP_RREF, /* 144 Used to hold a recursion number as condition */
+ OP_DNRREF, /* 145 Used to point to duplicate names as a condition */
+ OP_FALSE, /* 146 Always false (used by DEFINE and VERSION) */
+ OP_TRUE, /* 147 Always true (used by VERSION) */
- OP_BRAZERO, /* 146 These two must remain together and in this */
- OP_BRAMINZERO, /* 147 order. */
- OP_BRAPOSZERO, /* 148 */
+ OP_BRAZERO, /* 148 These two must remain together and in this */
+ OP_BRAMINZERO, /* 149 order. */
+ OP_BRAPOSZERO, /* 150 */
/* These are backtracking control verbs */
- OP_MARK, /* 149 always has an argument */
- OP_PRUNE, /* 150 */
- OP_PRUNE_ARG, /* 151 same, but with argument */
- OP_SKIP, /* 152 */
- OP_SKIP_ARG, /* 153 same, but with argument */
- OP_THEN, /* 154 */
- OP_THEN_ARG, /* 155 same, but with argument */
- OP_COMMIT, /* 156 */
+ OP_MARK, /* 151 always has an argument */
+ OP_PRUNE, /* 152 */
+ OP_PRUNE_ARG, /* 153 same, but with argument */
+ OP_SKIP, /* 154 */
+ OP_SKIP_ARG, /* 155 same, but with argument */
+ OP_THEN, /* 156 */
+ OP_THEN_ARG, /* 157 same, but with argument */
+ OP_COMMIT, /* 158 */
/* These are forced failure and success verbs */
- OP_FAIL, /* 157 */
- OP_ACCEPT, /* 158 */
- OP_ASSERT_ACCEPT, /* 159 Used inside assertions */
- OP_CLOSE, /* 160 Used before OP_ACCEPT to close open captures */
+ OP_FAIL, /* 159 */
+ OP_ACCEPT, /* 160 */
+ OP_ASSERT_ACCEPT, /* 161 Used inside assertions */
+ OP_CLOSE, /* 162 Used before OP_ACCEPT to close open captures */
/* This is used to skip a subpattern with a {0} quantifier */
- OP_SKIPZERO, /* 161 */
+ OP_SKIPZERO, /* 163 */
+
+ /* This is used to identify a DEFINE group during compilation so that it can
+ be checked for having only one branch. It is changed to OP_FALSE before
+ compilation finishes. */
+
+ OP_DEFINE, /* 164 */
/* This is not an opcode, but is used to check that tables indexed by opcode
are the correct length, in order to catch updating errors - there have been
some in the past. */
OP_TABLE_LENGTH
+
};
/* *** NOTE NOTE NOTE *** Whenever the list above is updated, the two macro
definitions that follow must also be updated to match. There are also tables
-called "opcode_possessify" in pcre_compile.c and "coptable" and "poptable" in
-pcre_dfa_exec.c that must be updated. */
+called "opcode_possessify" in pcre2_compile.c and "coptable" and "poptable" in
+pcre2_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
+only in pcre2_printint.c, which fills out the full names in many cases (and in
some cases doesn't actually use these names at all). */
#define OP_NAME_LIST \
@@ -2167,7 +1635,7 @@ some cases doesn't actually use these names at all). */
"*", "*?", "+", "+?", "?", "??", "{", "{", \
"*+","++", "?+", "{", \
"class", "nclass", "xclass", "Ref", "Refi", "DnRef", "DnRefi", \
- "Recurse", "Callout", \
+ "Recurse", "Callout", "CalloutStr", \
"Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \
"Reverse", "Assert", "Assert not", "AssertB", "AssertB not", \
"Once", "Once_NC", \
@@ -2175,12 +1643,13 @@ some cases doesn't actually use these names at all). */
"Cond", \
"SBra", "SBraPos", "SCBra", "SCBraPos", \
"SCond", \
- "Cond ref", "Cond dnref", "Cond rec", "Cond dnrec", "Cond def", \
+ "Cond ref", "Cond dnref", "Cond rec", "Cond dnrec", \
+ "Cond false", "Cond true", \
"Brazero", "Braminzero", "Braposzero", \
"*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \
"*THEN", "*THEN", "*COMMIT", "*FAIL", \
"*ACCEPT", "*ASSERT_ACCEPT", \
- "Close", "Skip zero"
+ "Close", "Skip zero", "Define"
/* This macro defines the length of fixed length operations in the compiled
@@ -2232,15 +1701,16 @@ in UTF-8 mode. The code that uses this table must know about such things. */
1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ \
1+2*IMM2_SIZE, 1+2*IMM2_SIZE, /* CRRANGE, CRMINRANGE */ \
1, 1, 1, 1+2*IMM2_SIZE, /* Possessive *+, ++, ?+, CRPOSRANGE */ \
- 1+(32/sizeof(pcre_uchar)), /* CLASS */ \
- 1+(32/sizeof(pcre_uchar)), /* NCLASS */ \
+ 1+(32/sizeof(PCRE2_UCHAR)), /* CLASS */ \
+ 1+(32/sizeof(PCRE2_UCHAR)), /* NCLASS */ \
0, /* XCLASS - variable length */ \
1+IMM2_SIZE, /* REF */ \
1+IMM2_SIZE, /* REFI */ \
1+2*IMM2_SIZE, /* DNREF */ \
1+2*IMM2_SIZE, /* DNREFI */ \
1+LINK_SIZE, /* RECURSE */ \
- 2+2*LINK_SIZE, /* CALLOUT */ \
+ 1+2*LINK_SIZE+1, /* CALLOUT */ \
+ 0, /* CALLOUT_STR - variable length */ \
1+LINK_SIZE, /* Alt */ \
1+LINK_SIZE, /* Ket */ \
1+LINK_SIZE, /* KetRmax */ \
@@ -2265,139 +1735,29 @@ in UTF-8 mode. The code that uses this table must know about such things. */
1+LINK_SIZE, /* SCOND */ \
1+IMM2_SIZE, 1+2*IMM2_SIZE, /* CREF, DNCREF */ \
1+IMM2_SIZE, 1+2*IMM2_SIZE, /* RREF, DNRREF */ \
- 1, /* DEF */ \
+ 1, 1, /* FALSE, TRUE */ \
1, 1, 1, /* BRAZERO, BRAMINZERO, BRAPOSZERO */ \
3, 1, 3, /* MARK, PRUNE, PRUNE_ARG */ \
1, 3, /* SKIP, SKIP_ARG */ \
1, 3, /* THEN, THEN_ARG */ \
1, 1, 1, 1, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */ \
- 1+IMM2_SIZE, 1 /* CLOSE, SKIPZERO */
+ 1+IMM2_SIZE, 1, /* CLOSE, SKIPZERO */ \
+ 1 /* DEFINE */
/* A magic value for OP_RREF 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, ERR75, ERR76, ERR77, ERR78, ERR79,
- ERR80, ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERRCOUNT };
-
-/* JIT compiling modes. The function list is indexed by them. */
-
-enum { JIT_COMPILE, JIT_PARTIAL_SOFT_COMPILE, JIT_PARTIAL_HARD_COMPILE,
- JIT_NUMBER_OF_COMPILE_MODES };
-
-/* 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.
-
-The size of the structure must be a multiple of 8 bytes. For the case of
-compiled-on-4 and run-on-8, we include an extra pointer that is always NULL so
-that there are an even number of pointers which therefore are a multiple of 8
-bytes.
-
-It is necessary to fork the struct for the 32 bit library, since it needs to
-use pcre_uint32 for first_char and req_char. We can't put an ifdef inside the
-typedef because pcretest needs access to the struct of the 8-, 16- and 32-bit
-variants.
-
-*** WARNING ***
-When new fields are added to these structures, remember to adjust the code in
-pcre_byte_order.c that is concerned with swapping the byte order of the fields
-when a compiled regex is reloaded on a host with different endianness.
-*** WARNING ***
-There is also similar byte-flipping code in pcretest.c, which is used for
-testing the byte-flipping features. It must also be kept in step.
-*** WARNING ***
-*/
-
-typedef struct real_pcre8_or_16 {
- pcre_uint32 magic_number;
- pcre_uint32 size; /* Total that was malloced */
- pcre_uint32 options; /* Public options */
- pcre_uint32 flags; /* Private flags */
- pcre_uint32 limit_match; /* Limit set from regex */
- pcre_uint32 limit_recursion; /* Limit set from regex */
- pcre_uint16 first_char; /* Starting character */
- pcre_uint16 req_char; /* This character must be seen */
- pcre_uint16 max_lookbehind; /* Longest lookbehind (characters) */
- pcre_uint16 top_bracket; /* Highest numbered group */
- pcre_uint16 top_backref; /* Highest numbered back reference */
- 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 */
- pcre_uint16 dummy1; /* To ensure size is a multiple of 8 */
- pcre_uint16 dummy2; /* To ensure size is a multiple of 8 */
- pcre_uint16 dummy3; /* To ensure size is a multiple of 8 */
- const pcre_uint8 *tables; /* Pointer to tables or NULL for std */
- void *nullpad; /* NULL padding */
-} real_pcre8_or_16;
-
-typedef struct real_pcre8_or_16 real_pcre;
-typedef struct real_pcre8_or_16 real_pcre16;
-
-typedef struct real_pcre32 {
- pcre_uint32 magic_number;
- pcre_uint32 size; /* Total that was malloced */
- pcre_uint32 options; /* Public options */
- pcre_uint32 flags; /* Private flags */
- pcre_uint32 limit_match; /* Limit set from regex */
- pcre_uint32 limit_recursion; /* Limit set from regex */
- pcre_uint32 first_char; /* Starting character */
- pcre_uint32 req_char; /* This character must be seen */
- pcre_uint16 max_lookbehind; /* Longest lookbehind (characters) */
- pcre_uint16 top_bracket; /* Highest numbered group */
- pcre_uint16 top_backref; /* Highest numbered back reference */
- 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 */
- pcre_uint16 dummy; /* To ensure size is a multiple of 8 */
- const pcre_uint8 *tables; /* Pointer to tables or NULL for std */
- void *nullpad; /* NULL padding */
-} real_pcre32;
-
-#if defined COMPILE_PCRE8
-#define REAL_PCRE real_pcre
-#elif defined COMPILE_PCRE16
-#define REAL_PCRE real_pcre16
-#elif defined COMPILE_PCRE32
-#define REAL_PCRE real_pcre32
-#endif
-/* Assert that the size of REAL_PCRE is divisible by 8 */
-typedef int __assert_real_pcre_size_divisible_8[(sizeof(REAL_PCRE) % 8) == 0 ? 1 : -1];
+/* ---------- Private structures that are mode-independent. ---------- */
-/* Needed in pcretest to access some fields in the real_pcre* structures
- * directly. They're unified for 8/16/32 bits since the structs only differ
- * after these fields; if that ever changes, need to fork those defines into
- * 8/16 and 32 bit versions. */
-#define REAL_PCRE_MAGIC(re) (((REAL_PCRE*)re)->magic_number)
-#define REAL_PCRE_SIZE(re) (((REAL_PCRE*)re)->size)
-#define REAL_PCRE_OPTIONS(re) (((REAL_PCRE*)re)->options)
-#define REAL_PCRE_FLAGS(re) (((REAL_PCRE*)re)->flags)
+/* Structure to hold data for custom memory management. */
-/* 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;
+typedef struct pcre2_memctl {
+ void * (*malloc)(size_t, void *);
+ void (*free)(void *, void *);
+ void *memory_data;
+} pcre2_memctl;
/* Structure for building a chain of open capturing subpatterns during
compiling, so that instructions to close them can be compiled when (*ACCEPT) is
@@ -2406,377 +1766,31 @@ 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 */
+ uint16_t number; /* Capture number */
+ uint16_t flag; /* Set TRUE if recursive back ref */
} open_capitem;
-/* Structure for building a list of named groups during the first pass of
-compiling. */
-
-typedef struct named_group {
- const pcre_uchar *name; /* Points to the name in the pattern */
- int length; /* Length of the name */
- pcre_uint32 number; /* Group number */
-} named_group;
-
-/* 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 */
- pcre_uchar *hwm; /* High watermark of workspace */
- open_capitem *open_caps; /* Chain of open capture items */
- named_group *named_groups; /* Points to vector in pre-compile */
- 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 named_group_list_size; /* Number of entries in the list */
- int workspace_size; /* Size of workspace */
- unsigned int bracount; /* Count of capturing parens as we compile */
- int final_bracount; /* Saved value after first pass */
- int max_lookbehind; /* Maximum lookbehind (characters) */
- int top_backref; /* Maximum back reference */
- unsigned int backref_map; /* Bitmap of low back refs */
- unsigned int namedrefcount; /* Number of backreferences by name */
- int parens_depth; /* Depth of nested parentheses */
- int assert_depth; /* Depth of nested assertions */
- pcre_uint32 external_options; /* External (initial) options */
- pcre_uint32 external_flags; /* External flag bits to be set */
- int req_varyopt; /* "After variable item" flag for reqbyte */
- BOOL had_accept; /* (*ACCEPT) encountered */
- BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */
- BOOL check_lookbehind; /* Lookbehinds need later checking */
- BOOL dupnames; /* Duplicate names exist */
- BOOL dupgroups; /* Duplicate groups exist: (?| found */
- BOOL iscondassert; /* Next assert is a condition */
- int nltype; /* Newline type */
- int nllen; /* Newline string length */
- 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 mutual recursion detection. */
-
-typedef struct recurse_check {
- struct recurse_check *prev;
- const pcre_uchar *group;
-} recurse_check;
-
-/* 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) */
- unsigned 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 */
- int saved_capture_last; /* Last capture number */
- 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 */
- unsigned int skip_arg_count; /* For counting SKIP_ARGs */
- unsigned int ignore_skip_arg; /* For re-run when SKIP arg name not found */
- 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 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) */
- 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 */
- pcre_int32 capture_last; /* Most recent capture number + overflow flag */
- 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 */
-#ifdef NO_RECURSE
- void *match_frames_base; /* For remembering malloc'd frames */
-#endif
-} 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 and data prefixes. */
-
-#if defined COMPILE_PCRE8
-#ifndef PUBL
-#define PUBL(name) pcre_##name
-#endif
-#ifndef PRIV
-#define PRIV(name) _pcre_##name
-#endif
-#elif defined COMPILE_PCRE16
-#ifndef PUBL
-#define PUBL(name) pcre16_##name
-#endif
-#ifndef PRIV
-#define PRIV(name) _pcre16_##name
-#endif
-#elif defined COMPILE_PCRE32
-#ifndef PUBL
-#define PUBL(name) pcre32_##name
-#endif
-#ifndef PRIV
-#define PRIV(name) _pcre32_##name
-#endif
-#else
-#error Unsupported compiling mode
-#endif /* COMPILE_PCRE[8|16|32] */
-
/* 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;
+ uint16_t name_offset;
+ uint16_t type;
+ uint16_t 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(OP_lengths)[];
-extern const pcre_uint8 PRIV(default_tables)[];
-
-extern const pcre_uint32 PRIV(hspace_list)[];
-extern const pcre_uint32 PRIV(vspace_list)[];
-
-
-/* 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. */
-#if defined 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)
-
-#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
-
-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_PCRE[8|16|32] */
-
-#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
-
-#define STRCMP_UC_UC_TEST(str1, str2) STRCMP_UC_UC(str1, str2)
-#define STRCMP_UC_C8_TEST(str1, str2) STRCMP_UC_C8(str1, str2)
-
-#elif defined COMPILE_PCRE32
-
-extern int PRIV(strcmp_uc_uc_utf)(const pcre_uchar *,
- const pcre_uchar *);
-extern int PRIV(strcmp_uc_c8_utf)(const pcre_uchar *,
- const char *);
-
-#define STRCMP_UC_UC_TEST(str1, str2) \
- (utf ? PRIV(strcmp_uc_uc_utf)((str1), (str2)) : PRIV(strcmp_uc_uc)((str1), (str2)))
-#define STRCMP_UC_C8_TEST(str1, str2) \
- (utf ? PRIV(strcmp_uc_c8_utf)((str1), (str2)) : PRIV(strcmp_uc_c8)((str1), (str2)))
-
-#endif /* COMPILE_PCRE[8|16|32] */
-
-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 unsigned 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)(pcre_uint32, const pcre_uchar *, BOOL);
-
-#ifdef SUPPORT_JIT
-extern void PRIV(jit_compile)(const REAL_PCRE *,
- PUBL(extra) *, int);
-extern int PRIV(jit_exec)(const PUBL(extra) *,
- const pcre_uchar *, 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) */
+/* Unicode character database (UCD) record format */
typedef struct {
- pcre_uint8 script; /* ucp_Arabic, etc. */
- pcre_uint8 chartype; /* ucp_Cc, etc. (general categories) */
- pcre_uint8 gbprop; /* ucp_gbControl, etc. (grapheme break property) */
- pcre_uint8 caseset; /* offset to multichar other cases or zero */
- pcre_int32 other_case; /* offset to other case, or zero if none */
+ uint8_t script; /* ucp_Arabic, etc. */
+ uint8_t chartype; /* ucp_Cc, etc. (general categories) */
+ uint8_t gbprop; /* ucp_gbControl, etc. (grapheme break property) */
+ uint8_t caseset; /* offset to multichar other cases or zero */
+ int32_t other_case; /* offset to other case, or zero if none */
} ucd_record;
-extern const pcre_uint32 PRIV(ucd_caseless_sets)[];
-extern const ucd_record PRIV(ucd_records)[];
-extern const pcre_uint8 PRIV(ucd_stage1)[];
-extern const pcre_uint16 PRIV(ucd_stage2)[];
-extern const pcre_uint32 PRIV(ucp_gentype)[];
-extern const pcre_uint32 PRIV(ucp_gbtable)[];
-#ifdef SUPPORT_JIT
-extern const int PRIV(ucp_typerange)[];
-#endif
-
-#ifdef SUPPORT_UCP
/* UCD access macros */
#define UCD_BLOCK_SIZE 128
@@ -2789,10 +1803,158 @@ extern const int PRIV(ucp_typerange)[];
#define UCD_CATEGORY(ch) PRIV(ucp_gentype)[UCD_CHARTYPE(ch)]
#define UCD_GRAPHBREAK(ch) GET_UCD(ch)->gbprop
#define UCD_CASESET(ch) GET_UCD(ch)->caseset
-#define UCD_OTHERCASE(ch) ((pcre_uint32)((int)ch + (int)(GET_UCD(ch)->other_case)))
+#define UCD_OTHERCASE(ch) ((uint32_t)((int)ch + (int)(GET_UCD(ch)->other_case)))
+
+/* Header for serialized pcre2 codes. */
-#endif /* SUPPORT_UCP */
+typedef struct pcre2_serialized_data {
+ uint32_t magic;
+ uint32_t version;
+ uint32_t config;
+ int32_t number_of_codes;
+} pcre2_serialized_data;
+
+
+/* ----------------- Items that need PCRE2_CODE_UNIT_WIDTH ----------------- */
+
+/* When this file is included by pcre2test, PCRE2_CODE_UNIT_WIDTH is defined as
+0, so the following items are omitted. */
+
+#if defined PCRE2_CODE_UNIT_WIDTH && PCRE2_CODE_UNIT_WIDTH != 0
+
+/* EBCDIC is supported only for the 8-bit library. */
+
+#if defined EBCDIC && PCRE2_CODE_UNIT_WIDTH != 8
+#error EBCDIC is not supported for the 16-bit or 32-bit libraries
#endif
-/* End of pcre_internal.h */
+/* This is the largest non-UTF code point. */
+
+#define MAX_NON_UTF_CHAR (0xffffffffU >> (32 - PCRE2_CODE_UNIT_WIDTH))
+
+/* Internal shared data tables and variables. These are used by more than one
+of the exported public functions. They have to be "external" in the C sense,
+but are not part of the PCRE2 public API. Although the data for some of them is
+identical in all libraries, they must have different names so that multiple
+libraries can be simultaneously linked to a single application. However, UTF-8
+tables are needed only when compiling the 8-bit library. */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+extern const int PRIV(utf8_table1)[];
+extern const int PRIV(utf8_table1_size);
+extern const int PRIV(utf8_table2)[];
+extern const int PRIV(utf8_table3)[];
+extern const uint8_t PRIV(utf8_table4)[];
+#endif
+
+#define _pcre2_OP_lengths PCRE2_SUFFIX(_pcre2_OP_lengths_)
+#define _pcre2_callout_end_delims PCRE2_SUFFIX(_pcre2_callout_end_delims_)
+#define _pcre2_callout_start_delims PCRE2_SUFFIX(_pcre2_callout_start_delims_)
+#define _pcre2_default_compile_context PCRE2_SUFFIX(_pcre2_default_compile_context_)
+#define _pcre2_default_match_context PCRE2_SUFFIX(_pcre2_default_match_context_)
+#define _pcre2_default_tables PCRE2_SUFFIX(_pcre2_default_tables_)
+#define _pcre2_hspace_list PCRE2_SUFFIX(_pcre2_hspace_list_)
+#define _pcre2_vspace_list PCRE2_SUFFIX(_pcre2_vspace_list_)
+#define _pcre2_ucd_caseless_sets PCRE2_SUFFIX(_pcre2_ucd_caseless_sets_)
+#define _pcre2_ucd_records PCRE2_SUFFIX(_pcre2_ucd_records_)
+#define _pcre2_ucd_stage1 PCRE2_SUFFIX(_pcre2_ucd_stage1_)
+#define _pcre2_ucd_stage2 PCRE2_SUFFIX(_pcre2_ucd_stage2_)
+#define _pcre2_ucp_gbtable PCRE2_SUFFIX(_pcre2_ucp_gbtable_)
+#define _pcre2_ucp_gentype PCRE2_SUFFIX(_pcre2_ucp_gentype_)
+#define _pcre2_ucp_typerange PCRE2_SUFFIX(_pcre2_ucp_typerange_)
+#define _pcre2_unicode_version PCRE2_SUFFIX(_pcre2_unicode_version_)
+#define _pcre2_utt PCRE2_SUFFIX(_pcre2_utt_)
+#define _pcre2_utt_names PCRE2_SUFFIX(_pcre2_utt_names_)
+#define _pcre2_utt_size PCRE2_SUFFIX(_pcre2_utt_size_)
+
+extern const uint8_t PRIV(OP_lengths)[];
+extern const uint32_t PRIV(callout_end_delims)[];
+extern const uint32_t PRIV(callout_start_delims)[];
+extern const pcre2_compile_context PRIV(default_compile_context);
+extern const pcre2_match_context PRIV(default_match_context);
+extern const uint8_t PRIV(default_tables)[];
+extern const uint32_t PRIV(hspace_list)[];
+extern const uint32_t PRIV(vspace_list)[];
+extern const uint32_t PRIV(ucd_caseless_sets)[];
+extern const ucd_record PRIV(ucd_records)[];
+extern const uint8_t PRIV(ucd_stage1)[];
+extern const uint16_t PRIV(ucd_stage2)[];
+extern const uint32_t PRIV(ucp_gbtable)[];
+extern const uint32_t PRIV(ucp_gentype)[];
+#ifdef SUPPORT_JIT
+extern const int PRIV(ucp_typerange)[];
+#endif
+extern const char *PRIV(unicode_version);
+extern const ucp_type_table PRIV(utt)[];
+extern const char PRIV(utt_names)[];
+extern const size_t PRIV(utt_size);
+
+/* Mode-dependent macros and hidden and private structures are defined in a
+separate file so that pcre2test can include them at all supported widths. When
+compiling the library, PCRE2_CODE_UNIT_WIDTH will be defined, and we can
+include them at the appropriate width, after setting up suffix macros for the
+private structures. */
+
+#define branch_chain PCRE2_SUFFIX(branch_chain_)
+#define compile_block PCRE2_SUFFIX(compile_block_)
+#define dfa_match_block PCRE2_SUFFIX(dfa_match_block_)
+#define match_block PCRE2_SUFFIX(match_block_)
+#define named_group PCRE2_SUFFIX(named_group_)
+
+#include "pcre2_intmodedep.h"
+
+/* Private "external" functions. These are internal functions that are called
+from modules other than the one in which they are defined. They have to be
+"external" in the C sense, but are not part of the PCRE2 public API. They are
+not referenced from pcre2test, and must not be defined when no code unit width
+is available. */
+
+#define _pcre2_auto_possessify PCRE2_SUFFIX(_pcre2_auto_possessify_)
+#define _pcre2_check_escape PCRE2_SUFFIX(_pcre2_check_escape_)
+#define _pcre2_find_bracket PCRE2_SUFFIX(_pcre2_find_bracket_)
+#define _pcre2_is_newline PCRE2_SUFFIX(_pcre2_is_newline_)
+#define _pcre2_jit_free_rodata PCRE2_SUFFIX(_pcre2_jit_free_rodata_)
+#define _pcre2_jit_free PCRE2_SUFFIX(_pcre2_jit_free_)
+#define _pcre2_jit_get_size PCRE2_SUFFIX(_pcre2_jit_get_size_)
+#define _pcre2_jit_get_target PCRE2_SUFFIX(_pcre2_jit_get_target_)
+#define _pcre2_memctl_malloc PCRE2_SUFFIX(_pcre2_memctl_malloc_)
+#define _pcre2_ord2utf PCRE2_SUFFIX(_pcre2_ord2utf_)
+#define _pcre2_strcmp PCRE2_SUFFIX(_pcre2_strcmp_)
+#define _pcre2_strcmp_c8 PCRE2_SUFFIX(_pcre2_strcmp_c8_)
+#define _pcre2_strcpy_c8 PCRE2_SUFFIX(_pcre2_strcpy_c8_)
+#define _pcre2_strlen PCRE2_SUFFIX(_pcre2_strlen_)
+#define _pcre2_strncmp PCRE2_SUFFIX(_pcre2_strncmp_)
+#define _pcre2_strncmp_c8 PCRE2_SUFFIX(_pcre2_strncmp_c8_)
+#define _pcre2_study PCRE2_SUFFIX(_pcre2_study_)
+#define _pcre2_valid_utf PCRE2_SUFFIX(_pcre2_valid_utf_)
+#define _pcre2_was_newline PCRE2_SUFFIX(_pcre2_was_newline_)
+#define _pcre2_xclass PCRE2_SUFFIX(_pcre2_xclass_)
+
+extern int _pcre2_auto_possessify(PCRE2_UCHAR *, BOOL,
+ const compile_block *);
+extern int _pcre2_check_escape(PCRE2_SPTR *, PCRE2_SPTR, uint32_t *,
+ int *, uint32_t, BOOL, compile_block *);
+extern PCRE2_SPTR _pcre2_find_bracket(PCRE2_SPTR, BOOL, int);
+extern BOOL _pcre2_is_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR,
+ uint32_t *, BOOL);
+extern void _pcre2_jit_free_rodata(void *, void *);
+extern void _pcre2_jit_free(void *, pcre2_memctl *);
+extern size_t _pcre2_jit_get_size(void *);
+const char * _pcre2_jit_get_target(void);
+extern void * _pcre2_memctl_malloc(size_t, pcre2_memctl *);
+extern unsigned int _pcre2_ord2utf(uint32_t, PCRE2_UCHAR *);
+extern int _pcre2_strcmp(PCRE2_SPTR, PCRE2_SPTR);
+extern int _pcre2_strcmp_c8(PCRE2_SPTR, const char *);
+extern PCRE2_SIZE _pcre2_strcpy_c8(PCRE2_UCHAR *, const char *);
+extern PCRE2_SIZE _pcre2_strlen(PCRE2_SPTR);
+extern int _pcre2_strncmp(PCRE2_SPTR, PCRE2_SPTR, size_t);
+extern int _pcre2_strncmp_c8(PCRE2_SPTR, const char *, size_t);
+extern int _pcre2_study(pcre2_real_code *);
+extern int _pcre2_valid_utf(PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE *);
+extern BOOL _pcre2_was_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR,
+ uint32_t *, BOOL);
+extern BOOL _pcre2_xclass(uint32_t, PCRE2_SPTR, BOOL);
+#endif /* PCRE2_CODE_UNIT_WIDTH */
+
+/* End of pcre2_internal.h */
diff --git a/src/3rdparty/pcre2/src/pcre2_intmodedep.h b/src/3rdparty/pcre2/src/pcre2_intmodedep.h
new file mode 100644
index 0000000000..596d62cfdc
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_intmodedep.h
@@ -0,0 +1,852 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+/* This module contains mode-dependent macro and structure definitions. The
+file is #included by pcre2_internal.h if PCRE2_CODE_UNIT_WIDTH is defined.
+These mode-dependent items are kept in a separate file so that they can also be
+#included multiple times for different code unit widths by pcre2test in order
+to have access to the hidden structures at all supported widths.
+
+Some of the mode-dependent macros are required at different widths for
+different parts of the pcre2test code (in particular, the included
+pcre_printint.c file). We undefine them here so that they can be re-defined for
+multiple inclusions. Not all of these are used in pcre2test, but it's easier
+just to undefine them all. */
+
+#undef ACROSSCHAR
+#undef BACKCHAR
+#undef BYTES2CU
+#undef CU2BYTES
+#undef FORWARDCHAR
+#undef FORWARDCHARTEST
+#undef GET
+#undef GET2
+#undef GETCHAR
+#undef GETCHARINC
+#undef GETCHARINCTEST
+#undef GETCHARLEN
+#undef GETCHARLENTEST
+#undef GETCHARTEST
+#undef GET_EXTRALEN
+#undef HAS_EXTRALEN
+#undef IMM2_SIZE
+#undef MAX_255
+#undef MAX_MARK
+#undef MAX_PATTERN_SIZE
+#undef MAX_UTF_SINGLE_CU
+#undef NOT_FIRSTCU
+#undef PUT
+#undef PUT2
+#undef PUT2INC
+#undef PUTCHAR
+#undef PUTINC
+#undef TABLE_GET
+
+
+
+/* -------------------------- MACROS ----------------------------- */
+
+/* PCRE keeps offsets in its compiled code as at least 16-bit quantities
+(always stored in big-endian order in 8-bit mode) by default. These are used,
+for example, to link from the start of a subpattern to its alternatives and its
+end. The use of 16 bits per offset limits the size of an 8-bit compiled regex
+to around 64K, which is big enough for almost everybody. However, I received a
+request for an even bigger limit. For this reason, and also to make the code
+easier to maintain, the storing and loading of offsets from the compiled code
+unit string is now handled by the macros that are defined here.
+
+The macros are controlled by the value of LINK_SIZE. This defaults to 2, but
+values of 3 or 4 are also supported. */
+
+/* ------------------- 8-bit support ------------------ */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+
+#if LINK_SIZE == 2
+#define PUT(a,n,d) \
+ (a[n] = (PCRE2_UCHAR)((d) >> 8)), \
+ (a[(n)+1] = (PCRE2_UCHAR)((d) & 255))
+#define GET(a,n) \
+ (unsigned int)(((a)[n] << 8) | (a)[(n)+1])
+#define MAX_PATTERN_SIZE (1 << 16)
+
+#elif LINK_SIZE == 3
+#define PUT(a,n,d) \
+ (a[n] = (PCRE2_UCHAR)((d) >> 16)), \
+ (a[(n)+1] = (PCRE2_UCHAR)((d) >> 8)), \
+ (a[(n)+2] = (PCRE2_UCHAR)((d) & 255))
+#define GET(a,n) \
+ (unsigned int)(((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2])
+#define MAX_PATTERN_SIZE (1 << 24)
+
+#elif LINK_SIZE == 4
+#define PUT(a,n,d) \
+ (a[n] = (PCRE2_UCHAR)((d) >> 24)), \
+ (a[(n)+1] = (PCRE2_UCHAR)((d) >> 16)), \
+ (a[(n)+2] = (PCRE2_UCHAR)((d) >> 8)), \
+ (a[(n)+3] = (PCRE2_UCHAR)((d) & 255))
+#define GET(a,n) \
+ (unsigned int)(((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3])
+#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */
+
+#else
+#error LINK_SIZE must be 2, 3, or 4
+#endif
+
+
+/* ------------------- 16-bit support ------------------ */
+
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+
+#if LINK_SIZE == 2
+#undef LINK_SIZE
+#define LINK_SIZE 1
+#define PUT(a,n,d) \
+ (a[n] = (d))
+#define GET(a,n) \
+ (a[n])
+#define MAX_PATTERN_SIZE (1 << 16)
+
+#elif LINK_SIZE == 3 || LINK_SIZE == 4
+#undef LINK_SIZE
+#define LINK_SIZE 2
+#define PUT(a,n,d) \
+ (a[n] = (PCRE2_UCHAR)((d) >> 16)), \
+ (a[(n)+1] = (PCRE2_UCHAR)((d) & 65535))
+#define GET(a,n) \
+ (unsigned int)(((a)[n] << 16) | (a)[(n)+1])
+#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */
+
+#else
+#error LINK_SIZE must be 2, 3, or 4
+#endif
+
+
+/* ------------------- 32-bit support ------------------ */
+
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+#undef LINK_SIZE
+#define LINK_SIZE 1
+#define PUT(a,n,d) \
+ (a[n] = (d))
+#define GET(a,n) \
+ (a[n])
+#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */
+
+#else
+#error Unsupported compiling mode
+#endif
+
+
+/* --------------- Other mode-specific macros ----------------- */
+
+/* PCRE uses some other (at least) 16-bit quantities that do not change when
+the size of offsets changes. There are used for repeat counts and for other
+things such as capturing parenthesis numbers in back references.
+
+Define the number of code units required to hold a 16-bit count/offset, and
+macros to load and store such a value. For reasons that I do not understand,
+the expression in the 8-bit GET2 macro is treated by gcc as a signed
+expression, even when a is declared as unsigned. It seems that any kind of
+arithmetic results in a signed value. Hence the cast. */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+#define IMM2_SIZE 2
+#define GET2(a,n) (unsigned int)(((a)[n] << 8) | (a)[(n)+1])
+#define PUT2(a,n,d) a[n] = (d) >> 8, a[(n)+1] = (d) & 255
+
+#else /* Code units are 16 or 32 bits */
+#define IMM2_SIZE 1
+#define GET2(a,n) a[n]
+#define PUT2(a,n,d) a[n] = d
+#endif
+
+/* Other macros that are different for 8-bit mode. The MAX_255 macro checks
+whether its argument is less than 256. The maximum length of a MARK name must
+fit in one code unit; currently it is set to 255 or 65535. The TABLE_GET macro
+is used to access elements of tables containing exactly 256 items. When code
+points can be greater than 255, a check is needed before accessing these
+tables. */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+#define MAX_255(c) TRUE
+#define MAX_MARK ((1u << 8) - 1)
+#ifdef SUPPORT_UNICODE
+#define SUPPORT_WIDE_CHARS
+#endif /* SUPPORT_UNICODE */
+#define TABLE_GET(c, table, default) ((table)[c])
+
+#else /* Code units are 16 or 32 bits */
+#define MAX_255(c) ((c) <= 255u)
+#define MAX_MARK ((1u << 16) - 1)
+#define SUPPORT_WIDE_CHARS
+#define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default))
+#endif
+
+
+
+/* ----------------- Character-handling macros ----------------- */
+
+/* There is a proposed future special "UTF-21" mode, in which only the lowest
+21 bits of a 32-bit character are interpreted as UTF, with the remaining 11
+high-order bits available to the application for other uses. In preparation for
+the future implementation of this mode, there are macros that load a data item
+and, if in this special mode, mask it to 21 bits. These macros all have names
+starting with UCHAR21. In all other modes, including the normal 32-bit
+library, the macros all have the same simple definitions. When the new mode is
+implemented, it is expected that these definitions will be varied appropriately
+using #ifdef when compiling the library that supports the special mode. */
+
+#define UCHAR21(eptr) (*(eptr))
+#define UCHAR21TEST(eptr) (*(eptr))
+#define UCHAR21INC(eptr) (*(eptr)++)
+#define UCHAR21INCTEST(eptr) (*(eptr)++)
+
+/* When UTF encoding is being used, a character is no longer just a single
+byte in 8-bit mode or a single short in 16-bit mode. The macros for character
+handling generate simple sequences when used in the basic mode, and more
+complicated ones for UTF characters. GETCHARLENTEST and other macros are not
+used when UTF is not supported. To make sure they can never even appear when
+UTF support is omitted, we don't even define them. */
+
+#ifndef SUPPORT_UNICODE
+
+/* #define MAX_UTF_SINGLE_CU */
+/* #define HAS_EXTRALEN(c) */
+/* #define GET_EXTRALEN(c) */
+/* #define NOT_FIRSTCU(c) */
+#define GETCHAR(c, eptr) c = *eptr;
+#define GETCHARTEST(c, eptr) c = *eptr;
+#define GETCHARINC(c, eptr) c = *eptr++;
+#define GETCHARINCTEST(c, eptr) c = *eptr++;
+#define GETCHARLEN(c, eptr, len) c = *eptr;
+#define PUTCHAR(c, p) (*p = c, 1)
+/* #define GETCHARLENTEST(c, eptr, len) */
+/* #define BACKCHAR(eptr) */
+/* #define FORWARDCHAR(eptr) */
+/* #define FORWARCCHARTEST(eptr,end) */
+/* #define ACROSSCHAR(condition, eptr, action) */
+
+#else /* SUPPORT_UNICODE */
+
+/* ------------------- 8-bit support ------------------ */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+#define MAYBE_UTF_MULTI /* UTF chars may use multiple code units */
+
+/* The largest UTF code point that can be encoded as a single code unit. */
+
+#define MAX_UTF_SINGLE_CU 127
+
+/* Tests whether the code point needs extra characters to decode. */
+
+#define HAS_EXTRALEN(c) HASUTF8EXTRALEN(c)
+
+/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE.
+Otherwise it has an undefined behaviour. */
+
+#define GET_EXTRALEN(c) (PRIV(utf8_table4)[(c) & 0x3fu])
+
+/* Returns TRUE, if the given value is not the first code unit of a UTF
+sequence. */
+
+#define NOT_FIRSTCU(c) (((c) & 0xc0u) == 0x80u)
+
+/* Get the next UTF-8 character, not advancing the pointer. This is called when
+we know we are in UTF-8 mode. */
+
+#define GETCHAR(c, eptr) \
+ c = *eptr; \
+ if (c >= 0xc0u) GETUTF8(c, eptr);
+
+/* Get the next UTF-8 character, testing for UTF-8 mode, and not advancing the
+pointer. */
+
+#define GETCHARTEST(c, eptr) \
+ c = *eptr; \
+ if (utf && c >= 0xc0u) GETUTF8(c, eptr);
+
+/* Get the next UTF-8 character, advancing the pointer. This is called when we
+know we are in UTF-8 mode. */
+
+#define GETCHARINC(c, eptr) \
+ c = *eptr++; \
+ if (c >= 0xc0u) GETUTF8INC(c, eptr);
+
+/* Get the next character, testing for UTF-8 mode, and advancing the pointer.
+This is called when we don't know if we are in UTF-8 mode. */
+
+#define GETCHARINCTEST(c, eptr) \
+ c = *eptr++; \
+ if (utf && c >= 0xc0u) GETUTF8INC(c, eptr);
+
+/* Get the next UTF-8 character, not advancing the pointer, incrementing length
+if there are extra bytes. This is called when we know we are in UTF-8 mode. */
+
+#define GETCHARLEN(c, eptr, len) \
+ c = *eptr; \
+ if (c >= 0xc0u) GETUTF8LEN(c, eptr, len);
+
+/* Get the next UTF-8 character, testing for UTF-8 mode, not advancing the
+pointer, incrementing length if there are extra bytes. This is called when we
+do not know if we are in UTF-8 mode. */
+
+#define GETCHARLENTEST(c, eptr, len) \
+ c = *eptr; \
+ if (utf && c >= 0xc0u) GETUTF8LEN(c, eptr, len);
+
+/* If the pointer is not at the start of a character, move it back until
+it is. This is called only in UTF-8 mode - we don't put a test within the macro
+because almost all calls are already within a block of UTF-8 only code. */
+
+#define BACKCHAR(eptr) while((*eptr & 0xc0u) == 0x80u) eptr--
+
+/* Same as above, just in the other direction. */
+#define FORWARDCHAR(eptr) while((*eptr & 0xc0u) == 0x80u) eptr++
+#define FORWARDCHARTEST(eptr,end) while(eptr < end && (*eptr & 0xc0u) == 0x80u) eptr++
+
+/* Same as above, but it allows a fully customizable form. */
+#define ACROSSCHAR(condition, eptr, action) \
+ while((condition) && ((eptr) & 0xc0u) == 0x80u) action
+
+/* Deposit a character into memory, returning the number of code units. */
+
+#define PUTCHAR(c, p) ((utf && c > MAX_UTF_SINGLE_CU)? \
+ PRIV(ord2utf)(c,p) : (*p = c, 1))
+
+
+/* ------------------- 16-bit support ------------------ */
+
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+#define MAYBE_UTF_MULTI /* UTF chars may use multiple code units */
+
+/* The largest UTF code point that can be encoded as a single code unit. */
+
+#define MAX_UTF_SINGLE_CU 65535
+
+/* Tests whether the code point needs extra characters to decode. */
+
+#define HAS_EXTRALEN(c) (((c) & 0xfc00u) == 0xd800u)
+
+/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE.
+Otherwise it has an undefined behaviour. */
+
+#define GET_EXTRALEN(c) 1
+
+/* Returns TRUE, if the given value is not the first code unit of a UTF
+sequence. */
+
+#define NOT_FIRSTCU(c) (((c) & 0xfc00u) == 0xdc00u)
+
+/* Base macro to pick up the low surrogate of a UTF-16 character, not
+advancing the pointer. */
+
+#define GETUTF16(c, eptr) \
+ { c = (((c & 0x3ffu) << 10) | (eptr[1] & 0x3ffu)) + 0x10000u; }
+
+/* Get the next UTF-16 character, not advancing the pointer. This is called when
+we know we are in UTF-16 mode. */
+
+#define GETCHAR(c, eptr) \
+ c = *eptr; \
+ if ((c & 0xfc00u) == 0xd800u) GETUTF16(c, eptr);
+
+/* Get the next UTF-16 character, testing for UTF-16 mode, and not advancing the
+pointer. */
+
+#define GETCHARTEST(c, eptr) \
+ c = *eptr; \
+ if (utf && (c & 0xfc00u) == 0xd800u) GETUTF16(c, eptr);
+
+/* Base macro to pick up the low surrogate of a UTF-16 character, advancing
+the pointer. */
+
+#define GETUTF16INC(c, eptr) \
+ { c = (((c & 0x3ffu) << 10) | (*eptr++ & 0x3ffu)) + 0x10000u; }
+
+/* Get the next UTF-16 character, advancing the pointer. This is called when we
+know we are in UTF-16 mode. */
+
+#define GETCHARINC(c, eptr) \
+ c = *eptr++; \
+ if ((c & 0xfc00u) == 0xd800u) GETUTF16INC(c, eptr);
+
+/* Get the next character, testing for UTF-16 mode, and advancing the pointer.
+This is called when we don't know if we are in UTF-16 mode. */
+
+#define GETCHARINCTEST(c, eptr) \
+ c = *eptr++; \
+ if (utf && (c & 0xfc00u) == 0xd800u) GETUTF16INC(c, eptr);
+
+/* Base macro to pick up the low surrogate of a UTF-16 character, not
+advancing the pointer, incrementing the length. */
+
+#define GETUTF16LEN(c, eptr, len) \
+ { c = (((c & 0x3ffu) << 10) | (eptr[1] & 0x3ffu)) + 0x10000u; len++; }
+
+/* Get the next UTF-16 character, not advancing the pointer, incrementing
+length if there is a low surrogate. This is called when we know we are in
+UTF-16 mode. */
+
+#define GETCHARLEN(c, eptr, len) \
+ c = *eptr; \
+ if ((c & 0xfc00u) == 0xd800u) GETUTF16LEN(c, eptr, len);
+
+/* Get the next UTF-816character, testing for UTF-16 mode, not advancing the
+pointer, incrementing length if there is a low surrogate. This is called when
+we do not know if we are in UTF-16 mode. */
+
+#define GETCHARLENTEST(c, eptr, len) \
+ c = *eptr; \
+ if (utf && (c & 0xfc00u) == 0xd800u) GETUTF16LEN(c, eptr, len);
+
+/* If the pointer is not at the start of a character, move it back until
+it is. This is called only in UTF-16 mode - we don't put a test within the
+macro because almost all calls are already within a block of UTF-16 only
+code. */
+
+#define BACKCHAR(eptr) if ((*eptr & 0xfc00u) == 0xdc00u) eptr--
+
+/* Same as above, just in the other direction. */
+#define FORWARDCHAR(eptr) if ((*eptr & 0xfc00u) == 0xdc00u) eptr++
+#define FORWARDCHARTEST(eptr,end) if (eptr < end && (*eptr & 0xfc00u) == 0xdc00u) eptr++
+
+/* Same as above, but it allows a fully customizable form. */
+#define ACROSSCHAR(condition, eptr, action) \
+ if ((condition) && ((eptr) & 0xfc00u) == 0xdc00u) action
+
+/* Deposit a character into memory, returning the number of code units. */
+
+#define PUTCHAR(c, p) ((utf && c > MAX_UTF_SINGLE_CU)? \
+ PRIV(ord2utf)(c,p) : (*p = c, 1))
+
+
+/* ------------------- 32-bit support ------------------ */
+
+#else
+
+/* These are trivial for the 32-bit library, since all UTF-32 characters fit
+into one PCRE2_UCHAR unit. */
+
+#define MAX_UTF_SINGLE_CU (0x10ffffu)
+#define HAS_EXTRALEN(c) (0)
+#define GET_EXTRALEN(c) (0)
+#define NOT_FIRSTCU(c) (0)
+
+/* Get the next UTF-32 character, not advancing the pointer. This is called when
+we know we are in UTF-32 mode. */
+
+#define GETCHAR(c, eptr) \
+ c = *(eptr);
+
+/* Get the next UTF-32 character, testing for UTF-32 mode, and not advancing the
+pointer. */
+
+#define GETCHARTEST(c, eptr) \
+ c = *(eptr);
+
+/* Get the next UTF-32 character, advancing the pointer. This is called when we
+know we are in UTF-32 mode. */
+
+#define GETCHARINC(c, eptr) \
+ c = *((eptr)++);
+
+/* Get the next character, testing for UTF-32 mode, and advancing the pointer.
+This is called when we don't know if we are in UTF-32 mode. */
+
+#define GETCHARINCTEST(c, eptr) \
+ c = *((eptr)++);
+
+/* Get the next UTF-32 character, not advancing the pointer, not incrementing
+length (since all UTF-32 is of length 1). This is called when we know we are in
+UTF-32 mode. */
+
+#define GETCHARLEN(c, eptr, len) \
+ GETCHAR(c, eptr)
+
+/* Get the next UTF-32character, testing for UTF-32 mode, not advancing the
+pointer, not incrementing the length (since all UTF-32 is of length 1).
+This is called when we do not know if we are in UTF-32 mode. */
+
+#define GETCHARLENTEST(c, eptr, len) \
+ GETCHARTEST(c, eptr)
+
+/* If the pointer is not at the start of a character, move it back until
+it is. This is called only in UTF-32 mode - we don't put a test within the
+macro because almost all calls are already within a block of UTF-32 only
+code.
+
+These are all no-ops since all UTF-32 characters fit into one pcre_uchar. */
+
+#define BACKCHAR(eptr) do { } while (0)
+
+/* Same as above, just in the other direction. */
+
+#define FORWARDCHAR(eptr) do { } while (0)
+#define FORWARDCHARTEST(eptr,end) do { } while (0)
+
+/* Same as above, but it allows a fully customizable form. */
+
+#define ACROSSCHAR(condition, eptr, action) do { } while (0)
+
+/* Deposit a character into memory, returning the number of code units. */
+
+#define PUTCHAR(c, p) (*p = c, 1)
+
+#endif /* UTF-32 character handling */
+#endif /* SUPPORT_UNICODE */
+
+
+/* Mode-dependent macros that have the same definition in all modes. */
+
+#define CU2BYTES(x) ((x)*((PCRE2_CODE_UNIT_WIDTH/8)))
+#define BYTES2CU(x) ((x)/((PCRE2_CODE_UNIT_WIDTH/8)))
+#define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE
+#define PUT2INC(a,n,d) PUT2(a,n,d), a += IMM2_SIZE
+
+
+/* ----------------------- HIDDEN STRUCTURES ----------------------------- */
+
+/* NOTE: All these structures *must* start with a pcre2_memctl structure. The
+code that uses them is simpler because it assumes this. */
+
+/* The real general context structure. At present it holds only data for custom
+memory control. */
+
+typedef struct pcre2_real_general_context {
+ pcre2_memctl memctl;
+} pcre2_real_general_context;
+
+/* The real compile context structure */
+
+typedef struct pcre2_real_compile_context {
+ pcre2_memctl memctl;
+ int (*stack_guard)(uint32_t, void *);
+ void *stack_guard_data;
+ const uint8_t *tables;
+ PCRE2_SIZE max_pattern_length;
+ uint16_t bsr_convention;
+ uint16_t newline_convention;
+ uint32_t parens_nest_limit;
+} pcre2_real_compile_context;
+
+/* The real match context structure. */
+
+typedef struct pcre2_real_match_context {
+ pcre2_memctl memctl;
+#ifdef HEAP_MATCH_RECURSE
+ pcre2_memctl stack_memctl;
+#endif
+#ifdef SUPPORT_JIT
+ pcre2_jit_callback jit_callback;
+ void *jit_callback_data;
+#endif
+ int (*callout)(pcre2_callout_block *, void *);
+ void *callout_data;
+ PCRE2_SIZE offset_limit;
+ uint32_t match_limit;
+ uint32_t recursion_limit;
+} pcre2_real_match_context;
+
+/* The real compiled code structure. The type for the blocksize field is
+defined specially because it is required in pcre2_serialize_decode() when
+copying the size from possibly unaligned memory into a variable of the same
+type. Use a macro rather than a typedef to avoid compiler warnings when this
+file is included multiple times by pcre2test. LOOKBEHIND_MAX specifies the
+largest lookbehind that is supported. (OP_REVERSE in a pattern has a 16-bit
+argument in 8-bit and 16-bit modes, so we need no more than a 16-bit field
+here.) */
+
+#undef CODE_BLOCKSIZE_TYPE
+#define CODE_BLOCKSIZE_TYPE size_t
+
+#undef LOOKBEHIND_MAX
+#define LOOKBEHIND_MAX UINT16_MAX
+
+typedef struct pcre2_real_code {
+ pcre2_memctl memctl; /* Memory control fields */
+ const uint8_t *tables; /* The character tables */
+ void *executable_jit; /* Pointer to JIT code */
+ uint8_t start_bitmap[32]; /* Bitmap for starting code unit < 256 */
+ CODE_BLOCKSIZE_TYPE blocksize; /* Total (bytes) that was malloc-ed */
+ uint32_t magic_number; /* Paranoid and endianness check */
+ uint32_t compile_options; /* Options passed to pcre2_compile() */
+ uint32_t overall_options; /* Options after processing the pattern */
+ uint32_t flags; /* Various state flags */
+ uint32_t limit_match; /* Limit set in the pattern */
+ uint32_t limit_recursion; /* Limit set in the pattern */
+ uint32_t first_codeunit; /* Starting code unit */
+ uint32_t last_codeunit; /* This codeunit must be seen */
+ uint16_t bsr_convention; /* What \R matches */
+ uint16_t newline_convention; /* What is a newline? */
+ uint16_t max_lookbehind; /* Longest lookbehind (characters) */
+ uint16_t minlength; /* Minimum length of match */
+ uint16_t top_bracket; /* Highest numbered group */
+ uint16_t top_backref; /* Highest numbered back reference */
+ uint16_t name_entry_size; /* Size (code units) of table entries */
+ uint16_t name_count; /* Number of name entries in the table */
+} pcre2_real_code;
+
+/* The real match data structure. */
+
+typedef struct pcre2_real_match_data {
+ pcre2_memctl memctl;
+ const pcre2_real_code *code; /* The pattern used for the match */
+ PCRE2_SPTR subject; /* The subject that was matched */
+ PCRE2_SPTR mark; /* Pointer to last mark */
+ PCRE2_SIZE leftchar; /* Offset to leftmost code unit */
+ PCRE2_SIZE rightchar; /* Offset to rightmost code unit */
+ PCRE2_SIZE startchar; /* Offset to starting code unit */
+ uint16_t matchedby; /* Type of match (normal, JIT, DFA) */
+ uint16_t oveccount; /* Number of pairs */
+ int rc; /* The return code from the match */
+ PCRE2_SIZE ovector[1]; /* The first field */
+} pcre2_real_match_data;
+
+
+/* ----------------------- PRIVATE STRUCTURES ----------------------------- */
+
+/* These structures are not needed for pcre2test. */
+
+#ifndef PCRE2_PCRE2TEST
+
+/* Structure for checking for mutual recursion when scanning compiled code. */
+
+typedef struct recurse_check {
+ struct recurse_check *prev;
+ PCRE2_SPTR group;
+} recurse_check;
+
+/* Structure for building a cache when filling in recursion offsets. */
+
+typedef struct recurse_cache {
+ PCRE2_SPTR group;
+ int recno;
+} recurse_cache;
+
+/* Structure for maintaining a chain of pointers to the currently incomplete
+branches, for testing for left recursion while compiling. */
+
+typedef struct branch_chain {
+ struct branch_chain *outer;
+ PCRE2_UCHAR *current_branch;
+} branch_chain;
+
+/* Structure for building a list of named groups during the first pass of
+compiling. */
+
+typedef struct named_group {
+ PCRE2_SPTR name; /* Points to the name in the pattern */
+ uint32_t number; /* Group number */
+ uint16_t length; /* Length of the name */
+ uint16_t isdup; /* TRUE if a duplicate */
+} named_group;
+
+/* Structure for passing "static" information around between the functions
+doing the compiling, so that they are thread-safe. */
+
+typedef struct compile_block {
+ pcre2_real_compile_context *cx; /* Points to the compile context */
+ const uint8_t *lcc; /* Points to lower casing table */
+ const uint8_t *fcc; /* Points to case-flipping table */
+ const uint8_t *cbits; /* Points to character type table */
+ const uint8_t *ctypes; /* Points to table of type maps */
+ PCRE2_SPTR start_workspace; /* The start of working space */
+ PCRE2_SPTR start_code; /* The start of the compiled code */
+ PCRE2_SPTR start_pattern; /* The start of the pattern */
+ PCRE2_SPTR end_pattern; /* The end of the pattern */
+ PCRE2_SPTR nestptr[2]; /* Pointer(s) saved for string substitution */
+ PCRE2_UCHAR *name_table; /* The name/number table */
+ size_t workspace_size; /* Size of workspace */
+ uint16_t names_found; /* Number of entries so far */
+ uint16_t name_entry_size; /* Size of each entry */
+ open_capitem *open_caps; /* Chain of open capture items */
+ named_group *named_groups; /* Points to vector in pre-compile */
+ uint32_t named_group_list_size; /* Number of entries in the list */
+ uint32_t external_options; /* External (initial) options */
+ uint32_t external_flags; /* External flag bits to be set */
+ uint32_t bracount; /* Count of capturing parens as we compile */
+ uint32_t final_bracount; /* Saved value after first pass */
+ uint32_t *groupinfo; /* Group info vector */
+ uint32_t top_backref; /* Maximum back reference */
+ uint32_t backref_map; /* Bitmap of low back refs */
+ uint32_t nltype; /* Newline type */
+ uint32_t nllen; /* Newline string length */
+ PCRE2_UCHAR nl[4]; /* Newline string when fixed length */
+ int max_lookbehind; /* Maximum lookbehind (characters) */
+ int parens_depth; /* Depth of nested parentheses */
+ int assert_depth; /* Depth of nested assertions */
+ int req_varyopt; /* "After variable item" flag for reqbyte */
+ BOOL had_accept; /* (*ACCEPT) encountered */
+ BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */
+ BOOL had_recurse; /* Had a recursion or subroutine call */
+ BOOL check_lookbehind; /* Lookbehinds need later checking */
+ BOOL dupnames; /* Duplicate names exist */
+ BOOL iscondassert; /* Next assert is a condition */
+} compile_block;
+
+/* Structure for keeping the properties of the in-memory stack used
+by the JIT matcher. */
+
+typedef struct pcre2_real_jit_stack {
+ pcre2_memctl memctl;
+ void* stack;
+} pcre2_real_jit_stack;
+
+/* Structure for keeping a chain of heap blocks used for saving ovectors
+during pattern recursion when the ovector is larger than can be saved on
+the system stack. */
+
+typedef struct ovecsave_frame {
+ struct ovecsave_frame *next; /* Next frame on free chain */
+ PCRE2_SIZE saved_ovec[1]; /* First vector element */
+} ovecsave_frame;
+
+/* Structure for items in a linked list that represents an explicit recursive
+call within the pattern; used by pcre_match(). */
+
+typedef struct recursion_info {
+ struct recursion_info *prevrec; /* Previous recursion record (or NULL) */
+ unsigned int group_num; /* Number of group that was called */
+ PCRE2_SIZE *ovec_save; /* Pointer to saved ovector frame */
+ uint32_t saved_capture_last; /* Last capture number */
+ PCRE2_SPTR subject_position; /* Position at start of recursion */
+} recursion_info;
+
+/* A similar structure for pcre_dfa_match(). */
+
+typedef struct dfa_recursion_info {
+ struct dfa_recursion_info *prevrec;
+ PCRE2_SPTR subject_position;
+ uint32_t group_num;
+} dfa_recursion_info;
+
+/* Structure for 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
+pcre2_match(). */
+
+typedef struct eptrblock {
+ struct eptrblock *epb_prev;
+ PCRE2_SPTR epb_saved_eptr;
+} eptrblock;
+
+/* Structure for passing "static" information around between the functions
+doing traditional NFA matching (pcre2_match() and friends). */
+
+typedef struct match_block {
+ pcre2_memctl memctl; /* For general use */
+#ifdef HEAP_MATCH_RECURSE
+ pcre2_memctl stack_memctl; /* For "stack" frames */
+#endif
+ uint32_t match_call_count; /* As it says */
+ uint32_t match_limit; /* As it says */
+ uint32_t match_limit_recursion; /* As it says */
+ BOOL hitend; /* Hit the end of the subject at some point */
+ BOOL hasthen; /* Pattern contains (*THEN) */
+ const uint8_t *lcc; /* Points to lower casing table */
+ const uint8_t *fcc; /* Points to case-flipping table */
+ const uint8_t *ctypes; /* Points to table of type maps */
+ PCRE2_SIZE *ovector; /* Pointer to the offset vector */
+ PCRE2_SIZE offset_end; /* One past the end */
+ PCRE2_SIZE offset_max; /* The maximum usable for return data */
+ PCRE2_SIZE start_offset; /* The start offset value */
+ PCRE2_SIZE end_offset_top; /* Highwater mark at end of match */
+ uint16_t partial; /* PARTIAL options */
+ uint16_t bsr_convention; /* \R interpretation */
+ uint16_t name_count; /* Number of names in name table */
+ uint16_t name_entry_size; /* Size of entry in names table */
+ PCRE2_SPTR name_table; /* Table of group names */
+ PCRE2_SPTR start_code; /* For use when recursing */
+ PCRE2_SPTR start_subject; /* Start of the subject string */
+ PCRE2_SPTR end_subject; /* End of the subject string */
+ PCRE2_SPTR start_match_ptr; /* Start of matched string */
+ PCRE2_SPTR end_match_ptr; /* Subject position at end match */
+ PCRE2_SPTR start_used_ptr; /* Earliest consulted character */
+ PCRE2_SPTR last_used_ptr; /* Latest consulted character */
+ PCRE2_SPTR mark; /* Mark pointer to pass back on success */
+ PCRE2_SPTR nomatch_mark; /* Mark pointer to pass back on failure */
+ PCRE2_SPTR once_target; /* Where to back up to for atomic groups */
+ uint32_t moptions; /* Match options */
+ uint32_t poptions; /* Pattern options */
+ uint32_t capture_last; /* Most recent capture number + overflow flag */
+ uint32_t skip_arg_count; /* For counting SKIP_ARGs */
+ uint32_t ignore_skip_arg; /* For re-run when SKIP arg name not found */
+ uint32_t match_function_type; /* Set for certain special calls of match() */
+ uint32_t nltype; /* Newline type */
+ uint32_t nllen; /* Newline string length */
+ PCRE2_UCHAR nl[4]; /* Newline string when fixed */
+ eptrblock *eptrchain; /* Chain of eptrblocks for tail recursions */
+ recursion_info *recursive; /* Linked list of recursion data */
+ ovecsave_frame *ovecsave_chain; /* Linked list of free ovecsave blocks */
+ void *callout_data; /* To pass back to callouts */
+ int (*callout)(pcre2_callout_block *,void *); /* Callout function or NULL */
+#ifdef HEAP_MATCH_RECURSE
+ void *match_frames_base; /* For remembering malloc'd frames */
+#endif
+} match_block;
+
+/* A similar structure is used for the same purpose by the DFA matching
+functions. */
+
+typedef struct dfa_match_block {
+ pcre2_memctl memctl; /* For general use */
+ PCRE2_SPTR start_code; /* Start of the compiled pattern */
+ PCRE2_SPTR start_subject ; /* Start of the subject string */
+ PCRE2_SPTR end_subject; /* End of subject string */
+ PCRE2_SPTR start_used_ptr; /* Earliest consulted character */
+ PCRE2_SPTR last_used_ptr; /* Latest consulted character */
+ const uint8_t *tables; /* Character tables */
+ PCRE2_SIZE start_offset; /* The start offset value */
+ uint32_t moptions; /* Match options */
+ uint32_t poptions; /* Pattern options */
+ uint32_t nltype; /* Newline type */
+ uint32_t nllen; /* Newline string length */
+ PCRE2_UCHAR nl[4]; /* Newline string when fixed */
+ uint16_t bsr_convention; /* \R interpretation */
+ void *callout_data; /* To pass back to callouts */
+ int (*callout)(pcre2_callout_block *,void *); /* Callout function or NULL */
+ dfa_recursion_info *recursive; /* Linked list of recursion data */
+} dfa_match_block;
+
+#endif /* PCRE2_PCRE2TEST */
+
+/* End of pcre2_intmodedep.h */
diff --git a/src/3rdparty/pcre/pcre_jit_compile.c b/src/3rdparty/pcre2/src/pcre2_jit_compile.c
index 4f15a27ac2..8dea90a1c5 100644
--- a/src/3rdparty/pcre/pcre_jit_compile.c
+++ b/src/3rdparty/pcre2/src/pcre2_jit_compile.c
@@ -6,10 +6,8 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2013 University of Cambridge
-
- The machine code generator part (this module) was written by Zoltan Herczeg
- Copyright (c) 2010-2013
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -44,20 +42,38 @@ POSSIBILITY OF SUCH DAMAGE.
#include "config.h"
#endif
-#include "pcre_internal.h"
+#include "pcre2_internal.h"
-#if defined SUPPORT_JIT
+#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, allocator_data) (PUBL(malloc))(size)
-#define SLJIT_FREE(ptr, allocator_data) (PUBL(free))(ptr)
#define SLJIT_CONFIG_AUTO 1
#define SLJIT_CONFIG_STATIC 1
#define SLJIT_VERBOSE 0
+
+#ifdef PCRE2_DEBUG
+#define SLJIT_DEBUG 1
+#else
#define SLJIT_DEBUG 0
+#endif
+
+#define SLJIT_MALLOC(size, allocator_data) pcre2_jit_malloc(size, allocator_data)
+#define SLJIT_FREE(ptr, allocator_data) pcre2_jit_free(ptr, allocator_data)
+
+static void * pcre2_jit_malloc(size_t size, void *allocator_data)
+{
+pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data);
+return allocator->malloc(size, allocator->memory_data);
+}
+
+static void pcre2_jit_free(void *ptr, void *allocator_data)
+{
+pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data);
+allocator->free(ptr, allocator->memory_data);
+}
#include "sljit/sljitLir.c"
@@ -160,29 +176,27 @@ Thus we can restore the private data 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 *uchar_ptr;
- pcre_uchar *mark_ptr;
+ PCRE2_SPTR str;
+ PCRE2_SPTR begin;
+ PCRE2_SPTR end;
+ pcre2_match_data *match_data;
+ PCRE2_SPTR startchar_ptr;
+ PCRE2_UCHAR *mark_ptr;
+ int (*callout)(pcre2_callout_block *, void *);
void *callout_data;
/* Everything else after. */
+ sljit_uw offset_limit;
sljit_u32 limit_match;
- int real_offset_count;
- int offset_count;
- sljit_u8 notbol;
- sljit_u8 noteol;
- sljit_u8 notempty;
- sljit_u8 notempty_atstart;
+ sljit_u32 oveccount;
+ sljit_u32 options;
} jit_arguments;
+#define JIT_NUMBER_OF_COMPILE_MODES 3
+
typedef struct executable_functions {
void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES];
void *read_only_data_heads[JIT_NUMBER_OF_COMPILE_MODES];
sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES];
- PUBL(jit_callback) callback;
- void *userdata;
sljit_u32 top_bracket;
sljit_u32 limit_match;
} executable_functions;
@@ -228,7 +242,7 @@ typedef struct backtrack_common {
struct backtrack_common *top;
jump_list *topbacktracks;
/* Opcode pointer. */
- pcre_uchar *cc;
+ PCRE2_SPTR cc;
} backtrack_common;
typedef struct assert_backtrack {
@@ -285,7 +299,7 @@ typedef struct char_iterator_backtrack {
jump_list *backtracks;
struct {
unsigned int othercasebit;
- pcre_uchar chr;
+ PCRE2_UCHAR chr;
BOOL enabled;
} charpos;
} u;
@@ -333,7 +347,7 @@ typedef struct compiler_common {
/* The sljit ceneric compiler. */
struct sljit_compiler *compiler;
/* First byte code. */
- pcre_uchar *start;
+ PCRE2_SPTR start;
/* Maps private data offset to each opcode. */
sljit_s32 *private_data_ptrs;
/* Chain list of read-only data ptrs. */
@@ -368,7 +382,7 @@ typedef struct compiler_common {
/* Points to the last matched capture block index. */
sljit_s32 capture_last_ptr;
/* Fast forward skipping byte code pointer. */
- pcre_uchar *fast_forward_bc_ptr;
+ PCRE2_SPTR fast_forward_bc_ptr;
/* Locals used by fast fail optimization. */
sljit_s32 fast_fail_start_ptr;
sljit_s32 fast_fail_end_ptr;
@@ -376,7 +390,7 @@ typedef struct compiler_common {
/* Flipped and lower case tables. */
const sljit_u8 *fcc;
sljit_sw lcc;
- /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */
+ /* Mode can be PCRE2_JIT_COMPLETE and others. */
int mode;
/* TRUE, when minlength is greater than 0. */
BOOL might_be_empty;
@@ -405,7 +419,7 @@ typedef struct compiler_common {
/* Tables. */
sljit_sw ctypes;
/* Named capturing brackets. */
- pcre_uchar *name_table;
+ PCRE2_SPTR name_table;
sljit_sw name_count;
sljit_sw name_entry_size;
@@ -434,19 +448,18 @@ typedef struct compiler_common {
jump_list *casefulcmp;
jump_list *caselesscmp;
jump_list *reset_match;
- BOOL jscript_compat;
-#ifdef SUPPORT_UTF
+ BOOL unset_backref;
+ BOOL alt_circumflex;
+#ifdef SUPPORT_UNICODE
BOOL utf;
-#ifdef SUPPORT_UCP
BOOL use_ucp;
jump_list *getucd;
-#endif
-#ifdef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
jump_list *utfreadchar;
jump_list *utfreadchar16;
jump_list *utfreadtype8;
#endif
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
} compiler_common;
/* For byte_sequence_compare. */
@@ -459,24 +472,24 @@ typedef struct compare_context {
union {
sljit_s32 asint;
sljit_u16 asushort;
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
sljit_u8 asbyte;
sljit_u8 asuchars[4];
-#elif defined COMPILE_PCRE16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
sljit_u16 asuchars[2];
-#elif defined COMPILE_PCRE32
+#elif PCRE2_CODE_UNIT_WIDTH == 32
sljit_u32 asuchars[1];
#endif
} c;
union {
sljit_s32 asint;
sljit_u16 asushort;
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
sljit_u8 asbyte;
sljit_u8 asuchars[4];
-#elif defined COMPILE_PCRE16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
sljit_u16 asuchars[2];
-#elif defined COMPILE_PCRE32
+#elif PCRE2_CODE_UNIT_WIDTH == 32
sljit_u32 asuchars[1];
#endif
} oc;
@@ -518,15 +531,20 @@ the start pointers when the end of the capturing group has not yet reached. */
#define OVECTOR_PRIV(i) (common->cbra_ptr + (i) * (sljit_sw)sizeof(sljit_sw))
#define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start])
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
#define MOV_UCHAR SLJIT_MOV_U8
#define MOVU_UCHAR SLJIT_MOVU_U8
-#elif defined COMPILE_PCRE16
+#define IN_UCHARS(x) (x)
+#elif PCRE2_CODE_UNIT_WIDTH == 16
#define MOV_UCHAR SLJIT_MOV_U16
#define MOVU_UCHAR SLJIT_MOVU_U16
-#elif defined COMPILE_PCRE32
+#define UCHAR_SHIFT (1)
+#define IN_UCHARS(x) ((x) * 2)
+#elif PCRE2_CODE_UNIT_WIDTH == 32
#define MOV_UCHAR SLJIT_MOV_U32
#define MOVU_UCHAR SLJIT_MOVU_U32
+#define UCHAR_SHIFT (2)
+#define IN_UCHARS(x) ((x) * 4)
#else
#error Unsupported compiling mode
#endif
@@ -559,7 +577,7 @@ the start pointers when the end of the capturing group has not yet reached. */
#define READ_CHAR_MAX 0x7fffffff
-static pcre_uchar *bracketend(pcre_uchar *cc)
+static PCRE2_SPTR bracketend(PCRE2_SPTR 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);
@@ -568,7 +586,7 @@ cc += 1 + LINK_SIZE;
return cc;
}
-static int no_alternatives(pcre_uchar *cc)
+static int no_alternatives(PCRE2_SPTR cc)
{
int count = 0;
SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
@@ -594,7 +612,7 @@ return count;
compile_backtrackingpath
*/
-static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc)
+static PCRE2_SPTR next_opcode(compiler_common *common, PCRE2_SPTR cc)
{
SLJIT_UNUSED_ARG(common);
switch(*cc)
@@ -672,7 +690,8 @@ switch(*cc)
case OP_DNCREF:
case OP_RREF:
case OP_DNRREF:
- case OP_DEF:
+ case OP_FALSE:
+ case OP_TRUE:
case OP_BRAZERO:
case OP_BRAMINZERO:
case OP_BRAPOSZERO:
@@ -744,7 +763,7 @@ switch(*cc)
case OP_NOTPOSQUERYI:
case OP_NOTPOSUPTOI:
cc += PRIV(OP_lengths)[*cc];
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
return cc;
@@ -766,12 +785,15 @@ switch(*cc)
return cc + PRIV(OP_lengths)[*cc] - 1;
case OP_ANYBYTE:
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf) return NULL;
#endif
return cc + 1;
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+ case OP_CALLOUT_STR:
+ return cc + GET(cc, 1 + 2*LINK_SIZE);
+
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
case OP_XCLASS:
return cc + GET(cc, 1);
#endif
@@ -789,11 +811,11 @@ switch(*cc)
}
}
-static BOOL check_opcode_types(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend)
+static BOOL check_opcode_types(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend)
{
int count;
-pcre_uchar *slot;
-pcre_uchar *assert_back_end = cc - 1;
+PCRE2_SPTR slot;
+PCRE2_SPTR assert_back_end = cc - 1;
/* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
while (cc < ccend)
@@ -822,7 +844,7 @@ while (cc < ccend)
case OP_SCOND:
/* Only AUTO_CALLOUT can insert this opcode. We do
not intend to support this case. */
- if (cc[1 + LINK_SIZE] == OP_CALLOUT)
+ if (cc[1 + LINK_SIZE] == OP_CALLOUT || cc[1 + LINK_SIZE] == OP_CALLOUT_STR)
return FALSE;
cc += 1 + LINK_SIZE;
break;
@@ -856,12 +878,13 @@ while (cc < ccend)
break;
case OP_CALLOUT:
+ case OP_CALLOUT_STR:
if (common->capture_last_ptr == 0)
{
common->capture_last_ptr = common->ovector_start;
common->ovector_start += sizeof(sljit_sw);
}
- cc += 2 + 2 * LINK_SIZE;
+ cc += (*cc == OP_CALLOUT) ? PRIV(OP_lengths)[OP_CALLOUT] : GET(cc, 1 + 2*LINK_SIZE);
break;
case OP_ASSERTBACK:
@@ -916,7 +939,7 @@ while (cc < ccend)
return TRUE;
}
-static BOOL is_accelerated_repeat(pcre_uchar *cc)
+static BOOL is_accelerated_repeat(PCRE2_SPTR cc)
{
switch(*cc)
{
@@ -959,11 +982,11 @@ switch(*cc)
case OP_CLASS:
case OP_NCLASS:
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
case OP_XCLASS:
- cc += (*cc == OP_XCLASS) ? GET(cc, 1) : (int)(1 + (32 / sizeof(pcre_uchar)));
+ cc += (*cc == OP_XCLASS) ? GET(cc, 1) : (int)(1 + (32 / sizeof(PCRE2_UCHAR)));
#else
- cc += (1 + (32 / sizeof(pcre_uchar)));
+ cc += (1 + (32 / sizeof(PCRE2_UCHAR)));
#endif
switch(*cc)
@@ -983,8 +1006,8 @@ return FALSE;
static SLJIT_INLINE BOOL detect_fast_forward_skip(compiler_common *common, int *private_data_start)
{
-pcre_uchar *cc = common->start;
-pcre_uchar *end;
+PCRE2_SPTR cc = common->start;
+PCRE2_SPTR end;
/* Skip not repeated brackets. */
while (TRUE)
@@ -1032,9 +1055,9 @@ if (is_accelerated_repeat(cc))
return FALSE;
}
-static SLJIT_INLINE void detect_fast_fail(compiler_common *common, pcre_uchar *cc, int *private_data_start, sljit_s32 depth)
+static SLJIT_INLINE void detect_fast_fail(compiler_common *common, PCRE2_SPTR cc, int *private_data_start, sljit_s32 depth)
{
- pcre_uchar *next_alt;
+ PCRE2_SPTR next_alt;
SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA);
@@ -1095,7 +1118,7 @@ static SLJIT_INLINE void detect_fast_fail(compiler_common *common, pcre_uchar *c
while (*cc == OP_ALT);
}
-static int get_class_iterator_size(pcre_uchar *cc)
+static int get_class_iterator_size(PCRE2_SPTR cc)
{
sljit_u32 min;
sljit_u32 max;
@@ -1127,15 +1150,15 @@ switch(*cc)
}
}
-static BOOL detect_repeat(compiler_common *common, pcre_uchar *begin)
+static BOOL detect_repeat(compiler_common *common, PCRE2_SPTR begin)
{
-pcre_uchar *end = bracketend(begin);
-pcre_uchar *next;
-pcre_uchar *next_end;
-pcre_uchar *max_end;
-pcre_uchar type;
+PCRE2_SPTR end = bracketend(begin);
+PCRE2_SPTR next;
+PCRE2_SPTR next_end;
+PCRE2_SPTR max_end;
+PCRE2_UCHAR type;
sljit_sw length = end - begin;
-int min, max, i;
+sljit_s32 min, max, i;
/* Detect fixed iterations first. */
if (end[-(1 + LINK_SIZE)] != OP_KET)
@@ -1264,11 +1287,11 @@ return FALSE;
case OP_TYPEUPTO: \
case OP_TYPEMINUPTO:
-static void set_private_data_ptrs(compiler_common *common, int *private_data_start, pcre_uchar *ccend)
+static void set_private_data_ptrs(compiler_common *common, int *private_data_start, PCRE2_SPTR ccend)
{
-pcre_uchar *cc = common->start;
-pcre_uchar *alternative;
-pcre_uchar *end = NULL;
+PCRE2_SPTR cc = common->start;
+PCRE2_SPTR alternative;
+PCRE2_SPTR end = NULL;
int private_data_ptr = *private_data_start;
int space, size, bracketlen;
BOOL repeat_check = TRUE;
@@ -1394,10 +1417,10 @@ while (cc < ccend)
case OP_CLASS:
case OP_NCLASS:
space = get_class_iterator_size(cc + size);
- size = 1 + 32 / sizeof(pcre_uchar);
+ size = 1 + 32 / sizeof(PCRE2_UCHAR);
break;
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
case OP_XCLASS:
space = get_class_iterator_size(cc + size);
size = GET(cc, 1);
@@ -1423,7 +1446,7 @@ while (cc < ccend)
if (size < 0)
{
cc += -size;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
}
@@ -1446,7 +1469,7 @@ while (cc < ccend)
}
/* Returns with a frame_types (always < 0) if no need for frame. */
-static int get_framesize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL recursive, BOOL *needs_control_head)
+static int get_framesize(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, BOOL recursive, BOOL *needs_control_head)
{
int length = 0;
int possessive = 0;
@@ -1613,7 +1636,9 @@ while (cc < ccend)
case OP_CLASS:
case OP_NCLASS:
case OP_XCLASS:
+
case OP_CALLOUT:
+ case OP_CALLOUT_STR:
cc = next_opcode(common, cc);
SLJIT_ASSERT(cc != NULL);
@@ -1629,7 +1654,7 @@ if (length > 0)
return stack_restore ? no_frame : no_stack;
}
-static void init_frame(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, int stackpos, int stacktop, BOOL recursive)
+static void init_frame(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, int stackpos, int stacktop, BOOL recursive)
{
DEFINE_COMPILER;
BOOL setsom_found = recursive;
@@ -1751,11 +1776,11 @@ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, 0);
SLJIT_ASSERT(stackpos == STACK(stacktop));
}
-static SLJIT_INLINE int get_private_data_copy_length(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL needs_control_head)
+static SLJIT_INLINE int get_private_data_copy_length(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, BOOL needs_control_head)
{
int private_data_length = needs_control_head ? 3 : 2;
int size;
-pcre_uchar *alternative;
+PCRE2_SPTR alternative;
/* Calculate the sum of the private machine words. */
while (cc < ccend)
{
@@ -1812,7 +1837,7 @@ while (cc < ccend)
if (PRIVATE_DATA(cc))
private_data_length++;
cc += 2;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
break;
@@ -1821,7 +1846,7 @@ while (cc < ccend)
if (PRIVATE_DATA(cc))
private_data_length += 2;
cc += 2;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
break;
@@ -1830,7 +1855,7 @@ while (cc < ccend)
if (PRIVATE_DATA(cc))
private_data_length += 2;
cc += 2 + IMM2_SIZE;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
break;
@@ -1855,11 +1880,11 @@ while (cc < ccend)
case OP_CLASS:
case OP_NCLASS:
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
case OP_XCLASS:
- size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar);
+ size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR);
#else
- size = 1 + 32 / (int)sizeof(pcre_uchar);
+ size = 1 + 32 / (int)sizeof(PCRE2_UCHAR);
#endif
if (PRIVATE_DATA(cc))
private_data_length += get_class_iterator_size(cc + size);
@@ -1876,7 +1901,7 @@ SLJIT_ASSERT(cc == ccend);
return private_data_length;
}
-static void copy_private_data(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend,
+static void copy_private_data(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend,
BOOL save, int stackptr, int stacktop, BOOL needs_control_head)
{
DEFINE_COMPILER;
@@ -1885,7 +1910,7 @@ int count, size;
BOOL tmp1next = TRUE;
BOOL tmp1empty = TRUE;
BOOL tmp2empty = TRUE;
-pcre_uchar *alternative;
+PCRE2_SPTR alternative;
enum {
start,
loop,
@@ -2006,7 +2031,7 @@ do
srcw[0] = PRIVATE_DATA(cc);
}
cc += 2;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
break;
@@ -2019,7 +2044,7 @@ do
srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
}
cc += 2;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
break;
@@ -2032,7 +2057,7 @@ do
srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
}
cc += 2 + IMM2_SIZE;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
break;
@@ -2068,11 +2093,11 @@ do
case OP_CLASS:
case OP_NCLASS:
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
case OP_XCLASS:
- size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(pcre_uchar);
+ size = (*cc == OP_XCLASS) ? GET(cc, 1) : 1 + 32 / (int)sizeof(PCRE2_UCHAR);
#else
- size = 1 + 32 / (int)sizeof(pcre_uchar);
+ size = 1 + 32 / (int)sizeof(PCRE2_UCHAR);
#endif
if (PRIVATE_DATA(cc))
switch(get_class_iterator_size(cc + size))
@@ -2198,9 +2223,9 @@ if (save)
SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty)));
}
-static SLJIT_INLINE pcre_uchar *set_then_offsets(compiler_common *common, pcre_uchar *cc, sljit_u8 *current_offset)
+static SLJIT_INLINE PCRE2_SPTR set_then_offsets(compiler_common *common, PCRE2_SPTR cc, sljit_u8 *current_offset)
{
-pcre_uchar *end = bracketend(cc);
+PCRE2_SPTR end = bracketend(cc);
BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT;
/* Assert captures then. */
@@ -2361,25 +2386,11 @@ common->read_only_data_head = (void *)result;
return result + 1;
}
-static void free_read_only_data(void *current, void *allocator_data)
-{
-void *next;
-
-SLJIT_UNUSED_ARG(allocator_data);
-
-while (current != NULL)
- {
- next = *(void**)current;
- SLJIT_FREE(current, allocator_data);
- current = next;
- }
-}
-
static SLJIT_INLINE void reset_ovector(compiler_common *common, int length)
{
DEFINE_COMPILER;
struct sljit_label *loop;
-int i;
+sljit_s32 i;
/* At this point we can freely use all temporary registers. */
SLJIT_ASSERT(length > 1);
@@ -2448,7 +2459,7 @@ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base));
}
-static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, const pcre_uchar *skip_arg)
+static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, PCRE2_SPTR skip_arg)
{
while (current != NULL)
{
@@ -2458,7 +2469,7 @@ while (current != NULL)
break;
case type_mark:
- if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0)
+ if (PRIV(strcmp)(skip_arg, (PCRE2_SPTR)current[-3]) == 0)
return current[-4];
break;
@@ -2476,34 +2487,39 @@ static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
{
DEFINE_COMPILER;
struct sljit_label *loop;
-struct sljit_jump *early_quit;
/* At this point we can freely use all registers. */
OP1(SLJIT_MOV, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(1), STR_PTR, 0);
OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);
+OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
if (common->mark_ptr != 0)
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mark_ptr);
-OP1(SLJIT_MOV_S32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offset_count));
+OP1(SLJIT_MOV_U32, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, oveccount));
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_S0, 0);
if (common->mark_ptr != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_R2, 0);
-OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
-OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin));
+OP2(SLJIT_ADD, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, match_data),
+ SLJIT_IMM, SLJIT_OFFSETOF(pcre2_match_data, ovector) - sizeof(PCRE2_SIZE));
+
GET_LOCAL_BASE(SLJIT_S0, 0, OVECTOR_START);
-/* Unlikely, but possible */
-early_quit = CMP(SLJIT_EQUAL, SLJIT_R1, 0, SLJIT_IMM, 0);
+OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, begin));
+
loop = LABEL();
OP2(SLJIT_SUB, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_S0), 0, SLJIT_R0, 0);
OP2(SLJIT_ADD, SLJIT_S0, 0, SLJIT_S0, 0, SLJIT_IMM, sizeof(sljit_sw));
/* Copy the integer value to the output buffer */
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);
#endif
-OP1(SLJIT_MOVU_S32, SLJIT_MEM1(SLJIT_R2), sizeof(int), SLJIT_S1, 0);
+SLJIT_ASSERT(sizeof(PCRE2_SIZE) == 4 || sizeof(PCRE2_SIZE) == 8);
+if (sizeof(PCRE2_SIZE) == 4)
+ OP1(SLJIT_MOVU_U32, SLJIT_MEM1(SLJIT_R2), sizeof(PCRE2_SIZE), SLJIT_S1, 0);
+else
+ OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_R2), sizeof(PCRE2_SIZE), SLJIT_S1, 0);
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1);
JUMPTO(SLJIT_NOT_ZERO, loop);
-JUMPHERE(early_quit);
/* Calculate the return value, which is the maximum ovector value. */
if (topbracket > 1)
@@ -2525,41 +2541,35 @@ else
static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *quit)
{
DEFINE_COMPILER;
-struct sljit_jump *jump;
+sljit_s32 mov_opcode;
SLJIT_COMPILE_ASSERT(STR_END == SLJIT_S1, str_end_must_be_saved_reg2);
SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0
- && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0));
+ && (common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start != 0 : common->hit_start == 0));
OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0);
-OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL);
-OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, real_offset_count));
-CMPTO(SLJIT_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 2, quit);
+OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP),
+ common->mode == PCRE2_JIT_PARTIAL_SOFT ? common->hit_start : common->start_ptr);
+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_PARTIAL);
/* Store match begin and end. */
OP1(SLJIT_MOV, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, begin));
-OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, offsets));
-
-jump = CMP(SLJIT_SIG_LESS, SLJIT_R2, 0, SLJIT_IMM, 3);
-OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_ptr : (common->hit_start + (int)sizeof(sljit_sw)), SLJIT_S0, 0);
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
-OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT);
-#endif
-OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), 2 * sizeof(int), SLJIT_R2, 0);
-JUMPHERE(jump);
+OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, startchar_ptr), SLJIT_R2, 0);
+OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, match_data));
-OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start);
-OP2(SLJIT_SUB, SLJIT_S1, 0, STR_END, 0, SLJIT_S0, 0);
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
-OP2(SLJIT_ASHR, SLJIT_S1, 0, SLJIT_S1, 0, SLJIT_IMM, UCHAR_SHIFT);
-#endif
-OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), sizeof(int), SLJIT_S1, 0);
+mov_opcode = (sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV;
OP2(SLJIT_SUB, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_S0, 0);
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
OP2(SLJIT_ASHR, SLJIT_R2, 0, SLJIT_R2, 0, SLJIT_IMM, UCHAR_SHIFT);
#endif
-OP1(SLJIT_MOV_S32, SLJIT_MEM1(SLJIT_R1), 0, SLJIT_R2, 0);
+OP1(mov_opcode, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(pcre2_match_data, ovector), SLJIT_R2, 0);
+
+OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_S0, 0);
+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
+OP2(SLJIT_ASHR, STR_END, 0, STR_END, 0, SLJIT_IMM, UCHAR_SHIFT);
+#endif
+OP1(mov_opcode, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(pcre2_match_data, ovector) + sizeof(PCRE2_SIZE), STR_END, 0);
JUMPTO(SLJIT_JUMP, quit);
}
@@ -2570,7 +2580,7 @@ static SLJIT_INLINE void check_start_used_ptr(compiler_common *common)
DEFINE_COMPILER;
struct sljit_jump *jump;
-if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
+if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
{
/* The value of -1 must be kept for start_used_ptr! */
OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, 1);
@@ -2580,7 +2590,7 @@ if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
JUMPHERE(jump);
}
-else if (common->mode == JIT_PARTIAL_HARD_COMPILE)
+else if (common->mode == PCRE2_JIT_PARTIAL_HARD)
{
jump = CMP(SLJIT_LESS_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
@@ -2588,24 +2598,20 @@ else if (common->mode == JIT_PARTIAL_HARD_COMPILE)
}
}
-static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar *cc)
+static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, PCRE2_SPTR cc)
{
/* Detects if the character has an othercase. */
unsigned int c;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf)
{
GETCHAR(c, cc);
if (c > 127)
{
-#ifdef SUPPORT_UCP
return c != UCD_OTHERCASE(c);
-#else
- return FALSE;
-#endif
}
-#ifndef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
return common->fcc[c] != c;
#endif
}
@@ -2618,28 +2624,24 @@ 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
+#ifdef SUPPORT_UNICODE
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)
+static unsigned int char_get_othercase_bit(compiler_common *common, PCRE2_SPTR cc)
{
/* Detects if the character and its othercase has only 1 bit difference. */
unsigned int c, oc, bit;
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
int n;
#endif
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf)
{
GETCHAR(c, cc);
@@ -2647,11 +2649,7 @@ if (common->utf)
oc = common->fcc[c];
else
{
-#ifdef SUPPORT_UCP
oc = UCD_OTHERCASE(c);
-#else
- oc = c;
-#endif
}
}
else
@@ -2675,9 +2673,9 @@ if (c <= 127 && bit == 0x20)
if (!is_powerof2(bit))
return 0;
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && c > 127)
{
n = GET_EXTRALEN(*cc);
@@ -2688,12 +2686,12 @@ if (common->utf && c > 127)
}
return (n << 8) | bit;
}
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
return (0 << 8) | bit;
-#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && c > 65535)
{
if (bit >= (1 << 10))
@@ -2701,10 +2699,10 @@ if (common->utf && c > 65535)
else
return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8));
}
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (bit >> 8));
-#endif /* COMPILE_PCRE[8|16|32] */
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
}
static void check_partial(compiler_common *common, BOOL force)
@@ -2713,17 +2711,17 @@ static void check_partial(compiler_common *common, BOOL force)
DEFINE_COMPILER;
struct sljit_jump *jump = NULL;
-SLJIT_ASSERT(!force || common->mode != JIT_COMPILE);
+SLJIT_ASSERT(!force || common->mode != PCRE2_JIT_COMPLETE);
-if (common->mode == JIT_COMPILE)
+if (common->mode == PCRE2_JIT_COMPLETE)
return;
if (!force)
jump = CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
-else if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
+else if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
jump = CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1);
-if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
+if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);
else
{
@@ -2743,14 +2741,14 @@ static void check_str_end(compiler_common *common, jump_list **end_reached)
DEFINE_COMPILER;
struct sljit_jump *jump;
-if (common->mode == JIT_COMPILE)
+if (common->mode == PCRE2_JIT_COMPLETE)
{
add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
return;
}
jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
-if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
+if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
{
add_jump(compiler, end_reached, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);
@@ -2772,7 +2770,7 @@ static void detect_partial_match(compiler_common *common, jump_list **backtracks
DEFINE_COMPILER;
struct sljit_jump *jump;
-if (common->mode == JIT_COMPILE)
+if (common->mode == PCRE2_JIT_COMPLETE)
{
add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
return;
@@ -2781,7 +2779,7 @@ if (common->mode == JIT_COMPILE)
/* Partial matching mode. */
jump = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0));
-if (common->mode == JIT_PARTIAL_SOFT_COMPILE)
+if (common->mode == PCRE2_JIT_PARTIAL_SOFT)
{
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);
add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
@@ -2801,14 +2799,14 @@ static void peek_char(compiler_common *common, sljit_u32 max)
/* Reads the character into TMP1, keeps STR_PTR.
Does not check STR_END. TMP2 Destroyed. */
DEFINE_COMPILER;
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
struct sljit_jump *jump;
#endif
SLJIT_UNUSED_ARG(max);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
{
if (max < 128) return;
@@ -2819,9 +2817,9 @@ if (common->utf)
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
JUMPHERE(jump);
}
-#endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
-#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16
if (common->utf)
{
if (max < 0xd800) return;
@@ -2839,7 +2837,7 @@ if (common->utf)
#endif
}
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
static BOOL is_char7_bitset(const sljit_u8 *bitset, BOOL nclass)
{
@@ -2882,7 +2880,7 @@ if (full_read)
}
}
-#endif /* SUPPORT_UTF && COMPILE_PCRE8 */
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */
static void read_char_range(compiler_common *common, sljit_u32 min, sljit_u32 max, BOOL update_str_ptr)
{
@@ -2890,10 +2888,10 @@ static void read_char_range(compiler_common *common, sljit_u32 min, sljit_u32 ma
between min and max (c >= min && c <= max). Otherwise it returns with a value
outside the range. Does not check STR_END. */
DEFINE_COMPILER;
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
struct sljit_jump *jump;
#endif
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
struct sljit_jump *jump2;
#endif
@@ -2905,7 +2903,7 @@ SLJIT_ASSERT(min <= max);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
{
if (max < 128 && !update_str_ptr) return;
@@ -2980,7 +2978,7 @@ if (common->utf)
}
#endif
-#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16
if (common->utf)
{
if (max >= 0x10000)
@@ -3021,10 +3019,10 @@ static void read_char8_type(compiler_common *common, BOOL update_str_ptr)
{
/* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
DEFINE_COMPILER;
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
struct sljit_jump *jump;
#endif
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
struct sljit_jump *jump2;
#endif
@@ -3033,7 +3031,7 @@ SLJIT_UNUSED_ARG(update_str_ptr);
OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
{
/* This can be an extra read in some situations, but hopefully
@@ -3058,19 +3056,19 @@ if (common->utf)
JUMPHERE(jump);
return;
}
-#endif /* SUPPORT_UTF && COMPILE_PCRE8 */
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */
-#if !defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
/* The ctypes array contains only 256 values. */
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
jump = CMP(SLJIT_GREATER, TMP2, 0, SLJIT_IMM, 255);
#endif
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
-#if !defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
JUMPHERE(jump);
#endif
-#if defined SUPPORT_UTF && defined COMPILE_PCRE16
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16
if (common->utf && update_str_ptr)
{
/* Skip low surrogate if necessary. */
@@ -3079,15 +3077,15 @@ if (common->utf && update_str_ptr)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
JUMPHERE(jump);
}
-#endif /* SUPPORT_UTF && COMPILE_PCRE16 */
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16 */
}
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_PCRE32
-#if defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+#if PCRE2_CODE_UNIT_WIDTH == 8
struct sljit_label *label;
if (common->utf)
@@ -3099,7 +3097,7 @@ if (common->utf)
CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label);
return;
}
-#elif defined COMPILE_PCRE16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
if (common->utf)
{
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1));
@@ -3112,8 +3110,8 @@ if (common->utf)
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
return;
}
-#endif /* COMPILE_PCRE[8|16] */
-#endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
}
@@ -3149,9 +3147,9 @@ else
}
}
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
static void do_utfreadchar(compiler_common *common)
{
/* Fast decoding a UTF-8 character. TMP1 contains the first byte
@@ -3272,11 +3270,7 @@ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
-#endif /* COMPILE_PCRE8 */
-
-#endif /* SUPPORT_UTF */
-
-#ifdef SUPPORT_UCP
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
/* UCD_BLOCK_SIZE must be 128 (see the assert below). */
#define UCD_BLOCK_MASK 127
@@ -3302,9 +3296,10 @@ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(
OP1(SLJIT_MOV_U8, 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)
+#endif /* SUPPORT_UNICODE */
+
+static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, sljit_u32 overall_options)
{
DEFINE_COMPILER;
struct sljit_label *mainloop;
@@ -3312,20 +3307,23 @@ struct sljit_label *newlinelabel = NULL;
struct sljit_jump *start;
struct sljit_jump *end = NULL;
struct sljit_jump *end2 = NULL;
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
struct sljit_jump *singlechar;
#endif
jump_list *newline = NULL;
BOOL newlinecheck = FALSE;
BOOL readuchar = FALSE;
-if (!(hascrorlf || (common->match_end_ptr != 0)) &&
- (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
+if (!(hascrorlf || (overall_options & PCRE2_FIRSTLINE) != 0)
+ && (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
newlinecheck = TRUE;
-if (common->match_end_ptr != 0)
+SLJIT_ASSERT(common->forced_quit_label == NULL);
+
+if ((overall_options & PCRE2_FIRSTLINE) != 0)
{
/* Search for the end of the first line. */
+ SLJIT_ASSERT(common->match_end_ptr != 0);
OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
if (common->nltype == NLTYPE_FIXED && common->newline > 255)
@@ -3356,6 +3354,31 @@ if (common->match_end_ptr != 0)
OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
}
+else if ((overall_options & PCRE2_USE_OFFSET_LIMIT) != 0)
+ {
+ /* Check whether offset limit is set and valid. */
+ SLJIT_ASSERT(common->match_end_ptr != 0);
+
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, offset_limit));
+ OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);
+ end = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw) PCRE2_UNSET);
+ OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
+#if PCRE2_CODE_UNIT_WIDTH == 16
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);
+#endif
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
+ end2 = CMP(SLJIT_LESS_EQUAL, TMP2, 0, STR_END, 0);
+ OP1(SLJIT_MOV, TMP2, 0, STR_END, 0);
+ JUMPHERE(end2);
+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);
+ add_jump(compiler, &common->forced_quit, CMP(SLJIT_LESS, TMP2, 0, STR_PTR, 0));
+ JUMPHERE(end);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr, TMP2, 0);
+ }
start = JUMP(SLJIT_JUMP);
@@ -3367,7 +3390,7 @@ if (newlinecheck)
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);
OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
#endif
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
@@ -3377,7 +3400,7 @@ if (newlinecheck)
mainloop = LABEL();
/* Increasing the STR_PTR here requires one less jump in the most common case. */
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf) readuchar = TRUE;
#endif
if (newlinecheck) readuchar = TRUE;
@@ -3389,8 +3412,8 @@ if (newlinecheck)
CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
-#if defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
{
singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
@@ -3398,7 +3421,7 @@ if (common->utf)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
JUMPHERE(singlechar);
}
-#elif defined COMPILE_PCRE16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
if (common->utf)
{
singlechar = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
@@ -3409,8 +3432,8 @@ if (common->utf)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
JUMPHERE(singlechar);
}
-#endif /* COMPILE_PCRE[8|16] */
-#endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
JUMPHERE(start);
if (newlinecheck)
@@ -3425,9 +3448,9 @@ return mainloop;
#define MAX_N_CHARS 16
#define MAX_DIFF_CHARS 6
-static SLJIT_INLINE void add_prefix_char(pcre_uchar chr, pcre_uchar *chars)
+static SLJIT_INLINE void add_prefix_char(PCRE2_UCHAR chr, PCRE2_UCHAR *chars)
{
-pcre_uchar i, len;
+PCRE2_UCHAR i, len;
len = chars[0];
if (len == 255)
@@ -3455,20 +3478,20 @@ chars[len] = chr;
chars[0] = len;
}
-static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uchar *chars, int max_chars, sljit_u32 *rec_count)
+static int scan_prefix(compiler_common *common, PCRE2_SPTR cc, PCRE2_UCHAR *chars, int max_chars, sljit_u32 *rec_count)
{
/* Recursive function, which scans prefix literals. */
BOOL last, any, class, caseless;
int len, repeat, len_save, consumed = 0;
sljit_u32 chr; /* Any unicode character. */
sljit_u8 *bytes, *bytes_end, byte;
-pcre_uchar *alternative, *cc_save, *oc;
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
-pcre_uchar othercase[8];
-#elif defined SUPPORT_UTF && defined COMPILE_PCRE16
-pcre_uchar othercase[2];
+PCRE2_SPTR alternative, cc_save, oc;
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
+PCRE2_UCHAR othercase[8];
+#elif defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 16
+PCRE2_UCHAR othercase[2];
#else
-pcre_uchar othercase[1];
+PCRE2_UCHAR othercase[1];
#endif
repeat = 1;
@@ -3541,7 +3564,7 @@ while (TRUE)
case OP_POSQUERY:
len = 1;
cc++;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);
#endif
max_chars = scan_prefix(common, cc + len, chars, max_chars, rec_count);
@@ -3579,7 +3602,7 @@ while (TRUE)
continue;
case OP_CLASS:
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf && !is_char7_bitset((const sljit_u8 *)(cc + 1), FALSE))
return consumed;
#endif
@@ -3587,15 +3610,15 @@ while (TRUE)
break;
case OP_NCLASS:
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf) return consumed;
#endif
class = TRUE;
break;
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
case OP_XCLASS:
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf) return consumed;
#endif
any = TRUE;
@@ -3604,7 +3627,7 @@ while (TRUE)
#endif
case OP_DIGIT:
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE))
return consumed;
#endif
@@ -3613,7 +3636,7 @@ while (TRUE)
break;
case OP_WHITESPACE:
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE))
return consumed;
#endif
@@ -3622,7 +3645,7 @@ while (TRUE)
break;
case OP_WORDCHAR:
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf && !is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE))
return consumed;
#endif
@@ -3639,17 +3662,17 @@ while (TRUE)
case OP_NOT_WORDCHAR:
case OP_ANY:
case OP_ALLANY:
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf) return consumed;
#endif
any = TRUE;
cc++;
break;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
case OP_NOTPROP:
case OP_PROP:
-#ifndef COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf) return consumed;
#endif
any = TRUE;
@@ -3664,7 +3687,7 @@ while (TRUE)
case OP_NOTEXACT:
case OP_NOTEXACTI:
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf) return consumed;
#endif
any = TRUE;
@@ -3696,7 +3719,7 @@ while (TRUE)
if (class)
{
bytes = (sljit_u8*) (cc + 1);
- cc += 1 + 32 / sizeof(pcre_uchar);
+ cc += 1 + 32 / sizeof(PCRE2_UCHAR);
switch (*cc)
{
@@ -3791,13 +3814,13 @@ while (TRUE)
}
len = 1;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc);
#endif
if (caseless && char_has_othercase(common, cc))
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf)
{
GETCHAR(chr, cc);
@@ -3855,16 +3878,16 @@ while (TRUE)
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
-static sljit_s32 character_to_int32(pcre_uchar chr)
+static sljit_s32 character_to_int32(PCRE2_UCHAR chr)
{
sljit_s32 value = (sljit_s32)chr;
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
#define SSE2_COMPARE_TYPE_INDEX 0
return (value << 24) | (value << 16) | (value << 8) | value;
-#elif defined COMPILE_PCRE16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
#define SSE2_COMPARE_TYPE_INDEX 1
return (value << 16) | value;
-#elif defined COMPILE_PCRE32
+#elif PCRE2_CODE_UNIT_WIDTH == 32
#define SSE2_COMPARE_TYPE_INDEX 2
return value;
#else
@@ -3872,7 +3895,7 @@ return value;
#endif
}
-static SLJIT_INLINE void fast_forward_first_char2_sse2(compiler_common *common, pcre_uchar char1, pcre_uchar char2)
+static SLJIT_INLINE void fast_forward_first_char2_sse2(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2)
{
DEFINE_COMPILER;
struct sljit_label *start;
@@ -3883,7 +3906,7 @@ sljit_s32 tmp1_ind = sljit_get_register_index(TMP1);
sljit_s32 tmp2_ind = sljit_get_register_index(TMP2);
sljit_s32 str_ptr_ind = sljit_get_register_index(STR_PTR);
BOOL load_twice = FALSE;
-pcre_uchar bit;
+PCRE2_UCHAR bit;
bit = char1 ^ char2;
if (!is_powerof2(bit))
@@ -4004,12 +4027,12 @@ sljit_emit_op_custom(compiler, instruction, 4);
if (load_twice)
{
- OP1(SLJIT_MOV, TMP3, 0, TMP2, 0);
+ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP2, 0);
instruction[3] = 0xc0 | (tmp2_ind << 3) | 1;
sljit_emit_op_custom(compiler, instruction, 4);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
- OP1(SLJIT_MOV, TMP2, 0, TMP3, 0);
+ OP1(SLJIT_MOV, TMP2, 0, RETURN_ADDR, 0);
}
OP2(SLJIT_ASHR, TMP1, 0, TMP1, 0, TMP2, 0);
@@ -4134,14 +4157,14 @@ SET_LABEL(quit[2], start);
#endif
-static void fast_forward_first_char2(compiler_common *common, pcre_uchar char1, pcre_uchar char2, sljit_s32 offset)
+static void fast_forward_first_char2(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)
{
DEFINE_COMPILER;
struct sljit_label *start;
struct sljit_jump *quit;
struct sljit_jump *found;
-pcre_uchar mask;
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+PCRE2_UCHAR mask;
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
struct sljit_label *utf_start = NULL;
struct sljit_jump *utf_quit = NULL;
#endif
@@ -4169,7 +4192,7 @@ if (has_match_end)
}
}
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf && offset > 0)
utf_start = LABEL();
#endif
@@ -4182,25 +4205,25 @@ if (sljit_x86_is_sse2_available())
{
fast_forward_first_char2_sse2(common, char1, char2);
- SLJIT_ASSERT(common->mode == JIT_COMPILE || offset == 0);
- if (common->mode == JIT_COMPILE)
+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE || offset == 0);
+ if (common->mode == PCRE2_JIT_COMPLETE)
{
/* In complete mode, we don't need to run a match when STR_PTR == STR_END. */
SLJIT_ASSERT(common->forced_quit_label == NULL);
- OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);
add_jump(compiler, &common->forced_quit, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf && offset > 0)
{
- SLJIT_ASSERT(common->mode == JIT_COMPILE);
+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start);
-#elif defined COMPILE_PCRE16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start);
#else
@@ -4260,22 +4283,22 @@ else
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, start);
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf && offset > 0)
utf_quit = JUMP(SLJIT_JUMP);
#endif
JUMPHERE(found);
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf && offset > 0)
{
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, utf_start);
-#elif defined COMPILE_PCRE16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, utf_start);
#else
@@ -4310,10 +4333,10 @@ struct sljit_jump *quit;
struct sljit_jump *match;
/* bytes[0] represent the number of characters between 0
and MAX_N_BYTES - 1, 255 represents any character. */
-pcre_uchar chars[MAX_N_CHARS * MAX_DIFF_CHARS];
+PCRE2_UCHAR chars[MAX_N_CHARS * MAX_DIFF_CHARS];
sljit_s32 offset;
-pcre_uchar mask;
-pcre_uchar *char_set, *char_set_end;
+PCRE2_UCHAR mask;
+PCRE2_UCHAR *char_set, *char_set_end;
int i, max, from;
int range_right = -1, range_len;
sljit_u8 *update_table = NULL;
@@ -4441,7 +4464,7 @@ OP1(SLJIT_MOV, RETURN_ADDR, 0, SLJIT_IMM, (sljit_sw)update_table);
start = LABEL();
quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
-#if defined COMPILE_PCRE8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+#if PCRE2_CODE_UNIT_WIDTH == 8 || (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right));
#else
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(range_right + 1) - 1);
@@ -4479,7 +4502,7 @@ if (offset >= 0)
}
}
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf && offset != 0)
{
if (offset < 0)
@@ -4489,10 +4512,10 @@ if (common->utf && offset != 0)
}
else
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1));
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, start);
-#elif defined COMPILE_PCRE16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
CMPTO(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00, start);
#else
@@ -4526,17 +4549,16 @@ return TRUE;
}
#undef MAX_N_CHARS
-#undef MAX_DIFF_CHARS
-static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless)
+static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, PCRE2_UCHAR first_char, BOOL caseless)
{
-pcre_uchar oc;
+PCRE2_UCHAR oc;
oc = first_char;
if (caseless)
{
oc = TABLE_GET(first_char, common->fcc, first_char);
-#if defined SUPPORT_UCP && !defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
if (first_char > 127 && common->utf)
oc = UCD_OTHERCASE(first_char);
#endif
@@ -4573,7 +4595,7 @@ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
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);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_GREATER_EQUAL);
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);
#endif
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
@@ -4618,7 +4640,7 @@ if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
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);
OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
#endif
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
@@ -4641,7 +4663,7 @@ struct sljit_label *start;
struct sljit_jump *quit;
struct sljit_jump *found = NULL;
jump_list *matches = NULL;
-#ifndef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
struct sljit_jump *jump;
#endif
@@ -4654,14 +4676,14 @@ if (common->match_end_ptr != 0)
start = LABEL();
quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf)
OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
#endif
if (!check_class_ranges(common, start_bits, (start_bits[31] & 0x80) != 0, TRUE, &matches))
{
-#ifndef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
jump = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 255);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255);
JUMPHERE(jump);
@@ -4674,20 +4696,20 @@ if (!check_class_ranges(common, start_bits, (start_bits[31] & 0x80) != 0, TRUE,
found = JUMP(SLJIT_NOT_ZERO);
}
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
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));
-#ifdef SUPPORT_UTF
-#if defined COMPILE_PCRE8
+#ifdef SUPPORT_UNICODE
+#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
{
CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
}
-#elif defined COMPILE_PCRE16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
if (common->utf)
{
CMPTO(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start);
@@ -4697,8 +4719,8 @@ if (common->utf)
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
}
-#endif /* COMPILE_PCRE[8|16] */
-#endif /* SUPPORT_UTF */
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */
+#endif /* SUPPORT_UNICODE */
JUMPTO(SLJIT_JUMP, start);
if (found != NULL)
JUMPHERE(found);
@@ -4710,7 +4732,7 @@ if (common->match_end_ptr != 0)
OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0);
}
-static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uchar req_char, BOOL caseless, BOOL has_firstchar)
+static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, PCRE2_UCHAR req_char, BOOL caseless, BOOL has_firstchar)
{
DEFINE_COMPILER;
struct sljit_label *loop;
@@ -4723,7 +4745,7 @@ sljit_u32 oc, bit;
SLJIT_ASSERT(common->req_char_ptr != 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr);
-OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX);
+OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_CU_MAX);
toolong = CMP(SLJIT_LESS, TMP1, 0, STR_END, 0);
alreadyfound = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0);
@@ -4740,7 +4762,7 @@ oc = req_char;
if (caseless)
{
oc = TABLE_GET(req_char, common->fcc, req_char);
-#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
if (req_char > 127 && common->utf)
oc = UCD_OTHERCASE(req_char);
#endif
@@ -4813,7 +4835,7 @@ static void check_wordboundary(compiler_common *common)
DEFINE_COMPILER;
struct sljit_jump *skipread;
jump_list *skipread_list = NULL;
-#if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF
+#if PCRE2_CODE_UNIT_WIDTH != 8 || defined SUPPORT_UNICODE
struct sljit_jump *jump;
#endif
@@ -4830,7 +4852,7 @@ check_start_used_ptr(common);
read_char(common);
/* Testing char type. */
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
if (common->use_ucp)
{
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
@@ -4848,24 +4870,24 @@ if (common->use_ucp)
else
#endif
{
-#ifndef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
-#elif defined SUPPORT_UTF
+#elif defined SUPPORT_UNICODE
/* Here LOCALS1 has already been zeroed. */
jump = NULL;
if (common->utf)
jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
-#endif /* COMPILE_PCRE8 */
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */);
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP1, 0);
-#ifndef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
JUMPHERE(jump);
-#elif defined SUPPORT_UTF
+#elif defined SUPPORT_UNICODE
if (jump != NULL)
JUMPHERE(jump);
-#endif /* COMPILE_PCRE8 */
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
}
JUMPHERE(skipread);
@@ -4874,7 +4896,7 @@ check_str_end(common, &skipread_list);
peek_char(common, READ_CHAR_MAX);
/* Testing char type. This is a code duplication. */
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
if (common->use_ucp)
{
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
@@ -4891,11 +4913,11 @@ if (common->use_ucp)
else
#endif
{
-#ifndef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
/* TMP2 may be destroyed by peek_char. */
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
-#elif defined SUPPORT_UTF
+#elif defined SUPPORT_UNICODE
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
jump = NULL;
if (common->utf)
@@ -4904,12 +4926,12 @@ else
OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes);
OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
-#ifndef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
JUMPHERE(jump);
-#elif defined SUPPORT_UTF
+#elif defined SUPPORT_UNICODE
if (jump != NULL)
JUMPHERE(jump);
-#endif /* COMPILE_PCRE8 */
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
}
set_jumps(skipread_list, LABEL());
@@ -5080,18 +5102,18 @@ 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);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
-#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
-#ifdef COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
+#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
{
#endif
OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_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
+#if PCRE2_CODE_UNIT_WIDTH == 8
}
#endif
-#endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
+#endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */
OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
}
@@ -5108,8 +5130,8 @@ OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_EQUAL);
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
-#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
-#ifdef COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
+#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
{
#endif
@@ -5126,10 +5148,10 @@ if (common->utf)
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
-#ifdef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
}
#endif
-#endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
+#endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */
OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
@@ -5146,18 +5168,18 @@ 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);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL);
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
-#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
-#ifdef COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
+#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
{
#endif
OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_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
+#if PCRE2_CODE_UNIT_WIDTH == 8
}
#endif
-#endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
+#endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */
OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_EQUAL);
sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
@@ -5214,16 +5236,16 @@ 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
+#if PCRE2_CODE_UNIT_WIDTH != 8
jump = CMP(SLJIT_GREATER, CHAR1, 0, SLJIT_IMM, 255);
#endif
OP1(SLJIT_MOV_U8, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0);
-#ifndef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
JUMPHERE(jump);
jump = CMP(SLJIT_GREATER, CHAR2, 0, SLJIT_IMM, 255);
#endif
OP1(SLJIT_MOV_U8, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
-#ifndef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
JUMPHERE(jump);
#endif
jump = CMP(SLJIT_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
@@ -5242,21 +5264,21 @@ sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
#undef CHAR1
#undef CHAR2
-#if defined SUPPORT_UTF && defined SUPPORT_UCP
+#if defined SUPPORT_UNICODE
-static const pcre_uchar * SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1)
+static PCRE2_SPTR SLJIT_CALL do_utf_caselesscmp(PCRE2_SPTR src1, jit_arguments *args, PCRE2_SPTR end1)
{
/* This function would be ineffective to do in JIT level. */
sljit_u32 c1, c2;
-const pcre_uchar *src2 = args->uchar_ptr;
-const pcre_uchar *end2 = args->end;
+PCRE2_SPTR src2 = args->startchar_ptr;
+PCRE2_SPTR end2 = args->end;
const ucd_record *ur;
const sljit_u32 *pp;
while (src1 < end1)
{
if (src2 >= end2)
- return (pcre_uchar*)1;
+ return (PCRE2_SPTR)1;
GETCHARINC(c1, src1);
GETCHARINC(c2, src2);
ur = GET_UCD(c2);
@@ -5273,15 +5295,15 @@ while (src1 < end1)
return src2;
}
-#endif /* SUPPORT_UTF && SUPPORT_UCP */
+#endif /* SUPPORT_UNICODE */
-static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc,
+static PCRE2_SPTR byte_sequence_compare(compiler_common *common, BOOL caseless, PCRE2_SPTR cc,
compare_context *context, jump_list **backtracks)
{
DEFINE_COMPILER;
unsigned int othercasebit = 0;
-pcre_uchar *othercasechar = NULL;
-#ifdef SUPPORT_UTF
+PCRE2_SPTR othercasechar = NULL;
+#ifdef SUPPORT_UNICODE
int utflength;
#endif
@@ -5290,25 +5312,25 @@ if (caseless && char_has_othercase(common, cc))
othercasebit = char_get_othercase_bit(common, cc);
SLJIT_ASSERT(othercasebit);
/* Extracting bit difference info. */
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
othercasechar = cc + (othercasebit >> 8);
othercasebit &= 0xff;
-#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
/* Note that this code only handles characters in the BMP. If there
ever are characters outside the BMP whose othercase differs in only one
bit from itself (there currently are none), this code will need to be
- revised for COMPILE_PCRE32. */
+ revised for PCRE2_CODE_UNIT_WIDTH == 32. */
othercasechar = cc + (othercasebit >> 9);
if ((othercasebit & 0x100) != 0)
othercasebit = (othercasebit & 0xff) << 8;
else
othercasebit &= 0xff;
-#endif /* COMPILE_PCRE[8|16|32] */
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
}
if (context->sourcereg == -1)
{
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
if (context->length >= 4)
OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
@@ -5317,20 +5339,20 @@ if (context->sourcereg == -1)
else
#endif
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
-#elif defined COMPILE_PCRE16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
if (context->length >= 4)
OP1(SLJIT_MOV_S32, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
else
#endif
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
-#elif defined COMPILE_PCRE32
+#elif PCRE2_CODE_UNIT_WIDTH == 32
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
-#endif /* COMPILE_PCRE[8|16|32] */
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16|32] */
context->sourcereg = TMP2;
}
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
utflength = 1;
if (common->utf && HAS_EXTRALEN(*cc))
utflength += GET_EXTRALEN(*cc);
@@ -5340,7 +5362,7 @@ do
#endif
context->length -= IN_UCHARS(1);
-#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) && (defined COMPILE_PCRE8 || defined COMPILE_PCRE16)
+#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)
/* Unaligned read is supported. */
if (othercasebit != 0 && othercasechar == cc)
@@ -5355,7 +5377,7 @@ do
}
context->ucharptr++;
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1))
#else
if (context->ucharptr >= 2 || context->length == 0)
@@ -5365,27 +5387,27 @@ do
OP1(SLJIT_MOV_S32, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
else if (context->length >= 2)
OP1(SLJIT_MOV_U16, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
else if (context->length >= 1)
OP1(SLJIT_MOV_U8, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
-#endif /* COMPILE_PCRE8 */
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
switch(context->ucharptr)
{
- case 4 / sizeof(pcre_uchar):
+ case 4 / sizeof(PCRE2_UCHAR):
if (context->oc.asint != 0)
OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));
break;
- case 2 / sizeof(pcre_uchar):
+ case 2 / sizeof(PCRE2_UCHAR):
if (context->oc.asushort != 0)
OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort);
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort));
break;
-#ifdef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
case 1:
if (context->oc.asbyte != 0)
OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);
@@ -5419,7 +5441,7 @@ do
#endif
cc++;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
utflength--;
}
while (utflength > 0);
@@ -5428,7 +5450,7 @@ while (utflength > 0);
return cc;
}
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
#define SET_TYPE_OFFSET(value) \
if ((value) != typeoffset) \
@@ -5450,22 +5472,22 @@ return cc;
} \
charoffset = (value);
-static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks, BOOL check_str_ptr);
+static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr);
-static void compile_xclass_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
+static void compile_xclass_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks)
{
DEFINE_COMPILER;
jump_list *found = NULL;
jump_list **list = (cc[0] & XCL_NOT) == 0 ? &found : backtracks;
sljit_uw c, charoffset, max = 256, min = READ_CHAR_MAX;
struct sljit_jump *jump = NULL;
-pcre_uchar *ccbegin;
+PCRE2_SPTR ccbegin;
int compares, invertcmp, numberofcmps;
-#if defined SUPPORT_UTF && (defined COMPILE_PCRE8 || defined COMPILE_PCRE16)
+#if defined SUPPORT_UNICODE && (PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16)
BOOL utf = common->utf;
#endif
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
BOOL charsaved = FALSE;
int typereg = TMP1;
@@ -5477,10 +5499,11 @@ sljit_uw typeoffset;
cc++;
ccbegin = cc;
compares = 0;
+
if (cc[-1] & XCL_MAP)
{
min = 0;
- cc += 32 / sizeof(pcre_uchar);
+ cc += 32 / sizeof(PCRE2_UCHAR);
}
while (*cc != XCL_END)
@@ -5492,7 +5515,7 @@ while (*cc != XCL_END)
GETCHARINCTEST(c, cc);
if (c > max) max = c;
if (c < min) min = c;
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
needschar = TRUE;
#endif
}
@@ -5503,11 +5526,11 @@ while (*cc != XCL_END)
if (c < min) min = c;
GETCHARINCTEST(c, cc);
if (c > max) max = c;
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
needschar = TRUE;
#endif
}
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
else
{
SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
@@ -5599,7 +5622,7 @@ if ((cc[-1] & XCL_HASPROP) == 0)
add_jump(compiler, backtracks, JUMP(SLJIT_JUMP));
JUMPHERE(jump);
- cc += 32 / sizeof(pcre_uchar);
+ cc += 32 / sizeof(PCRE2_UCHAR);
}
else
{
@@ -5610,12 +5633,12 @@ if ((cc[-1] & XCL_HASPROP) == 0)
else if ((cc[-1] & XCL_MAP) != 0)
{
OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
charsaved = TRUE;
#endif
if (!check_class_ranges(common, (const sljit_u8 *)cc, FALSE, TRUE, list))
{
-#ifdef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
jump = NULL;
if (common->utf)
#endif
@@ -5628,17 +5651,17 @@ else if ((cc[-1] & XCL_MAP) != 0)
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO));
-#ifdef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
#endif
JUMPHERE(jump);
}
OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
- cc += 32 / sizeof(pcre_uchar);
+ cc += 32 / sizeof(PCRE2_UCHAR);
}
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
if (needstype || needsscript)
{
if (needschar && !charsaved)
@@ -5718,7 +5741,7 @@ if (needstype || needsscript)
/* Generating code. */
charoffset = 0;
numberofcmps = 0;
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
typeoffset = 0;
#endif
@@ -5778,7 +5801,7 @@ while (*cc != XCL_END)
numberofcmps = 0;
}
}
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
else
{
SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
@@ -6002,14 +6025,14 @@ if (found != NULL)
#endif
-static pcre_uchar *compile_simple_assertion_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks)
+static PCRE2_SPTR compile_simple_assertion_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks)
{
DEFINE_COMPILER;
int length;
struct sljit_jump *jump[4];
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
struct sljit_label *label;
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
switch(type)
{
@@ -6038,7 +6061,7 @@ switch(type)
{
OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
- if (common->mode == JIT_COMPILE)
+ if (common->mode == PCRE2_JIT_COMPLETE)
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_END, 0));
else
{
@@ -6106,8 +6129,8 @@ switch(type)
case OP_DOLL:
OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+ OP2(SLJIT_AND32 | SLJIT_SET_E, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
if (!common->endonly)
compile_simple_assertion_matchingpath(common, OP_EODN, cc, backtracks);
@@ -6121,8 +6144,8 @@ switch(type)
case OP_DOLLM:
jump[1] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+ OP2(SLJIT_AND32 | SLJIT_SET_E, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
check_partial(common, FALSE);
jump[0] = JUMP(SLJIT_JUMP);
JUMPHERE(jump[1]);
@@ -6131,7 +6154,7 @@ switch(type)
{
OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
- if (common->mode == JIT_COMPILE)
+ if (common->mode == PCRE2_JIT_COMPLETE)
add_jump(compiler, backtracks, CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0));
else
{
@@ -6159,20 +6182,22 @@ switch(type)
OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
- OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+ OP2(SLJIT_AND32 | SLJIT_SET_E, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
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_GREATER, STR_PTR, 0, TMP1, 0);
- OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
- add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+ OP2(SLJIT_AND32 | SLJIT_SET_E, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
jump[0] = JUMP(SLJIT_JUMP);
JUMPHERE(jump[1]);
- add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+ if (!common->alt_circumflex)
+ add_jump(compiler, backtracks, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
if (common->nltype == NLTYPE_FIXED && common->newline > 255)
{
OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
@@ -6196,7 +6221,7 @@ switch(type)
if (length == 0)
return cc + LINK_SIZE;
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf)
{
OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
@@ -6221,7 +6246,7 @@ SLJIT_ASSERT_STOP();
return cc;
}
-static pcre_uchar *compile_char1_matchingpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks, BOOL check_str_ptr)
+static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr)
{
DEFINE_COMPILER;
int length;
@@ -6229,12 +6254,10 @@ unsigned int c, oc, bit;
compare_context context;
struct sljit_jump *jump[3];
jump_list *end_list;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
struct sljit_label *label;
-#ifdef SUPPORT_UCP
-pcre_uchar propdata[5];
-#endif
-#endif /* SUPPORT_UTF */
+PCRE2_UCHAR propdata[5];
+#endif /* SUPPORT_UNICODE */
switch(type)
{
@@ -6243,8 +6266,8 @@ switch(type)
/* Digits are usually 0-9, so it is worth to optimize them. */
if (check_str_ptr)
detect_partial_match(common, backtracks);
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
- if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_digit, FALSE))
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
+ if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_digit, FALSE))
read_char7_type(common, type == OP_NOT_DIGIT);
else
#endif
@@ -6258,8 +6281,8 @@ switch(type)
case OP_WHITESPACE:
if (check_str_ptr)
detect_partial_match(common, backtracks);
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
- if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_space, FALSE))
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
+ if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_space, FALSE))
read_char7_type(common, type == OP_NOT_WHITESPACE);
else
#endif
@@ -6272,8 +6295,8 @@ switch(type)
case OP_WORDCHAR:
if (check_str_ptr)
detect_partial_match(common, backtracks);
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
- if (common->utf && is_char7_bitset((const sljit_u8 *)common->ctypes - cbit_length + cbit_word, FALSE))
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
+ if (common->utf && is_char7_bitset((const sljit_u8*)common->ctypes - cbit_length + cbit_word, FALSE))
read_char7_type(common, type == OP_NOT_WORDCHAR);
else
#endif
@@ -6290,7 +6313,7 @@ switch(type)
{
jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
end_list = NULL;
- if (common->mode != JIT_PARTIAL_HARD_COMPILE)
+ if (common->mode != PCRE2_JIT_PARTIAL_HARD)
add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
else
check_str_end(common, &end_list);
@@ -6307,17 +6330,17 @@ switch(type)
case OP_ALLANY:
if (check_str_ptr)
detect_partial_match(common, backtracks);
-#ifdef SUPPORT_UTF
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
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));
-#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8 || PCRE2_CODE_UNIT_WIDTH == 16
+#if PCRE2_CODE_UNIT_WIDTH == 8
jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xc0);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(utf8_table4) - 0xc0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
-#elif defined COMPILE_PCRE16
+#elif PCRE2_CODE_UNIT_WIDTH == 16
jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
@@ -6326,7 +6349,7 @@ switch(type)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
#endif
JUMPHERE(jump[0]);
-#endif /* COMPILE_PCRE[8|16] */
+#endif /* PCRE2_CODE_UNIT_WIDTH == [8|16] */
return cc;
}
#endif
@@ -6339,8 +6362,7 @@ switch(type)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
return cc;
-#ifdef SUPPORT_UTF
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
case OP_NOTPROP:
case OP_PROP:
propdata[0] = XCL_HASPROP;
@@ -6353,7 +6375,6 @@ switch(type)
compile_xclass_matchingpath(common, propdata, backtracks);
return cc + 2;
#endif
-#endif
case OP_ANYNL:
if (check_str_ptr)
@@ -6362,7 +6383,7 @@ switch(type)
jump[0] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
/* We don't need to handle soft partial matching case. */
end_list = NULL;
- if (common->mode != JIT_PARTIAL_HARD_COMPILE)
+ if (common->mode != PCRE2_JIT_PARTIAL_HARD)
add_jump(compiler, &end_list, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
else
check_str_end(common, &end_list);
@@ -6395,7 +6416,7 @@ switch(type)
add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_NOT_ZERO : SLJIT_ZERO));
return cc;
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
case OP_EXTUNI:
if (check_str_ptr)
detect_partial_match(common, backtracks);
@@ -6425,7 +6446,7 @@ switch(type)
JUMPHERE(jump[0]);
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
- if (common->mode == JIT_PARTIAL_HARD_COMPILE)
+ if (common->mode == PCRE2_JIT_PARTIAL_HARD)
{
jump[0] = CMP(SLJIT_LESS, STR_PTR, 0, STR_END, 0);
/* Since we successfully read a char above, partial matching must occure. */
@@ -6438,10 +6459,10 @@ switch(type)
case OP_CHAR:
case OP_CHARI:
length = 1;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc);
#endif
- if (common->mode == JIT_COMPILE && check_str_ptr
+ if (common->mode == PCRE2_JIT_COMPLETE && check_str_ptr
&& (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));
@@ -6457,7 +6478,7 @@ switch(type)
if (check_str_ptr)
detect_partial_match(common, backtracks);
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf)
{
GETCHAR(c, cc);
@@ -6490,11 +6511,12 @@ switch(type)
case OP_NOTI:
if (check_str_ptr)
detect_partial_match(common, backtracks);
+
length = 1;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf)
{
-#ifdef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
c = *cc;
if (c < 128)
{
@@ -6516,13 +6538,13 @@ switch(type)
return cc + 1;
}
else
-#endif /* COMPILE_PCRE8 */
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
{
GETCHARLEN(c, cc, length);
}
}
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
c = *cc;
if (type == OP_NOT || !char_has_othercase(common, cc))
@@ -6553,7 +6575,7 @@ switch(type)
if (check_str_ptr)
detect_partial_match(common, backtracks);
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
bit = (common->utf && is_char7_bitset((const sljit_u8 *)cc, type == OP_NCLASS)) ? 127 : 255;
read_char_range(common, 0, bit, type == OP_NCLASS);
#else
@@ -6561,9 +6583,9 @@ switch(type)
#endif
if (check_class_ranges(common, (const sljit_u8 *)cc, type == OP_NCLASS, FALSE, backtracks))
- return cc + 32 / sizeof(pcre_uchar);
+ return cc + 32 / sizeof(PCRE2_UCHAR);
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
jump[0] = NULL;
if (common->utf)
{
@@ -6574,14 +6596,14 @@ switch(type)
jump[0] = NULL;
}
}
-#elif !defined COMPILE_PCRE8
+#elif PCRE2_CODE_UNIT_WIDTH != 8
jump[0] = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255);
if (type == OP_CLASS)
{
add_jump(compiler, backtracks, jump[0]);
jump[0] = NULL;
}
-#endif /* SUPPORT_UTF && COMPILE_PCRE8 */
+#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */
OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
@@ -6590,13 +6612,13 @@ switch(type)
OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
if (jump[0] != NULL)
JUMPHERE(jump[0]);
#endif
- return cc + 32 / sizeof(pcre_uchar);
+ return cc + 32 / sizeof(PCRE2_UCHAR);
-#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
case OP_XCLASS:
if (check_str_ptr)
detect_partial_match(common, backtracks);
@@ -6608,12 +6630,12 @@ SLJIT_ASSERT_STOP();
return cc;
}
-static SLJIT_INLINE pcre_uchar *compile_charn_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **backtracks)
+static SLJIT_INLINE PCRE2_SPTR compile_charn_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, jump_list **backtracks)
{
/* This function consumes at least one input character. */
/* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
DEFINE_COMPILER;
-pcre_uchar *ccbegin = cc;
+PCRE2_SPTR ccbegin = cc;
compare_context context;
int size;
@@ -6626,7 +6648,7 @@ do
if (*cc == OP_CHAR)
{
size = 1;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(cc[1]))
size += GET_EXTRALEN(cc[1]);
#endif
@@ -6634,7 +6656,7 @@ do
else if (*cc == OP_CHARI)
{
size = 1;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf)
{
if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
@@ -6675,7 +6697,7 @@ return compile_char1_matchingpath(common, *cc, cc + 1, backtracks, TRUE);
}
/* Forward definitions. */
-static void compile_matchingpath(compiler_common *, pcre_uchar *, pcre_uchar *, backtrack_common *);
+static void compile_matchingpath(compiler_common *, PCRE2_SPTR, PCRE2_SPTR, backtrack_common *);
static void compile_backtrackingpath(compiler_common *, struct backtrack_common *);
#define PUSH_BACKTRACK(size, ccstart, error) \
@@ -6706,12 +6728,12 @@ static void compile_backtrackingpath(compiler_common *, struct backtrack_common
#define BACKTRACK_AS(type) ((type *)backtrack)
-static void compile_dnref_search(compiler_common *common, pcre_uchar *cc, jump_list **backtracks)
+static void compile_dnref_search(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks)
{
/* The OVECTOR offset goes to TMP2. */
DEFINE_COMPILER;
int count = GET2(cc, 1 + IMM2_SIZE);
-pcre_uchar *slot = common->name_table + GET2(cc, 1) * common->name_entry_size;
+PCRE2_SPTR slot = common->name_table + GET2(cc, 1) * common->name_entry_size;
unsigned int offset;
jump_list *found = NULL;
@@ -6730,13 +6752,13 @@ while (count-- > 0)
offset = GET2(slot, 0) << 1;
GET_LOCAL_BASE(TMP2, 0, OVECTOR(offset));
-if (backtracks != NULL && !common->jscript_compat)
+if (backtracks != NULL && !common->unset_backref)
add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP1, 0));
set_jumps(found, LABEL());
}
-static void compile_ref_matchingpath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail)
+static void compile_ref_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail)
{
DEFINE_COMPILER;
BOOL ref = (*cc == OP_REF || *cc == OP_REFI);
@@ -6750,13 +6772,13 @@ if (ref)
offset = GET2(cc, 1) << 1;
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
/* OVECTOR(1) contains the "string begin - 1" constant. */
- if (withchecks && !common->jscript_compat)
+ if (withchecks && !common->unset_backref)
add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(1)));
}
else
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), 0);
-#if defined SUPPORT_UTF && defined SUPPORT_UCP
+#if defined SUPPORT_UNICODE
if (common->utf && *cc == OP_REFI)
{
SLJIT_ASSERT(TMP1 == SLJIT_R0 && STACK_TOP == SLJIT_R1 && TMP2 == SLJIT_R2);
@@ -6771,10 +6793,10 @@ if (common->utf && *cc == OP_REFI)
/* Needed to save important temporary registers. */
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STACK_TOP, 0);
OP1(SLJIT_MOV, SLJIT_R1, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, uchar_ptr), STR_PTR, 0);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_R1), SLJIT_OFFSETOF(jit_arguments, startchar_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_SP), LOCALS0);
- if (common->mode == JIT_COMPILE)
+ if (common->mode == PCRE2_JIT_COMPLETE)
add_jump(compiler, backtracks, CMP(SLJIT_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1));
else
{
@@ -6787,7 +6809,7 @@ if (common->utf && *cc == OP_REFI)
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
}
else
-#endif /* SUPPORT_UTF && SUPPORT_UCP */
+#endif /* SUPPORT_UNICODE */
{
if (ref)
OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);
@@ -6799,13 +6821,13 @@ else
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
partial = CMP(SLJIT_GREATER, STR_PTR, 0, STR_END, 0);
- if (common->mode == JIT_COMPILE)
+ if (common->mode == PCRE2_JIT_COMPLETE)
add_jump(compiler, backtracks, partial);
add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
- if (common->mode != JIT_COMPILE)
+ if (common->mode != PCRE2_JIT_COMPLETE)
{
nopartial = JUMP(SLJIT_JUMP);
JUMPHERE(partial);
@@ -6832,17 +6854,17 @@ if (jump != NULL)
}
}
-static SLJIT_INLINE pcre_uchar *compile_ref_iterator_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+static SLJIT_INLINE PCRE2_SPTR compile_ref_iterator_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)
{
DEFINE_COMPILER;
BOOL ref = (*cc == OP_REF || *cc == OP_REFI);
backtrack_common *backtrack;
-pcre_uchar type;
+PCRE2_UCHAR type;
int offset = 0;
struct sljit_label *label;
struct sljit_jump *zerolength;
struct sljit_jump *jump = NULL;
-pcre_uchar *ccbegin = cc;
+PCRE2_SPTR ccbegin = cc;
int min = 0, max = 0;
BOOL minimize;
@@ -7039,14 +7061,14 @@ count_match(common);
return cc;
}
-static SLJIT_INLINE pcre_uchar *compile_recurse_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+static SLJIT_INLINE PCRE2_SPTR compile_recurse_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
recurse_entry *entry = common->entries;
recurse_entry *prev = NULL;
sljit_sw start = GET(cc, 1);
-pcre_uchar *start_cc;
+PCRE2_SPTR start_cc;
BOOL needs_control_head;
PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL);
@@ -7108,61 +7130,58 @@ add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IM
return cc + 1 + LINK_SIZE;
}
-static int SLJIT_CALL do_callout(struct jit_arguments *arguments, PUBL(callout_block) *callout_block, pcre_uchar **jit_ovector)
+static int SLJIT_CALL do_callout(struct jit_arguments *arguments, pcre2_callout_block *callout_block, PCRE2_SPTR *jit_ovector)
{
-const pcre_uchar *begin = arguments->begin;
-int *offset_vector = arguments->offsets;
-int offset_count = arguments->offset_count;
-int i;
+PCRE2_SPTR begin = arguments->begin;
+PCRE2_SIZE *ovector = arguments->match_data->ovector;
+sljit_u32 oveccount = arguments->oveccount;
+sljit_u32 i;
-if (PUBL(callout) == NULL)
+if (arguments->callout == NULL)
return 0;
-callout_block->version = 2;
-callout_block->callout_data = arguments->callout_data;
+callout_block->version = 1;
/* Offsets in subject. */
callout_block->subject_length = arguments->end - arguments->begin;
-callout_block->start_match = (pcre_uchar*)callout_block->subject - arguments->begin;
-callout_block->current_position = (pcre_uchar*)callout_block->offset_vector - arguments->begin;
-#if defined COMPILE_PCRE8
-callout_block->subject = (PCRE_SPTR)begin;
-#elif defined COMPILE_PCRE16
-callout_block->subject = (PCRE_SPTR16)begin;
-#elif defined COMPILE_PCRE32
-callout_block->subject = (PCRE_SPTR32)begin;
-#endif
+callout_block->start_match = (PCRE2_SPTR)callout_block->subject - arguments->begin;
+callout_block->current_position = (PCRE2_SPTR)callout_block->offset_vector - arguments->begin;
+callout_block->subject = begin;
-/* Convert and copy the JIT offset vector to the offset_vector array. */
+/* Convert and copy the JIT offset vector to the ovector array. */
callout_block->capture_top = 0;
-callout_block->offset_vector = offset_vector;
-for (i = 2; i < offset_count; i += 2)
+callout_block->offset_vector = ovector;
+for (i = 2; i < oveccount; i += 2)
{
- offset_vector[i] = jit_ovector[i] - begin;
- offset_vector[i + 1] = jit_ovector[i + 1] - begin;
+ ovector[i] = jit_ovector[i] - begin;
+ ovector[i + 1] = jit_ovector[i + 1] - begin;
if (jit_ovector[i] >= begin)
callout_block->capture_top = i;
}
callout_block->capture_top = (callout_block->capture_top >> 1) + 1;
-if (offset_count > 0)
- offset_vector[0] = -1;
-if (offset_count > 1)
- offset_vector[1] = -1;
-return (*PUBL(callout))(callout_block);
+ovector[0] = PCRE2_UNSET;
+ovector[1] = PCRE2_UNSET;
+return (arguments->callout)(callout_block, arguments->callout_data);
}
/* Aligning to 8 byte. */
#define CALLOUT_ARG_SIZE \
- (((int)sizeof(PUBL(callout_block)) + 7) & ~7)
+ (((int)sizeof(pcre2_callout_block) + 7) & ~7)
#define CALLOUT_ARG_OFFSET(arg) \
- (-CALLOUT_ARG_SIZE + SLJIT_OFFSETOF(PUBL(callout_block), arg))
+ (-CALLOUT_ARG_SIZE + SLJIT_OFFSETOF(pcre2_callout_block, arg))
-static SLJIT_INLINE pcre_uchar *compile_callout_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+static SLJIT_INLINE PCRE2_SPTR compile_callout_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
+sljit_s32 mov_opcode;
+unsigned int callout_length = (*cc == OP_CALLOUT)
+ ? PRIV(OP_lengths)[OP_CALLOUT] : GET(cc, 1 + 2 * LINK_SIZE);
+sljit_sw value1;
+sljit_sw value2;
+sljit_sw value3;
PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);
@@ -7171,8 +7190,9 @@ allocate_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw));
SLJIT_ASSERT(common->capture_last_ptr != 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr);
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, cc[1]);
-OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0);
+value1 = (*cc == OP_CALLOUT) ? cc[1 + 2 * LINK_SIZE] : 0;
+OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, value1);
+OP1(SLJIT_MOV_U32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0);
/* These pointer sized fields temporarly stores internal variables. */
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
@@ -7181,8 +7201,26 @@ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(subject), TMP2, 0);
if (common->mark_ptr != 0)
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr));
-OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 2));
-OP1(SLJIT_MOV_S32, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 2 + LINK_SIZE));
+mov_opcode = (sizeof(PCRE2_SIZE) == 4) ? SLJIT_MOV_U32 : SLJIT_MOV;
+OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 1));
+OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 1 + LINK_SIZE));
+
+if (*cc == OP_CALLOUT)
+ {
+ value1 = 0;
+ value2 = 0;
+ value3 = 0;
+ }
+else
+ {
+ value1 = (sljit_sw) (cc + (1 + 4*LINK_SIZE) + 1);
+ value2 = (callout_length - (1 + 4*LINK_SIZE + 2));
+ value3 = (sljit_sw) (GET(cc, 1 + 3*LINK_SIZE));
+ }
+
+OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string), SLJIT_IMM, value1);
+OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string_length), SLJIT_IMM, value2);
+OP1(mov_opcode, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_string_offset), SLJIT_IMM, value3);
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0);
/* Needed to save important temporary registers. */
@@ -7201,18 +7239,22 @@ if (common->forced_quit_label == NULL)
add_jump(compiler, &common->forced_quit, JUMP(SLJIT_SIG_LESS));
else
JUMPTO(SLJIT_SIG_LESS, common->forced_quit_label);
-return cc + 2 + 2 * LINK_SIZE;
+return cc + callout_length;
}
#undef CALLOUT_ARG_SIZE
#undef CALLOUT_ARG_OFFSET
-static SLJIT_INLINE BOOL assert_needs_str_ptr_saving(pcre_uchar *cc)
+static SLJIT_INLINE BOOL assert_needs_str_ptr_saving(PCRE2_SPTR cc)
{
while (TRUE)
{
switch (*cc)
{
+ case OP_CALLOUT_STR:
+ cc += GET(cc, 1 + 2*LINK_SIZE);
+ break;
+
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
case OP_CIRC:
@@ -7233,7 +7275,7 @@ while (TRUE)
}
}
-static pcre_uchar *compile_assert_matchingpath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional)
+static PCRE2_SPTR compile_assert_matchingpath(compiler_common *common, PCRE2_SPTR cc, assert_backtrack *backtrack, BOOL conditional)
{
DEFINE_COMPILER;
int framesize;
@@ -7241,9 +7283,9 @@ int extrasize;
BOOL needs_control_head;
int private_data_ptr;
backtrack_common altbacktrack;
-pcre_uchar *ccbegin;
-pcre_uchar opcode;
-pcre_uchar bra = OP_BRA;
+PCRE2_SPTR ccbegin;
+PCRE2_UCHAR opcode;
+PCRE2_UCHAR bra = OP_BRA;
jump_list *tmp = NULL;
jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks;
jump_list **found;
@@ -7655,7 +7697,7 @@ common->accept = save_accept;
return cc + 1 + LINK_SIZE;
}
-static SLJIT_INLINE void match_once_common(compiler_common *common, pcre_uchar ket, int framesize, int private_data_ptr, BOOL has_alternatives, BOOL needs_control_head)
+static SLJIT_INLINE void match_once_common(compiler_common *common, PCRE2_UCHAR ket, int framesize, int private_data_ptr, BOOL has_alternatives, BOOL needs_control_head)
{
DEFINE_COMPILER;
int stacksize;
@@ -7782,21 +7824,21 @@ return stacksize;
Or nothing, if trace is unnecessary
*/
-static pcre_uchar *compile_bracket_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+static PCRE2_SPTR compile_bracket_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
-pcre_uchar opcode;
+PCRE2_UCHAR opcode;
int private_data_ptr = 0;
int offset = 0;
int i, stacksize;
int repeat_ptr = 0, repeat_length = 0;
int repeat_type = 0, repeat_count = 0;
-pcre_uchar *ccbegin;
-pcre_uchar *matchingpath;
-pcre_uchar *slot;
-pcre_uchar bra = OP_BRA;
-pcre_uchar ket;
+PCRE2_SPTR ccbegin;
+PCRE2_SPTR matchingpath;
+PCRE2_SPTR slot;
+PCRE2_UCHAR bra = OP_BRA;
+PCRE2_UCHAR ket;
assert_backtrack *assert;
BOOL has_alternatives;
BOOL needs_control_head = FALSE;
@@ -7831,13 +7873,6 @@ if (ket == OP_KET && PRIVATE_DATA(matchingpath) != 0)
ket = OP_KETRMIN;
}
-if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)
- {
- /* Drop this bracket_backtrack. */
- parent->top = backtrack->prev;
- return matchingpath + 1 + LINK_SIZE + repeat_length;
- }
-
matchingpath = ccbegin + 1 + LINK_SIZE;
SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);
SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));
@@ -7845,7 +7880,11 @@ cc += GET(cc, 1);
has_alternatives = *cc == OP_ALT;
if (SLJIT_UNLIKELY(opcode == OP_COND || opcode == OP_SCOND))
- has_alternatives = (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF || *matchingpath == OP_FAIL) ? FALSE : TRUE;
+ {
+ SLJIT_COMPILE_ASSERT(OP_DNRREF == OP_RREF + 1 && OP_FALSE == OP_RREF + 2 && OP_TRUE == OP_RREF + 3,
+ compile_time_checks_must_be_grouped_together);
+ has_alternatives = ((*matchingpath >= OP_RREF && *matchingpath <= OP_TRUE) || *matchingpath == OP_FAIL) ? FALSE : TRUE;
+ }
if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
opcode = OP_SCOND;
@@ -8103,15 +8142,20 @@ if (opcode == OP_COND || opcode == OP_SCOND)
add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), JUMP(SLJIT_ZERO));
matchingpath += 1 + 2 * IMM2_SIZE;
}
- else if (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF || *matchingpath == OP_FAIL)
+ else if ((*matchingpath >= OP_RREF && *matchingpath <= OP_TRUE) || *matchingpath == OP_FAIL)
{
/* Never has other case. */
BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL;
SLJIT_ASSERT(!has_alternatives);
- if (*matchingpath == OP_FAIL)
+ if (*matchingpath == OP_TRUE)
+ {
+ stacksize = 1;
+ matchingpath++;
+ }
+ else if (*matchingpath == OP_FALSE || *matchingpath == OP_FAIL)
stacksize = 0;
- if (*matchingpath == OP_RREF)
+ else if (*matchingpath == OP_RREF)
{
stacksize = GET2(matchingpath, 1);
if (common->currententry == NULL)
@@ -8327,11 +8371,11 @@ if (opcode == OP_ONCE)
return cc + repeat_length;
}
-static pcre_uchar *compile_bracketpos_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+static PCRE2_SPTR compile_bracketpos_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
-pcre_uchar opcode;
+PCRE2_UCHAR opcode;
int private_data_ptr;
int cbraprivptr = 0;
BOOL needs_control_head;
@@ -8339,7 +8383,7 @@ int framesize;
int stacksize;
int offset = 0;
BOOL zero = FALSE;
-pcre_uchar *ccbegin = NULL;
+PCRE2_SPTR ccbegin = NULL;
int stack; /* Also contains the offset of control head. */
struct sljit_label *loop = NULL;
struct jump_list *emptymatch = NULL;
@@ -8610,7 +8654,7 @@ count_match(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, sljit_u32 *max, sljit_u32 *exact, pcre_uchar **end)
+static SLJIT_INLINE PCRE2_SPTR get_iterator_parameters(compiler_common *common, PCRE2_SPTR cc, PCRE2_UCHAR *opcode, PCRE2_UCHAR *type, sljit_u32 *max, sljit_u32 *exact, PCRE2_SPTR *end)
{
int class_len;
@@ -8651,7 +8695,7 @@ else
SLJIT_ASSERT(*opcode == OP_CLASS || *opcode == OP_NCLASS || *opcode == OP_XCLASS);
*type = *opcode;
cc++;
- class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0);
+ class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(PCRE2_UCHAR))) : GET(cc, 0);
*opcode = cc[class_len - 1];
if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY)
@@ -8749,25 +8793,25 @@ if (*type == OP_END)
}
*end = cc + 1;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc);
#endif
return cc;
}
-static pcre_uchar *compile_iterator_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+static PCRE2_SPTR compile_iterator_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
-pcre_uchar opcode;
-pcre_uchar type;
+PCRE2_UCHAR opcode;
+PCRE2_UCHAR type;
sljit_u32 max = 0, exact;
BOOL fast_fail;
sljit_s32 fast_str_ptr;
BOOL charpos_enabled;
-pcre_uchar charpos_char;
+PCRE2_UCHAR charpos_char;
unsigned int charpos_othercasebit;
-pcre_uchar *end;
+PCRE2_SPTR end;
jump_list *no_match = NULL;
jump_list *no_char1_match = NULL;
struct sljit_jump *jump = NULL;
@@ -8813,8 +8857,8 @@ if (fast_fail && fast_str_ptr != 0)
if (exact > 1)
{
SLJIT_ASSERT(fast_str_ptr == 0);
- if (common->mode == JIT_COMPILE
-#ifdef SUPPORT_UTF
+ if (common->mode == PCRE2_JIT_COMPLETE
+#ifdef SUPPORT_UNICODE
&& !common->utf
#endif
)
@@ -8883,7 +8927,7 @@ switch(opcode)
if ((type != OP_CHAR && type != OP_CHARI) && (*end == OP_CHAR || *end == OP_CHARI))
{
charpos_enabled = TRUE;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
charpos_enabled = !common->utf || !HAS_EXTRALEN(end[1]);
#endif
if (charpos_enabled && *end == OP_CHARI && char_has_othercase(common, end + 1))
@@ -8898,9 +8942,9 @@ switch(opcode)
charpos_char = end[1];
/* Consumpe the OP_CHAR opcode. */
end += 2;
-#if defined COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
SLJIT_ASSERT((charpos_othercasebit >> 8) == 0);
-#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
SLJIT_ASSERT((charpos_othercasebit >> 9) == 0);
if ((charpos_othercasebit & 0x100) != 0)
charpos_othercasebit = (charpos_othercasebit & 0xff) << 8;
@@ -8982,7 +9026,7 @@ switch(opcode)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
OP1(SLJIT_MOV, base, offset0, STR_PTR, 0);
}
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
else if (common->utf)
{
if (private_data_ptr == 0)
@@ -9077,7 +9121,7 @@ switch(opcode)
break;
case OP_POSSTAR:
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf)
{
OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0);
@@ -9105,7 +9149,7 @@ switch(opcode)
case OP_POSUPTO:
SLJIT_ASSERT(fast_str_ptr == 0);
-#if defined SUPPORT_UTF && !defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf)
{
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE1, STR_PTR, 0);
@@ -9150,7 +9194,7 @@ count_match(common);
return end;
}
-static SLJIT_INLINE pcre_uchar *compile_fail_accept_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+static SLJIT_INLINE PCRE2_SPTR compile_fail_accept_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
@@ -9178,13 +9222,14 @@ if (common->accept_label == NULL)
else
CMPTO(SLJIT_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), common->accept_label);
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
-OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
-add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
-OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
+OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));
+OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);
+add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_NOT_ZERO));
+OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);
if (common->accept_label == NULL)
- add_jump(compiler, &common->accept, CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
+ add_jump(compiler, &common->accept, JUMP(SLJIT_ZERO));
else
- CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->accept_label);
+ JUMPTO(SLJIT_ZERO, common->accept_label);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
if (common->accept_label == NULL)
add_jump(compiler, &common->accept, CMP(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0));
@@ -9194,7 +9239,7 @@ add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP));
return cc + 1;
}
-static SLJIT_INLINE pcre_uchar *compile_close_matchingpath(compiler_common *common, pcre_uchar *cc)
+static SLJIT_INLINE PCRE2_SPTR compile_close_matchingpath(compiler_common *common, PCRE2_SPTR cc)
{
DEFINE_COMPILER;
int offset = GET2(cc, 1);
@@ -9213,12 +9258,12 @@ if (!optimized_cbracket)
return cc + 1 + IMM2_SIZE;
}
-static SLJIT_INLINE pcre_uchar *compile_control_verb_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent)
+static SLJIT_INLINE PCRE2_SPTR compile_control_verb_matchingpath(compiler_common *common, PCRE2_SPTR cc, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
-pcre_uchar opcode = *cc;
-pcre_uchar *ccend = cc + 1;
+PCRE2_UCHAR opcode = *cc;
+PCRE2_SPTR ccend = cc + 1;
if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG)
ccend += 2 + cc[1];
@@ -9243,9 +9288,9 @@ if (opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG)
return ccend;
}
-static pcre_uchar then_trap_opcode[1] = { OP_THEN_TRAP };
+static PCRE2_UCHAR then_trap_opcode[1] = { OP_THEN_TRAP };
-static SLJIT_INLINE void compile_then_trap_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent)
+static SLJIT_INLINE void compile_then_trap_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
@@ -9276,7 +9321,7 @@ if (size >= 0)
init_frame(common, cc, ccend, size - 1, 0, FALSE);
}
-static void compile_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent)
+static void compile_matchingpath(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, backtrack_common *parent)
{
DEFINE_COMPILER;
backtrack_common *backtrack;
@@ -9345,7 +9390,7 @@ while (cc < ccend)
case OP_CHAR:
case OP_CHARI:
- if (common->mode == JIT_COMPILE)
+ if (common->mode == PCRE2_JIT_COMPLETE)
cc = compile_charn_matchingpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks);
else
cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);
@@ -9421,13 +9466,13 @@ while (cc < ccend)
case OP_CLASS:
case OP_NCLASS:
- if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRPOSRANGE)
+ if (cc[1 + (32 / sizeof(PCRE2_UCHAR))] >= OP_CRSTAR && cc[1 + (32 / sizeof(PCRE2_UCHAR))] <= OP_CRPOSRANGE)
cc = compile_iterator_matchingpath(common, cc, parent);
else
cc = compile_char1_matchingpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE);
break;
-#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
case OP_XCLASS:
if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRPOSRANGE)
cc = compile_iterator_matchingpath(common, cc, parent);
@@ -9464,6 +9509,7 @@ while (cc < ccend)
break;
case OP_CALLOUT:
+ case OP_CALLOUT_STR:
cc = compile_callout_matchingpath(common, cc, parent);
break;
@@ -9605,14 +9651,14 @@ SLJIT_ASSERT(cc == ccend);
static void compile_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)
{
DEFINE_COMPILER;
-pcre_uchar *cc = current->cc;
-pcre_uchar opcode;
-pcre_uchar type;
+PCRE2_SPTR cc = current->cc;
+PCRE2_UCHAR opcode;
+PCRE2_UCHAR type;
sljit_u32 max = 0, exact;
struct sljit_label *label = NULL;
struct sljit_jump *jump = NULL;
jump_list *jumplist = NULL;
-pcre_uchar *end;
+PCRE2_SPTR end;
int private_data_ptr = PRIVATE_DATA(cc);
int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP);
int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr;
@@ -9733,9 +9779,9 @@ set_jumps(current->topbacktracks, LABEL());
static SLJIT_INLINE void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current)
{
DEFINE_COMPILER;
-pcre_uchar *cc = current->cc;
+PCRE2_SPTR cc = current->cc;
BOOL ref = (*cc == OP_REF || *cc == OP_REFI);
-pcre_uchar type;
+PCRE2_UCHAR type;
type = cc[ref ? 1 + IMM2_SIZE : 1 + 2 * IMM2_SIZE];
@@ -9784,8 +9830,8 @@ else if (common->has_set_som || common->mark_ptr != 0)
static void compile_assert_backtrackingpath(compiler_common *common, struct backtrack_common *current)
{
DEFINE_COMPILER;
-pcre_uchar *cc = current->cc;
-pcre_uchar bra = OP_BRA;
+PCRE2_SPTR cc = current->cc;
+PCRE2_UCHAR bra = OP_BRA;
struct sljit_jump *brajump = NULL;
SLJIT_ASSERT(*cc != OP_BRAMINZERO);
@@ -9855,11 +9901,11 @@ int opcode, stacksize, alt_count, alt_max;
int offset = 0;
int private_data_ptr = CURRENT_AS(bracket_backtrack)->private_data_ptr;
int repeat_ptr = 0, repeat_type = 0, repeat_count = 0;
-pcre_uchar *cc = current->cc;
-pcre_uchar *ccbegin;
-pcre_uchar *ccprev;
-pcre_uchar bra = OP_BRA;
-pcre_uchar ket;
+PCRE2_SPTR cc = current->cc;
+PCRE2_SPTR ccbegin;
+PCRE2_SPTR ccprev;
+PCRE2_UCHAR bra = OP_BRA;
+PCRE2_UCHAR ket;
assert_backtrack *assert;
sljit_uw *next_update_addr = NULL;
BOOL has_alternatives;
@@ -10376,7 +10422,7 @@ SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks);
static SLJIT_INLINE void compile_control_verb_backtrackingpath(compiler_common *common, struct backtrack_common *current)
{
DEFINE_COMPILER;
-pcre_uchar opcode = *current->cc;
+PCRE2_UCHAR opcode = *current->cc;
struct sljit_label *loop;
struct sljit_jump *jump;
@@ -10550,7 +10596,7 @@ while (current)
case OP_TYPEPOSUPTO:
case OP_CLASS:
case OP_NCLASS:
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
case OP_XCLASS:
#endif
compile_iterator_backtrackingpath(common, current);
@@ -10625,7 +10671,7 @@ while (current)
case OP_COMMIT:
if (!common->local_exit)
- OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);
if (common->quit_label == NULL)
add_jump(compiler, &common->quit, JUMP(SLJIT_JUMP));
else
@@ -10633,6 +10679,7 @@ while (current)
break;
case OP_CALLOUT:
+ case OP_CALLOUT_STR:
case OP_FAIL:
case OP_ACCEPT:
case OP_ASSERT_ACCEPT:
@@ -10656,9 +10703,9 @@ common->then_trap = save_then_trap;
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) - (1 + LINK_SIZE);
+PCRE2_SPTR cc = common->start + common->currententry->start;
+PCRE2_SPTR ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE);
+PCRE2_SPTR ccend = bracketend(cc) - (1 + LINK_SIZE);
BOOL needs_control_head;
int framesize = get_framesize(common, cc, NULL, TRUE, &needs_control_head);
int private_data_size = get_private_data_copy_length(common, ccbegin, ccend, needs_control_head);
@@ -10781,17 +10828,17 @@ sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0);
#undef COMPILE_BACKTRACKINGPATH
#undef CURRENT_AS
-void
-PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra, int mode)
+static int jit_compile(pcre2_code *code, sljit_u32 mode)
{
+pcre2_real_code *re = (pcre2_real_code *)code;
struct sljit_compiler *compiler;
backtrack_common rootbacktrack;
compiler_common common_data;
compiler_common *common = &common_data;
const sljit_u8 *tables = re->tables;
-pcre_study_data *study;
+void *allocator_data = &re->memctl;
int private_data_size;
-pcre_uchar *ccend;
+PCRE2_SPTR ccend;
executable_functions *functions;
void *executable_func;
sljit_uw executable_size;
@@ -10808,48 +10855,35 @@ struct sljit_jump *minlength_check_failed = NULL;
struct sljit_jump *reqbyte_notfound = NULL;
struct sljit_jump *empty_match = NULL;
-SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0);
-study = extra->study_data;
-
-if (!tables)
- tables = PRIV(default_tables);
+SLJIT_ASSERT(tables);
memset(&rootbacktrack, 0, sizeof(backtrack_common));
memset(common, 0, sizeof(compiler_common));
-rootbacktrack.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size;
+common->name_table = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code));
+rootbacktrack.cc = common->name_table + re->name_count * re->name_entry_size;
common->start = rootbacktrack.cc;
common->read_only_data_head = NULL;
common->fcc = tables + fcc_offset;
common->lcc = (sljit_sw)(tables + lcc_offset);
common->mode = mode;
-common->might_be_empty = study->minlength == 0;
+common->might_be_empty = re->minlength == 0;
common->nltype = NLTYPE_FIXED;
-switch(re->options & PCRE_NEWLINE_BITS)
+switch(re->newline_convention)
{
- 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;
+ case PCRE2_NEWLINE_CR: common->newline = CHAR_CR; break;
+ case PCRE2_NEWLINE_LF: common->newline = CHAR_NL; break;
+ case PCRE2_NEWLINE_CRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; break;
+ case PCRE2_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
+ case PCRE2_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
+ default: return PCRE2_ERROR_INTERNAL;
}
common->nlmax = READ_CHAR_MAX;
common->nlmin = 0;
-if ((re->options & PCRE_BSR_ANYCRLF) != 0)
- common->bsr_nltype = NLTYPE_ANYCRLF;
-else if ((re->options & PCRE_BSR_UNICODE) != 0)
+if (re->bsr_convention == PCRE2_BSR_UNICODE)
common->bsr_nltype = NLTYPE_ANY;
+else if (re->bsr_convention == PCRE2_BSR_ANYCRLF)
+ common->bsr_nltype = NLTYPE_ANYCRLF;
else
{
#ifdef BSR_ANYCRLF
@@ -10860,18 +10894,16 @@ else
}
common->bsr_nlmax = READ_CHAR_MAX;
common->bsr_nlmin = 0;
-common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
+common->endonly = (re->overall_options & PCRE2_DOLLAR_ENDONLY) != 0;
common->ctypes = (sljit_sw)(tables + ctypes_offset);
-common->name_table = ((pcre_uchar *)re) + re->name_table_offset;
common->name_count = re->name_count;
common->name_entry_size = re->name_entry_size;
-common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
-#ifdef SUPPORT_UTF
+common->unset_backref = (re->overall_options & PCRE2_MATCH_UNSET_BACKREF) != 0;
+common->alt_circumflex = (re->overall_options & PCRE2_ALT_CIRCUMFLEX) != 0;
+#ifdef SUPPORT_UNICODE
/* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */
-common->utf = (re->options & PCRE_UTF8) != 0;
-#ifdef SUPPORT_UCP
-common->use_ucp = (re->options & PCRE_UCP) != 0;
-#endif
+common->utf = (re->overall_options & PCRE2_UTF) != 0;
+common->use_ucp = (re->overall_options & PCRE2_UCP) != 0;
if (common->utf)
{
if (common->nltype == NLTYPE_ANY)
@@ -10895,14 +10927,14 @@ if (common->utf)
common->bsr_nlmax = (CHAR_CR > CHAR_NL) ? CHAR_CR : CHAR_NL;
common->bsr_nlmin = (CHAR_CR < CHAR_NL) ? CHAR_CR : CHAR_NL;
}
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
ccend = bracketend(common->start);
/* Calculate the local space size on the stack. */
common->ovector_start = LIMIT_MATCH + sizeof(sljit_sw);
-common->optimized_cbracket = (sljit_u8 *)SLJIT_MALLOC(re->top_bracket + 1, compiler->allocator_data);
+common->optimized_cbracket = (sljit_u8 *)SLJIT_MALLOC(re->top_bracket + 1, allocator_data);
if (!common->optimized_cbracket)
- return;
+ return PCRE2_ERROR_NOMEMORY;
#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 1
memset(common->optimized_cbracket, 0, re->top_bracket + 1);
#else
@@ -10916,27 +10948,27 @@ common->ovector_start += sizeof(sljit_sw);
#endif
if (!check_opcode_types(common, common->start, ccend))
{
- SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
- return;
+ SLJIT_FREE(common->optimized_cbracket, allocator_data);
+ return PCRE2_ERROR_NOMEMORY;
}
/* Checking flags and updating ovector_start. */
-if (mode == JIT_COMPILE && (re->flags & PCRE_REQCHSET) != 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
+if (mode == PCRE2_JIT_COMPLETE && (re->flags & PCRE2_LASTSET) != 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
{
common->req_char_ptr = common->ovector_start;
common->ovector_start += sizeof(sljit_sw);
}
-if (mode != JIT_COMPILE)
+if (mode != PCRE2_JIT_COMPLETE)
{
common->start_used_ptr = common->ovector_start;
common->ovector_start += sizeof(sljit_sw);
- if (mode == JIT_PARTIAL_SOFT_COMPILE)
+ if (mode == PCRE2_JIT_PARTIAL_SOFT)
{
common->hit_start = common->ovector_start;
- common->ovector_start += 2 * sizeof(sljit_sw);
+ common->ovector_start += sizeof(sljit_sw);
}
}
-if ((re->options & PCRE_FIRSTLINE) != 0)
+if ((re->overall_options & (PCRE2_FIRSTLINE | PCRE2_USE_OFFSET_LIMIT)) != 0)
{
common->match_end_ptr = common->ovector_start;
common->ovector_start += sizeof(sljit_sw);
@@ -10971,17 +11003,17 @@ SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw);
total_length = ccend - common->start;
-common->private_data_ptrs = (sljit_s32 *)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), compiler->allocator_data);
+common->private_data_ptrs = (sljit_s32 *)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), allocator_data);
if (!common->private_data_ptrs)
{
- SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
- return;
+ SLJIT_FREE(common->optimized_cbracket, allocator_data);
+ return PCRE2_ERROR_NOMEMORY;
}
memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_s32));
private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw);
set_private_data_ptrs(common, &private_data_size, ccend);
-if ((re->options & PCRE_ANCHORED) == 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
+if ((re->overall_options & PCRE2_ANCHORED) == 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
{
if (!detect_fast_forward_skip(common, &private_data_size) && !common->has_skip_in_assert_back)
detect_fast_fail(common, common->start, &private_data_size, 4);
@@ -10991,9 +11023,9 @@ SLJIT_ASSERT(common->fast_fail_start_ptr <= common->fast_fail_end_ptr);
if (private_data_size > SLJIT_MAX_LOCAL_SIZE)
{
- SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
- SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
- return;
+ SLJIT_FREE(common->private_data_ptrs, allocator_data);
+ SLJIT_FREE(common->optimized_cbracket, allocator_data);
+ return PCRE2_ERROR_NOMEMORY;
}
if (common->has_then)
@@ -11003,12 +11035,12 @@ if (common->has_then)
set_then_offsets(common, common->start, NULL);
}
-compiler = sljit_create_compiler(NULL);
+compiler = sljit_create_compiler(allocator_data);
if (!compiler)
{
- SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
- SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
- return;
+ SLJIT_FREE(common->optimized_cbracket, allocator_data);
+ SLJIT_FREE(common->private_data_ptrs, allocator_data);
+ return PCRE2_ERROR_NOMEMORY;
}
common->compiler = compiler;
@@ -11034,7 +11066,7 @@ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0);
if (common->fast_fail_start_ptr < common->fast_fail_end_ptr)
reset_fast_fail(common);
-if (mode == JIT_PARTIAL_SOFT_COMPILE)
+if (mode == PCRE2_JIT_PARTIAL_SOFT)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1);
if (common->mark_ptr != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->mark_ptr, SLJIT_IMM, 0);
@@ -11042,41 +11074,41 @@ if (common->control_head_ptr != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
/* Main part of the matching */
-if ((re->options & PCRE_ANCHORED) == 0)
+if ((re->overall_options & PCRE2_ANCHORED) == 0)
{
- mainloop_label = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0);
+ mainloop_label = mainloop_entry(common, (re->flags & PCRE2_HASCRORLF) != 0, re->overall_options);
continue_match_label = LABEL();
/* Forward search if possible. */
- if ((re->options & PCRE_NO_START_OPTIMIZE) == 0)
+ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
{
- if (mode == JIT_COMPILE && fast_forward_first_n_chars(common))
+ if (mode == PCRE2_JIT_COMPLETE && fast_forward_first_n_chars(common))
;
- else if ((re->flags & PCRE_FIRSTSET) != 0)
- fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0);
- else if ((re->flags & PCRE_STARTLINE) != 0)
+ else if ((re->flags & PCRE2_FIRSTSET) != 0)
+ fast_forward_first_char(common, (PCRE2_UCHAR)(re->first_codeunit), (re->flags & PCRE2_FIRSTCASELESS) != 0);
+ else if ((re->flags & PCRE2_STARTLINE) != 0)
fast_forward_newline(common);
- else if (study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)
- fast_forward_start_bits(common, study->start_bits);
+ else if ((re->flags & PCRE2_FIRSTMAPSET) != 0)
+ fast_forward_start_bits(common, re->start_bitmap);
}
}
else
continue_match_label = LABEL();
-if (mode == JIT_COMPILE && study->minlength > 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0)
+if (mode == PCRE2_JIT_COMPLETE && re->minlength > 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
{
- OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
- OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength));
+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);
+ OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(re->minlength));
minlength_check_failed = CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0);
}
if (common->req_char_ptr != 0)
- reqbyte_notfound = search_requested_char(common, (pcre_uchar)re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0);
+ reqbyte_notfound = search_requested_char(common, (PCRE2_UCHAR)(re->last_codeunit), (re->flags & PCRE2_LASTCASELESS) != 0, (re->flags & PCRE2_FIRSTSET) != 0);
/* Store the current STR_PTR in OVECTOR(0). */
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0);
/* Copy the limit of allowed recursions. */
OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH);
if (common->capture_last_ptr != 0)
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, -1);
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, 0);
if (common->fast_forward_bc_ptr != NULL)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), PRIVATE_DATA(common->fast_forward_bc_ptr + 1), STR_PTR, 0);
@@ -11084,24 +11116,23 @@ if (common->start_ptr != OVECTOR(0))
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_ptr, STR_PTR, 0);
/* Copy the beginning of the string. */
-if (mode == JIT_PARTIAL_SOFT_COMPILE)
+if (mode == PCRE2_JIT_PARTIAL_SOFT)
{
jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
- OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start + sizeof(sljit_sw), STR_PTR, 0);
JUMPHERE(jump);
}
-else if (mode == JIT_PARTIAL_HARD_COMPILE)
+else if (mode == PCRE2_JIT_PARTIAL_HARD)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, STR_PTR, 0);
compile_matchingpath(common, common->start, ccend, &rootbacktrack);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
{
sljit_free_compiler(compiler);
- SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
- SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
- free_read_only_data(common->read_only_data_head, compiler->allocator_data);
- return;
+ SLJIT_FREE(common->optimized_cbracket, allocator_data);
+ SLJIT_FREE(common->private_data_ptrs, allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ return PCRE2_ERROR_NOMEMORY;
}
if (common->might_be_empty)
@@ -11125,7 +11156,7 @@ if (minlength_check_failed != NULL)
SET_LABEL(minlength_check_failed, common->forced_quit_label);
sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0);
-if (mode != JIT_COMPILE)
+if (mode != PCRE2_JIT_COMPLETE)
{
common->partialmatchlabel = LABEL();
set_jumps(common->partialmatch, common->partialmatchlabel);
@@ -11138,55 +11169,64 @@ compile_backtrackingpath(common, rootbacktrack.top);
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
{
sljit_free_compiler(compiler);
- SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
- SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
- free_read_only_data(common->read_only_data_head, compiler->allocator_data);
- return;
+ SLJIT_FREE(common->optimized_cbracket, allocator_data);
+ SLJIT_FREE(common->private_data_ptrs, allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ return PCRE2_ERROR_NOMEMORY;
}
SLJIT_ASSERT(rootbacktrack.prev == NULL);
reset_match_label = LABEL();
-if (mode == JIT_PARTIAL_SOFT_COMPILE)
+if (mode == PCRE2_JIT_PARTIAL_SOFT)
{
/* Update hit_start only in the first time. */
jump = CMP(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, 0);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->start_ptr);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_used_ptr, SLJIT_IMM, -1);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, TMP1, 0);
JUMPHERE(jump);
}
/* Check we have remaining characters. */
-if ((re->options & PCRE_ANCHORED) == 0 && (re->options & PCRE_FIRSTLINE) != 0)
+if ((re->overall_options & PCRE2_ANCHORED) == 0 && common->match_end_ptr != 0)
{
- SLJIT_ASSERT(common->match_end_ptr != 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
}
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP),
(common->fast_forward_bc_ptr != NULL) ? (PRIVATE_DATA(common->fast_forward_bc_ptr + 1)) : common->start_ptr);
-if ((re->options & PCRE_ANCHORED) == 0)
+if ((re->overall_options & PCRE2_ANCHORED) == 0)
{
if (common->ff_newline_shortcut != NULL)
{
- if ((re->options & PCRE_FIRSTLINE) == 0)
- CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, common->ff_newline_shortcut);
- /* There cannot be more newlines here. */
+ /* There cannot be more newlines if PCRE2_FIRSTLINE is set. */
+ if ((re->overall_options & PCRE2_FIRSTLINE) == 0)
+ {
+ if (common->match_end_ptr != 0)
+ {
+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
+ OP1(SLJIT_MOV, STR_END, 0, TMP1, 0);
+ CMPTO(SLJIT_LESS, STR_PTR, 0, TMP1, 0, common->ff_newline_shortcut);
+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
+ }
+ else
+ CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, common->ff_newline_shortcut);
+ }
}
else
- CMPTO(SLJIT_LESS, STR_PTR, 0, ((re->options & PCRE_FIRSTLINE) == 0) ? STR_END : TMP1, 0, mainloop_label);
+ CMPTO(SLJIT_LESS, STR_PTR, 0, (common->match_end_ptr == 0) ? STR_END : TMP1, 0, mainloop_label);
}
/* No more remaining characters. */
if (reqbyte_notfound != NULL)
JUMPHERE(reqbyte_notfound);
-if (mode == JIT_PARTIAL_SOFT_COMPILE)
+if (mode == PCRE2_JIT_PARTIAL_SOFT)
CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1, common->partialmatchlabel);
-OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_NOMATCH);
JUMPTO(SLJIT_JUMP, common->quit_label);
flush_stubs(common);
@@ -11195,10 +11235,11 @@ if (common->might_be_empty)
{
JUMPHERE(empty_match);
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
- OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
- CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack_label);
- OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
- CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found_label);
+ OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);
+ JUMPTO(SLJIT_NOT_ZERO, empty_match_backtrack_label);
+ OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);
+ JUMPTO(SLJIT_ZERO, empty_match_found_label);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label);
JUMPTO(SLJIT_JUMP, empty_match_backtrack_label);
@@ -11217,10 +11258,10 @@ while (common->currententry != NULL)
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
{
sljit_free_compiler(compiler);
- SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
- SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
- free_read_only_data(common->read_only_data_head, compiler->allocator_data);
- return;
+ SLJIT_FREE(common->optimized_cbracket, allocator_data);
+ SLJIT_FREE(common->private_data_ptrs, allocator_data);
+ PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ return PCRE2_ERROR_NOMEMORY;
}
flush_stubs(common);
common->currententry = common->currententry->next;
@@ -11251,12 +11292,12 @@ sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_SP), LOCALS0);
/* Allocation failed. */
JUMPHERE(jump);
/* We break the return address cache here, but this is a really rare case. */
-OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT);
+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_JIT_STACKLIMIT);
JUMPTO(SLJIT_JUMP, common->quit_label);
/* Call limit reached. */
set_jumps(common->calllimit, LABEL());
-OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT);
+OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_MATCHLIMIT);
JUMPTO(SLJIT_JUMP, common->quit_label);
if (common->revertframes != NULL)
@@ -11302,8 +11343,8 @@ if (common->reset_match != NULL)
OP1(SLJIT_MOV, STR_PTR, 0, TMP1, 0);
JUMPTO(SLJIT_JUMP, reset_match_label);
}
-#ifdef SUPPORT_UTF
-#ifdef COMPILE_PCRE8
+#ifdef SUPPORT_UNICODE
+#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utfreadchar != NULL)
{
set_jumps(common->utfreadchar, LABEL());
@@ -11319,18 +11360,16 @@ if (common->utfreadtype8 != NULL)
set_jumps(common->utfreadtype8, LABEL());
do_utfreadtype8(common);
}
-#endif /* COMPILE_PCRE8 */
-#endif /* SUPPORT_UTF */
-#ifdef SUPPORT_UCP
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
if (common->getucd != NULL)
{
set_jumps(common->getucd, LABEL());
do_getucd(common);
}
-#endif
+#endif /* SUPPORT_UNICODE */
-SLJIT_FREE(common->optimized_cbracket, compiler->allocator_data);
-SLJIT_FREE(common->private_data_ptrs, compiler->allocator_data);
+SLJIT_FREE(common->optimized_cbracket, allocator_data);
+SLJIT_FREE(common->private_data_ptrs, allocator_data);
executable_func = sljit_generate_code(compiler);
executable_size = sljit_get_generated_code_size(compiler);
@@ -11343,384 +11382,120 @@ while (label_addr != NULL)
sljit_free_compiler(compiler);
if (executable_func == NULL)
{
- free_read_only_data(common->read_only_data_head, compiler->allocator_data);
- return;
+ PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ return PCRE2_ERROR_NOMEMORY;
}
/* Reuse the function descriptor if possible. */
-if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL)
- functions = (executable_functions *)extra->executable_jit;
+if (re->executable_jit != NULL)
+ functions = (executable_functions *)re->executable_jit;
else
{
- /* Note: If your memory-checker has flagged the allocation below as a
- * memory leak, it is probably because you either forgot to call
- * pcre_free_study() (or pcre16_free_study()) on the pcre_extra (or
- * pcre16_extra) object, or you called said function after having
- * cleared the PCRE_EXTRA_EXECUTABLE_JIT bit from the "flags" field
- * of the object. (The function will only free the JIT data if the
- * bit remains set, as the bit indicates that the pointer to the data
- * is valid.)
- */
- functions = SLJIT_MALLOC(sizeof(executable_functions), compiler->allocator_data);
+ functions = SLJIT_MALLOC(sizeof(executable_functions), allocator_data);
if (functions == NULL)
{
/* This case is highly unlikely since we just recently
freed a lot of memory. Not impossible though. */
sljit_free_code(executable_func);
- free_read_only_data(common->read_only_data_head, compiler->allocator_data);
- return;
+ PRIV(jit_free_rodata)(common->read_only_data_head, compiler->allocator_data);
+ return PCRE2_ERROR_NOMEMORY;
}
memset(functions, 0, sizeof(executable_functions));
- functions->top_bracket = (re->top_bracket + 1) * 2;
- functions->limit_match = (re->flags & PCRE_MLSET) != 0 ? re->limit_match : 0;
- extra->executable_jit = functions;
- extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT;
+ functions->top_bracket = re->top_bracket + 1;
+ functions->limit_match = re->limit_match;
+ re->executable_jit = functions;
}
+/* Turn mode into an index. */
+if (mode == PCRE2_JIT_COMPLETE)
+ mode = 0;
+else
+ mode = (mode == PCRE2_JIT_PARTIAL_SOFT) ? 1 : 2;
+
+SLJIT_ASSERT(mode < JIT_NUMBER_OF_COMPILE_MODES);
functions->executable_funcs[mode] = executable_func;
functions->read_only_data_heads[mode] = common->read_only_data_head;
functions->executable_sizes[mode] = executable_size;
+return 0;
}
-static SLJIT_NOINLINE int jit_machine_stack_exec(jit_arguments *arguments, void *executable_func)
-{
-union {
- void *executable_func;
- jit_function call_executable_func;
-} convert_executable_func;
-sljit_u8 local_space[MACHINE_STACK_SIZE];
-struct sljit_stack local_stack;
-
-local_stack.top = (sljit_sw)&local_space;
-local_stack.base = local_stack.top;
-local_stack.limit = local_stack.base + MACHINE_STACK_SIZE;
-local_stack.max_limit = local_stack.limit;
-arguments->stack = &local_stack;
-convert_executable_func.executable_func = executable_func;
-return convert_executable_func.call_executable_func(arguments);
-}
+#endif
-int
-PRIV(jit_exec)(const PUBL(extra) *extra_data, const pcre_uchar *subject,
- int length, int start_offset, int options, int *offsets, int offset_count)
-{
-executable_functions *functions = (executable_functions *)extra_data->executable_jit;
-union {
- void *executable_func;
- jit_function call_executable_func;
-} convert_executable_func;
-jit_arguments arguments;
-int max_offset_count;
-int retval;
-int mode = JIT_COMPILE;
-
-if ((options & PCRE_PARTIAL_HARD) != 0)
- mode = JIT_PARTIAL_HARD_COMPILE;
-else if ((options & PCRE_PARTIAL_SOFT) != 0)
- mode = JIT_PARTIAL_SOFT_COMPILE;
-
-if (functions->executable_funcs[mode] == NULL)
- return PCRE_ERROR_JIT_BADOPTION;
-
-/* Sanity checks should be handled by pcre_exec. */
-arguments.str = subject + start_offset;
-arguments.begin = subject;
-arguments.end = subject + length;
-arguments.mark_ptr = NULL;
-/* JIT decreases this value less frequently than the interpreter. */
-arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (sljit_u32)(extra_data->match_limit);
-if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match)
- arguments.limit_match = functions->limit_match;
-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;
-arguments.callout_data = (extra_data->flags & PCRE_EXTRA_CALLOUT_DATA) != 0 ? extra_data->callout_data : NULL;
-arguments.real_offset_count = offset_count;
-
-/* pcre_exec() rounds offset_count 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 (offset_count != 2)
- offset_count = ((offset_count - (offset_count % 3)) * 2) / 3;
-max_offset_count = functions->top_bracket;
-if (offset_count > max_offset_count)
- offset_count = max_offset_count;
-arguments.offset_count = offset_count;
-
-if (functions->callback)
- arguments.stack = (struct sljit_stack *)functions->callback(functions->userdata);
-else
- arguments.stack = (struct sljit_stack *)functions->userdata;
+/*************************************************
+* JIT compile a Regular Expression *
+*************************************************/
-if (arguments.stack == NULL)
- retval = jit_machine_stack_exec(&arguments, functions->executable_funcs[mode]);
-else
- {
- convert_executable_func.executable_func = functions->executable_funcs[mode];
- retval = convert_executable_func.call_executable_func(&arguments);
- }
+/* This function used JIT to convert a previously-compiled pattern into machine
+code.
-if (retval * 2 > offset_count)
- retval = 0;
-if ((extra_data->flags & PCRE_EXTRA_MARK) != 0)
- *(extra_data->mark) = arguments.mark_ptr;
+Arguments:
+ code a compiled pattern
+ options JIT option bits
-return retval;
-}
+Returns: 0: success or (*NOJIT) was used
+ <0: an error code
+*/
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre_jit_exec(const pcre *argument_re, const pcre_extra *extra_data,
- PCRE_SPTR subject, int length, int start_offset, int options,
- int *offsets, int offset_count, pcre_jit_stack *stack)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre16_jit_exec(const pcre16 *argument_re, const pcre16_extra *extra_data,
- PCRE_SPTR16 subject, int length, int start_offset, int options,
- int *offsets, int offset_count, pcre16_jit_stack *stack)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_jit_exec(const pcre32 *argument_re, const pcre32_extra *extra_data,
- PCRE_SPTR32 subject, int length, int start_offset, int options,
- int *offsets, int offset_count, pcre32_jit_stack *stack)
-#endif
-{
-pcre_uchar *subject_ptr = (pcre_uchar *)subject;
-executable_functions *functions = (executable_functions *)extra_data->executable_jit;
-union {
- void *executable_func;
- jit_function call_executable_func;
-} convert_executable_func;
-jit_arguments arguments;
-int max_offset_count;
-int retval;
-int mode = JIT_COMPILE;
-
-SLJIT_UNUSED_ARG(argument_re);
-
-/* Plausibility checks */
-if ((options & ~PUBLIC_JIT_EXEC_OPTIONS) != 0) return PCRE_ERROR_JIT_BADOPTION;
-
-if ((options & PCRE_PARTIAL_HARD) != 0)
- mode = JIT_PARTIAL_HARD_COMPILE;
-else if ((options & PCRE_PARTIAL_SOFT) != 0)
- mode = JIT_PARTIAL_SOFT_COMPILE;
-
-if (functions->executable_funcs[mode] == NULL)
- return PCRE_ERROR_JIT_BADOPTION;
-
-/* Sanity checks should be handled by pcre_exec. */
-arguments.stack = (struct sljit_stack *)stack;
-arguments.str = subject_ptr + start_offset;
-arguments.begin = subject_ptr;
-arguments.end = subject_ptr + length;
-arguments.mark_ptr = NULL;
-/* JIT decreases this value less frequently than the interpreter. */
-arguments.limit_match = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : (sljit_u32)(extra_data->match_limit);
-if (functions->limit_match != 0 && functions->limit_match < arguments.limit_match)
- arguments.limit_match = functions->limit_match;
-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;
-arguments.callout_data = (extra_data->flags & PCRE_EXTRA_CALLOUT_DATA) != 0 ? extra_data->callout_data : NULL;
-arguments.real_offset_count = offset_count;
-
-/* pcre_exec() rounds offset_count 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 (offset_count != 2)
- offset_count = ((offset_count - (offset_count % 3)) * 2) / 3;
-max_offset_count = functions->top_bracket;
-if (offset_count > max_offset_count)
- offset_count = max_offset_count;
-arguments.offset_count = offset_count;
-
-convert_executable_func.executable_func = functions->executable_funcs[mode];
-retval = convert_executable_func.call_executable_func(&arguments);
-
-if (retval * 2 > offset_count)
- retval = 0;
-if ((extra_data->flags & PCRE_EXTRA_MARK) != 0)
- *(extra_data->mark) = arguments.mark_ptr;
-
-return retval;
-}
+#define PUBLIC_JIT_COMPILE_OPTIONS \
+ (PCRE2_JIT_COMPLETE|PCRE2_JIT_PARTIAL_SOFT|PCRE2_JIT_PARTIAL_HARD)
-void
-PRIV(jit_free)(void *executable_funcs)
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_jit_compile(pcre2_code *code, uint32_t options)
{
-int i;
-executable_functions *functions = (executable_functions *)executable_funcs;
-for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
- {
- if (functions->executable_funcs[i] != NULL)
- sljit_free_code(functions->executable_funcs[i]);
- free_read_only_data(functions->read_only_data_heads[i], NULL);
- }
-SLJIT_FREE(functions, compiler->allocator_data);
-}
+#ifndef SUPPORT_JIT
-int
-PRIV(jit_get_size)(void *executable_funcs)
-{
-int i;
-sljit_uw size = 0;
-sljit_uw *executable_sizes = ((executable_functions *)executable_funcs)->executable_sizes;
-for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
- size += executable_sizes[i];
-return (int)size;
-}
+(void)code;
+(void)options;
+return PCRE2_ERROR_JIT_BADOPTION;
-const char*
-PRIV(jit_get_target)(void)
-{
-return sljit_get_platform_name();
-}
+#else /* SUPPORT_JIT */
-#if defined COMPILE_PCRE8
-PCRE_EXP_DECL pcre_jit_stack *
-pcre_jit_stack_alloc(int startsize, int maxsize)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DECL pcre16_jit_stack *
-pcre16_jit_stack_alloc(int startsize, int maxsize)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DECL pcre32_jit_stack *
-pcre32_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, NULL);
-}
+pcre2_real_code *re = (pcre2_real_code *)code;
+executable_functions *functions;
+int result;
-#if defined COMPILE_PCRE8
-PCRE_EXP_DECL void
-pcre_jit_stack_free(pcre_jit_stack *stack)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DECL void
-pcre16_jit_stack_free(pcre16_jit_stack *stack)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DECL void
-pcre32_jit_stack_free(pcre32_jit_stack *stack)
-#endif
-{
-sljit_free_stack((struct sljit_stack *)stack, NULL);
-}
+if (code == NULL)
+ return PCRE2_ERROR_NULL;
-#if defined COMPILE_PCRE8
-PCRE_EXP_DECL void
-pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DECL void
-pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DECL void
-pcre32_assign_jit_stack(pcre32_extra *extra, pcre32_jit_callback callback, void *userdata)
-#endif
-{
-executable_functions *functions;
-if (extra != NULL &&
- (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 &&
- extra->executable_jit != NULL)
- {
- functions = (executable_functions *)extra->executable_jit;
- functions->callback = callback;
- functions->userdata = userdata;
- }
-}
+if ((options & ~PUBLIC_JIT_COMPILE_OPTIONS) != 0)
+ return PCRE2_ERROR_JIT_BADOPTION;
-#if defined COMPILE_PCRE8
-PCRE_EXP_DECL void
-pcre_jit_free_unused_memory(void)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DECL void
-pcre16_jit_free_unused_memory(void)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DECL void
-pcre32_jit_free_unused_memory(void)
-#endif
-{
-sljit_free_unused_memory_exec();
-}
+if ((re->flags & PCRE2_NOJIT) != 0) return 0;
-#else /* SUPPORT_JIT */
+functions = (executable_functions *)re->executable_jit;
-/* These are dummy functions to avoid linking errors when JIT support is not
-being compiled. */
+if ((options & PCRE2_JIT_COMPLETE) != 0 && (functions == NULL
+ || functions->executable_funcs[0] == NULL)) {
+ result = jit_compile(code, PCRE2_JIT_COMPLETE);
+ if (result != 0)
+ return result;
+ }
-#if defined COMPILE_PCRE8
-PCRE_EXP_DECL pcre_jit_stack *
-pcre_jit_stack_alloc(int startsize, int maxsize)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DECL pcre16_jit_stack *
-pcre16_jit_stack_alloc(int startsize, int maxsize)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DECL pcre32_jit_stack *
-pcre32_jit_stack_alloc(int startsize, int maxsize)
-#endif
-{
-(void)startsize;
-(void)maxsize;
-return NULL;
-}
+if ((options & PCRE2_JIT_PARTIAL_SOFT) != 0 && (functions == NULL
+ || functions->executable_funcs[1] == NULL)) {
+ result = jit_compile(code, PCRE2_JIT_PARTIAL_SOFT);
+ if (result != 0)
+ return result;
+ }
-#if defined COMPILE_PCRE8
-PCRE_EXP_DECL void
-pcre_jit_stack_free(pcre_jit_stack *stack)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DECL void
-pcre16_jit_stack_free(pcre16_jit_stack *stack)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DECL void
-pcre32_jit_stack_free(pcre32_jit_stack *stack)
-#endif
-{
-(void)stack;
-}
+if ((options & PCRE2_JIT_PARTIAL_HARD) != 0 && (functions == NULL
+ || functions->executable_funcs[2] == NULL)) {
+ result = jit_compile(code, PCRE2_JIT_PARTIAL_HARD);
+ if (result != 0)
+ return result;
+ }
-#if defined COMPILE_PCRE8
-PCRE_EXP_DECL void
-pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DECL void
-pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DECL void
-pcre32_assign_jit_stack(pcre32_extra *extra, pcre32_jit_callback callback, void *userdata)
-#endif
-{
-(void)extra;
-(void)callback;
-(void)userdata;
-}
+return 0;
-#if defined COMPILE_PCRE8
-PCRE_EXP_DECL void
-pcre_jit_free_unused_memory(void)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DECL void
-pcre16_jit_free_unused_memory(void)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DECL void
-pcre32_jit_free_unused_memory(void)
-#endif
-{
+#endif /* SUPPORT_JIT */
}
-#endif
+/* JIT compiler uses an all-in-one approach. This improves security,
+ since the code generator functions are not exported. */
+
+#define INCLUDED_FROM_PCRE2_JIT_COMPILE
+
+#include "pcre2_jit_match.c"
+#include "pcre2_jit_misc.c"
-/* End of pcre_jit_compile.c */
+/* End of pcre2_jit_compile.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_jit_match.c b/src/3rdparty/pcre2/src/pcre2_jit_match.c
new file mode 100644
index 0000000000..a323971ff3
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_jit_match.c
@@ -0,0 +1,189 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#ifndef INCLUDED_FROM_PCRE2_JIT_COMPILE
+#error This file must be included from pcre2_jit_compile.c.
+#endif
+
+#ifdef SUPPORT_JIT
+
+static SLJIT_NOINLINE int jit_machine_stack_exec(jit_arguments *arguments, jit_function executable_func)
+{
+sljit_u8 local_space[MACHINE_STACK_SIZE];
+struct sljit_stack local_stack;
+
+local_stack.top = (sljit_sw)&local_space;
+local_stack.base = local_stack.top;
+local_stack.limit = local_stack.base + MACHINE_STACK_SIZE;
+local_stack.max_limit = local_stack.limit;
+arguments->stack = &local_stack;
+return executable_func(arguments);
+}
+
+#endif
+
+
+/*************************************************
+* Do a JIT pattern match *
+*************************************************/
+
+/* This function runs a JIT pattern match.
+
+Arguments:
+ code points to the compiled expression
+ subject points to the subject string
+ length length of subject string (may contain binary zeros)
+ start_offset where to start in the subject string
+ options option bits
+ match_data points to a match_data block
+ mcontext points to a match context
+ jit_stack points to a JIT stack
+
+Returns: > 0 => success; value is the number of ovector pairs filled
+ = 0 => success, but ovector is not big enough
+ -1 => failed to match (PCRE_ERROR_NOMATCH)
+ < -1 => some kind of unexpected problem
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_jit_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
+ PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext)
+{
+#ifndef SUPPORT_JIT
+
+(void)code;
+(void)subject;
+(void)length;
+(void)start_offset;
+(void)options;
+(void)match_data;
+(void)mcontext;
+return PCRE2_ERROR_JIT_BADOPTION;
+
+#else /* SUPPORT_JIT */
+
+pcre2_real_code *re = (pcre2_real_code *)code;
+executable_functions *functions = (executable_functions *)re->executable_jit;
+pcre2_jit_stack *jit_stack;
+uint32_t oveccount = match_data->oveccount;
+uint32_t max_oveccount;
+union {
+ void *executable_func;
+ jit_function call_executable_func;
+} convert_executable_func;
+jit_arguments arguments;
+int rc;
+int index = 0;
+
+if ((options & PCRE2_PARTIAL_HARD) != 0)
+ index = 2;
+else if ((options & PCRE2_PARTIAL_SOFT) != 0)
+ index = 1;
+
+if (functions->executable_funcs[index] == NULL)
+ return PCRE2_ERROR_JIT_BADOPTION;
+
+/* Sanity checks should be handled by pcre_exec. */
+arguments.str = subject + start_offset;
+arguments.begin = subject;
+arguments.end = subject + length;
+arguments.match_data = match_data;
+arguments.startchar_ptr = subject;
+arguments.mark_ptr = NULL;
+arguments.options = options;
+
+if (mcontext != NULL)
+ {
+ arguments.callout = mcontext->callout;
+ arguments.callout_data = mcontext->callout_data;
+ arguments.offset_limit = mcontext->offset_limit;
+ arguments.limit_match = (mcontext->match_limit < re->limit_match)?
+ mcontext->match_limit : re->limit_match;
+ if (mcontext->jit_callback != NULL)
+ jit_stack = mcontext->jit_callback(mcontext->jit_callback_data);
+ else
+ jit_stack = (pcre2_jit_stack *)mcontext->jit_callback_data;
+ }
+else
+ {
+ arguments.callout = NULL;
+ arguments.callout_data = NULL;
+ arguments.offset_limit = PCRE2_UNSET;
+ arguments.limit_match = (MATCH_LIMIT < re->limit_match)?
+ MATCH_LIMIT : re->limit_match;
+ jit_stack = NULL;
+ }
+
+/* JIT only need two offsets for each ovector entry. Hence
+ the last 1/3 of the ovector will never be touched. */
+
+max_oveccount = functions->top_bracket;
+if (oveccount > max_oveccount)
+ oveccount = max_oveccount;
+arguments.oveccount = oveccount << 1;
+
+
+convert_executable_func.executable_func = functions->executable_funcs[index];
+if (jit_stack != NULL)
+ {
+ arguments.stack = (struct sljit_stack *)(jit_stack->stack);
+ rc = convert_executable_func.call_executable_func(&arguments);
+ }
+else
+ rc = jit_machine_stack_exec(&arguments, convert_executable_func.call_executable_func);
+
+if (rc > (int)oveccount)
+ rc = 0;
+match_data->code = re;
+match_data->subject = subject;
+match_data->rc = rc;
+match_data->startchar = arguments.startchar_ptr - subject;
+match_data->leftchar = 0;
+match_data->rightchar = 0;
+match_data->mark = arguments.mark_ptr;
+match_data->matchedby = PCRE2_MATCHEDBY_JIT;
+
+return match_data->rc;
+
+#endif /* SUPPORT_JIT */
+}
+
+/* End of pcre2_jit_match.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_jit_misc.c b/src/3rdparty/pcre2/src/pcre2_jit_misc.c
new file mode 100644
index 0000000000..efdb05580f
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_jit_misc.c
@@ -0,0 +1,227 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+#ifndef INCLUDED_FROM_PCRE2_JIT_COMPILE
+#error This file must be included from pcre2_jit_compile.c.
+#endif
+
+
+
+/*************************************************
+* Free JIT read-only data *
+*************************************************/
+
+void
+PRIV(jit_free_rodata)(void *current, void *allocator_data)
+{
+#ifndef SUPPORT_JIT
+(void)current;
+(void)allocator_data;
+#else /* SUPPORT_JIT */
+void *next;
+
+SLJIT_UNUSED_ARG(allocator_data);
+
+while (current != NULL)
+ {
+ next = *(void**)current;
+ SLJIT_FREE(current, allocator_data);
+ current = next;
+ }
+
+#endif /* SUPPORT_JIT */
+}
+
+/*************************************************
+* Free JIT compiled code *
+*************************************************/
+
+void
+PRIV(jit_free)(void *executable_jit, pcre2_memctl *memctl)
+{
+#ifndef SUPPORT_JIT
+(void)executable_jit;
+(void)memctl;
+#else /* SUPPORT_JIT */
+
+executable_functions *functions = (executable_functions *)executable_jit;
+void *allocator_data = memctl;
+int i;
+
+for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++)
+ {
+ if (functions->executable_funcs[i] != NULL)
+ sljit_free_code(functions->executable_funcs[i]);
+ PRIV(jit_free_rodata)(functions->read_only_data_heads[i], allocator_data);
+ }
+
+SLJIT_FREE(functions, allocator_data);
+
+#endif /* SUPPORT_JIT */
+}
+
+
+/*************************************************
+* Free unused JIT memory *
+*************************************************/
+
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_jit_free_unused_memory(pcre2_general_context *gcontext)
+{
+#ifndef SUPPORT_JIT
+(void)gcontext; /* Suppress warning */
+#else /* SUPPORT_JIT */
+SLJIT_UNUSED_ARG(gcontext);
+sljit_free_unused_memory_exec();
+#endif /* SUPPORT_JIT */
+}
+
+
+
+/*************************************************
+* Allocate a JIT stack *
+*************************************************/
+
+PCRE2_EXP_DEFN pcre2_jit_stack * PCRE2_CALL_CONVENTION
+pcre2_jit_stack_create(size_t startsize, size_t maxsize,
+ pcre2_general_context *gcontext)
+{
+#ifndef SUPPORT_JIT
+
+(void)gcontext;
+(void)startsize;
+(void)maxsize;
+return NULL;
+
+#else /* SUPPORT_JIT */
+
+pcre2_jit_stack *jit_stack;
+
+if (startsize < 1 || maxsize < 1)
+ return NULL;
+if (startsize > maxsize)
+ startsize = maxsize;
+startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
+maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
+
+jit_stack = PRIV(memctl_malloc)(sizeof(pcre2_real_jit_stack), (pcre2_memctl *)gcontext);
+if (jit_stack == NULL) return NULL;
+jit_stack->stack = sljit_allocate_stack(startsize, maxsize, &jit_stack->memctl);
+return jit_stack;
+
+#endif
+}
+
+
+/*************************************************
+* Assign a JIT stack to a pattern *
+*************************************************/
+
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_jit_stack_assign(pcre2_match_context *mcontext, pcre2_jit_callback callback,
+ void *callback_data)
+{
+#ifndef SUPPORT_JIT
+(void)mcontext;
+(void)callback;
+(void)callback_data;
+#else /* SUPPORT_JIT */
+
+if (mcontext == NULL) return;
+mcontext->jit_callback = callback;
+mcontext->jit_callback_data = callback_data;
+
+#endif /* SUPPORT_JIT */
+}
+
+
+/*************************************************
+* Free a JIT stack *
+*************************************************/
+
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_jit_stack_free(pcre2_jit_stack *jit_stack)
+{
+#ifndef SUPPORT_JIT
+(void)jit_stack;
+#else /* SUPPORT_JIT */
+if (jit_stack != NULL)
+ {
+ sljit_free_stack((struct sljit_stack *)(jit_stack->stack), &jit_stack->memctl);
+ jit_stack->memctl.free(jit_stack, jit_stack->memctl.memory_data);
+ }
+#endif /* SUPPORT_JIT */
+}
+
+
+/*************************************************
+* Get target CPU type *
+*************************************************/
+
+const char*
+PRIV(jit_get_target)(void)
+{
+#ifndef SUPPORT_JIT
+return "JIT is not supported";
+#else /* SUPPORT_JIT */
+return sljit_get_platform_name();
+#endif /* SUPPORT_JIT */
+}
+
+
+/*************************************************
+* Get size of JIT code *
+*************************************************/
+
+size_t
+PRIV(jit_get_size)(void *executable_jit)
+{
+#ifndef SUPPORT_JIT
+(void)executable_jit;
+return 0;
+#else /* SUPPORT_JIT */
+sljit_uw *executable_sizes = ((executable_functions *)executable_jit)->executable_sizes;
+SLJIT_COMPILE_ASSERT(JIT_NUMBER_OF_COMPILE_MODES == 3, number_of_compile_modes_changed);
+return executable_sizes[0] + executable_sizes[1] + executable_sizes[2];
+#endif
+}
+
+/* End of pcre2_jit_misc.c */
diff --git a/src/3rdparty/pcre/pcre_maketables.c b/src/3rdparty/pcre2/src/pcre2_maketables.c
index a44a6eaa90..2c7ae84d86 100644
--- a/src/3rdparty/pcre/pcre_maketables.c
+++ b/src/3rdparty/pcre2/src/pcre2_maketables.c
@@ -6,7 +6,8 @@
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
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -38,53 +39,53 @@ 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
+/* This module contains the external function pcre2_maketables(), which builds
+character tables for PCRE2 in the current locale. The file is compiled on its
+own as part of the PCRE2 library. However, it is also included in the
compilation of dftables.c, in which case the macro DFTABLES is defined. */
-
#ifndef DFTABLES
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
-# include "pcre_internal.h"
+# include "pcre2_internal.h"
#endif
+
/*************************************************
-* Create PCRE character tables *
+* Create PCRE2 character tables *
*************************************************/
-/* This function builds a set of character tables for use by PCRE and returns
+/* This function builds a set of character tables for use by PCRE2 and returns
a pointer to them. They are build using the ctype functions, and consequently
their contents will depend upon the current locale setting. When compiled as
-part of the library, the store is obtained via PUBL(malloc)(), but when
-compiled inside dftables, use malloc().
+part of the library, the store is obtained via a general context malloc, if
+supplied, but when DFTABLES is defined (when compiling the dftables auxiliary
+program) malloc() is used, and the function has a different name so as not to
+clash with the prototype in pcre2.h.
-Arguments: none
+Arguments: none when DFTABLES is defined
+ else a PCRE2 general context or NULL
Returns: pointer to the contiguous block of data
*/
-#if defined COMPILE_PCRE8
-const unsigned char *
-pcre_maketables(void)
-#elif defined COMPILE_PCRE16
-const unsigned char *
-pcre16_maketables(void)
-#elif defined COMPILE_PCRE32
-const unsigned char *
-pcre32_maketables(void)
-#endif
+#ifdef DFTABLES /* Included in freestanding dftables.c program */
+static const uint8_t *maketables(void)
{
-unsigned char *yield, *p;
-int i;
+uint8_t *yield = (uint8_t *)malloc(tables_length);
-#ifndef DFTABLES
-yield = (unsigned char*)(PUBL(malloc))(tables_length);
-#else
-yield = (unsigned char*)malloc(tables_length);
-#endif
+#else /* Not DFTABLES, compiling the library */
+PCRE2_EXP_DEFN const uint8_t * PCRE2_CALL_CONVENTION
+pcre2_maketables(pcre2_general_context *gcontext)
+{
+uint8_t *yield = (uint8_t *)((gcontext != NULL)?
+ gcontext->memctl.malloc(tables_length, gcontext->memctl.memory_data) :
+ malloc(tables_length));
+#endif /* DFTABLES */
+
+int i;
+uint8_t *p;
if (yield == NULL) return NULL;
p = yield;
@@ -153,4 +154,4 @@ for (i = 0; i < 256; i++)
return yield;
}
-/* End of pcre_maketables.c */
+/* End of pcre2_maketables.c */
diff --git a/src/3rdparty/pcre/pcre_exec.c b/src/3rdparty/pcre2/src/pcre2_match.c
index 24b23ca286..0763a239e1 100644
--- a/src/3rdparty/pcre/pcre_exec.c
+++ b/src/3rdparty/pcre2/src/pcre2_match.c
@@ -6,7 +6,8 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2014 University of Cambridge
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -37,26 +38,30 @@ 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 HAVE_CONFIG_H
#include "config.h"
#endif
-#define NLBLOCK md /* Block containing newline information */
+#define NLBLOCK mb /* Block containing newline information */
#define PSSTART start_subject /* Field containing processed string start */
#define PSEND end_subject /* Field containing processed string end */
-#include "pcre_internal.h"
+#include "pcre2_internal.h"
-/* Undefine some potentially clashing cpp symbols */
+/* Masks for identifying the public options that are permitted at match time.
+*/
-#undef min
-#undef max
+#define PUBLIC_MATCH_OPTIONS \
+ (PCRE2_ANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \
+ PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK|PCRE2_PARTIAL_HARD| \
+ PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT)
+
+#define PUBLIC_JIT_MATCH_OPTIONS \
+ (PCRE2_NO_UTF_CHECK|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY|\
+ PCRE2_NOTEMPTY_ATSTART|PCRE2_PARTIAL_SOFT|PCRE2_PARTIAL_HARD)
-/* The md->capture_last field uses the lower 16 bits for the last captured
+/* The mb->capture_last field uses the lower 16 bits for the last captured
substring (which can never be greater than 65535) and a bit in the top half
to mean "capture vector overflowed". This odd way of doing things was
implemented when it was realized that preserving and restoring the overflow bit
@@ -70,7 +75,7 @@ implementing this. */
#define OVFLMASK 0xffff0000 /* The bits used for the overflow flag */
#define OVFLBIT 0x00010000 /* The bit that is set for overflow */
-/* Values for setting in md->match_function_type to indicate two special types
+/* Bits for setting in mb->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. */
@@ -78,7 +83,7 @@ as stack usage is to be discouraged. */
#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. */
+defined PCRE2_ERROR_xxx codes, which are all negative. */
#define MATCH_MATCH 1
#define MATCH_NOMATCH 0
@@ -99,44 +104,17 @@ for any one of them can use a range. */
#define MATCH_BACKTRACK_MAX MATCH_THEN
#define MATCH_BACKTRACK_MIN MATCH_COMMIT
-/* 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, 0, 0, 0, 1, 0, };
static const char rep_max[] = { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 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
-*/
+/* Maximum number of ovector elements that can be saved on the system stack
+when processing OP_RECURSE in non-HEAP_MATCH_RECURSE mode. If the ovector is
+bigger, malloc() is used. This value should be a multiple of 3, because the
+ovector length is always a multiple of 3. */
-static void
-pchars(const pcre_uchar *p, int length, BOOL is_subject, match_data *md)
-{
-pcre_uint32 c;
-BOOL utf = md->utf;
-if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
-while (length-- > 0)
- if (isprint(c = UCHAR21INCTEST(p))) printf("%c", (char)c); else printf("\\x{%02x}", c);
-}
-#endif
+#define OP_RECURSE_STACK_SAVE_MAX 45
@@ -144,62 +122,62 @@ while (length-- > 0)
* 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.
+/* This function is called only when it is known that the offset lies within
+the offsets that have so far been used in the match. Note that in caseless
+UTF-8 mode, the number of subject bytes matched may be different to the number
+of reference bytes. (In theory this could also happen in UTF-16 mode, but it
+seems unlikely.)
Arguments:
offset index into the offset vector
+ offset_top top of the used offset vector
eptr pointer into the subject
- length length of reference to be matched (number of bytes)
- md points to match data block
+ mb points to match block
caseless TRUE if caseless
+ lengthptr pointer for returning the length matched
-Returns: >= 0 the number of subject bytes matched
- -1 no match
- -2 partial match; always given if at end subject
+Returns: = 0 sucessful match; number of code units matched is set
+ < 0 no match
+ > 0 partial match
*/
static int
-match_ref(int offset, register PCRE_PUCHAR eptr, int length, match_data *md,
- BOOL caseless)
+match_ref(PCRE2_SIZE offset, PCRE2_SIZE offset_top, register PCRE2_SPTR eptr,
+ match_block *mb, BOOL caseless, PCRE2_SIZE *lengthptr)
{
-PCRE_PUCHAR eptr_start = eptr;
-register PCRE_PUCHAR p = md->start_subject + md->offset_vector[offset];
-#if defined SUPPORT_UTF && defined SUPPORT_UCP
-BOOL utf = md->utf;
+#if defined SUPPORT_UNICODE
+BOOL utf = (mb->poptions & PCRE2_UTF) != 0;
#endif
-#ifdef PCRE_DEBUG
-if (eptr >= md->end_subject)
- printf("matching subject <null>");
-else
+register PCRE2_SPTR p;
+PCRE2_SIZE length;
+PCRE2_SPTR eptr_start = eptr;
+
+/* Deal with an unset group. The default is no match, but there is an option to
+match an empty string. */
+
+if (offset >= offset_top || mb->ovector[offset] == PCRE2_UNSET)
{
- printf("matching subject ");
- pchars(eptr, length, TRUE, md);
+ if ((mb->poptions & PCRE2_MATCH_UNSET_BACKREF) != 0)
+ {
+ *lengthptr = 0;
+ return 0; /* Match */
+ }
+ else return -1; /* No match */
}
-printf(" against backref ");
-pchars(p, length, FALSE, md);
-printf("\n");
-#endif
-/* Always fail if reference not set (and not JavaScript compatible - in that
-case the length is passed as zero). */
+/* Separate the caseless and UTF cases for speed. */
-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. */
+p = mb->start_subject + mb->ovector[offset];
+length = mb->ovector[offset+1] - mb->ovector[offset];
if (caseless)
{
-#if defined SUPPORT_UTF && defined SUPPORT_UCP
+#if defined SUPPORT_UNICODE
if (utf)
{
/* Match characters up to the end of the reference. NOTE: the number of
- data units matched may differ, because in UTF-8 there are some characters
+ code units matched may differ, because in UTF-8 there are some characters
whose upper and lower case versions code have different numbers of bytes.
For example, U+023A (2 bytes in UTF-8) is the upper case version of U+2C65
(3 bytes in UTF-8); a sequence of 3 of the former uses 6 bytes, as does a
@@ -207,21 +185,21 @@ if (caseless)
length along the reference, not along the subject (earlier code did this
wrong). */
- PCRE_PUCHAR endptr = p + length;
+ PCRE2_SPTR endptr = p + length;
while (p < endptr)
{
- pcre_uint32 c, d;
+ uint32_t c, d;
const ucd_record *ur;
- if (eptr >= md->end_subject) return -2; /* Partial match */
+ if (eptr >= mb->end_subject) return 1; /* Partial match */
GETCHARINC(c, eptr);
GETCHARINC(d, p);
ur = GET_UCD(d);
- if (c != d && c != d + ur->other_case)
+ if (c != d && c != (uint32_t)((int)d + ur->other_case))
{
- const pcre_uint32 *pp = PRIV(ucd_caseless_sets) + ur->caseset;
+ const uint32_t *pp = PRIV(ucd_caseless_sets) + ur->caseset;
for (;;)
{
- if (c < *pp) return -1;
+ if (c < *pp) return -1; /* No match */
if (c == *pp++) break;
}
}
@@ -230,35 +208,37 @@ if (caseless)
else
#endif
- /* The same code works when not in UTF-8 mode and in UTF-8 mode when there
- is no UCP support. */
+ /* Not in UTF mode */
+
{
- while (length-- > 0)
+ for (; length > 0; length--)
{
- pcre_uint32 cc, cp;
- if (eptr >= md->end_subject) return -2; /* Partial match */
+ uint32_t cc, cp;
+ if (eptr >= mb->end_subject) return 1; /* Partial match */
cc = UCHAR21TEST(eptr);
cp = UCHAR21TEST(p);
- if (TABLE_GET(cp, md->lcc, cp) != TABLE_GET(cc, md->lcc, cc)) return -1;
+ if (TABLE_GET(cp, mb->lcc, cp) != TABLE_GET(cc, mb->lcc, cc))
+ return -1; /* No match */
p++;
eptr++;
}
}
}
-/* In the caseful case, we can just compare the bytes, whether or not we
-are in UTF-8 mode. */
+/* In the caseful case, we can just compare the code units, whether or not we
+are in UTF mode. */
else
{
- while (length-- > 0)
+ for (; length > 0; length--)
{
- if (eptr >= md->end_subject) return -2; /* Partial match */
- if (UCHAR21INCTEST(p) != UCHAR21INCTEST(eptr)) return -1;
+ if (eptr >= mb->end_subject) return 1; /* Partial match */
+ if (UCHAR21INCTEST(p) != UCHAR21INCTEST(eptr)) return -1; /*No match */
}
}
-return (int)(eptr - eptr_start);
+*lengthptr = eptr - eptr_start;
+return 0; /* Match */
}
@@ -268,7 +248,7 @@ 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
+increases the recursion 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
@@ -279,9 +259,9 @@ 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
+There is a fudge, triggered by defining HEAP_MATCH_RECURSE, which avoids
+recursive calls by keeping local variables that need to be preserved in blocks
+of memory on the heap 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.
@@ -310,38 +290,20 @@ enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10,
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, RM67 };
+ RM61, RM62, RM63, RM64, RM65, RM66, RM67, RM68 };
-/* 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. */
+/* These versions of the macros use the stack, as normal. Note that the "rw"
+argument of RMATCH isn't actually used in this definition. */
-#ifndef NO_RECURSE
+#ifndef HEAP_MATCH_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\n", 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
+the "rd" argument of RMATCH isn't actually used in this definition. It's the mb
argument of match(), which never changes. */
#define REGISTER
@@ -351,8 +313,9 @@ argument of match(), which never changes. */
heapframe *newframe = frame->Xnextframe;\
if (newframe == NULL)\
{\
- newframe = (heapframe *)(PUBL(stack_malloc))(sizeof(heapframe));\
- if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\
+ newframe = (heapframe *)(mb->stack_memctl.malloc)\
+ (sizeof(heapframe), mb->stack_memctl.memory_data);\
+ if (newframe == NULL) RRETURN(PCRE2_ERROR_NOMEMORY);\
newframe->Xnextframe = NULL;\
frame->Xnextframe = newframe;\
}\
@@ -365,10 +328,8 @@ argument of match(), which never changes. */
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__));\
+ L_##rw:;\
}
#define RRETURN(ra)\
@@ -384,67 +345,63 @@ argument of match(), which never changes. */
}
-/* Structure for remembering the local variables in a private frame */
+/* Structure for remembering the local variables in a private frame. Arrange it
+so as to minimize the number of holes. */
typedef struct heapframe {
struct heapframe *Xprevframe;
struct heapframe *Xnextframe;
- /* Function arguments that may change */
+#ifdef SUPPORT_UNICODE
+ PCRE2_SPTR Xcharptr;
+#endif
+ PCRE2_SPTR Xeptr;
+ PCRE2_SPTR Xecode;
+ PCRE2_SPTR Xmstart;
+ PCRE2_SPTR Xcallpat;
+ PCRE2_SPTR Xdata;
+ PCRE2_SPTR Xnext_ecode;
+ PCRE2_SPTR Xpp;
+ PCRE2_SPTR Xprev;
+ PCRE2_SPTR Xsaved_eptr;
- 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;
+ PCRE2_SIZE Xlength;
+ PCRE2_SIZE Xoffset;
+ PCRE2_SIZE Xoffset_top;
+ PCRE2_SIZE Xsave_offset1, Xsave_offset2, Xsave_offset3;
- BOOL Xcur_is_word;
- BOOL Xcondition;
- BOOL Xprev_is_word;
+ uint32_t Xfc;
+ uint32_t Xnumber;
+ uint32_t Xrdepth;
+ uint32_t Xop;
+ uint32_t Xsave_capture_last;
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
+ uint32_t Xprop_value;
int Xprop_type;
- unsigned 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;
- unsigned int Xnumber;
- int Xoffset;
- unsigned int Xop;
- pcre_int32 Xsave_capture_last;
- int Xsave_offset1, Xsave_offset2, Xsave_offset3;
- int Xstacksave[REC_STACK_SAVE_MAX];
-
- eptrblock Xnewptrb;
+ int Xwhere; /* Where to jump back to */
- /* Where to jump back to */
+ BOOL Xcondition;
+ BOOL Xcur_is_word;
+ BOOL Xprev_is_word;
- int Xwhere;
+ eptrblock Xnewptrb;
+ recursion_info Xnew_recursive;
+#ifdef SUPPORT_UNICODE
+ PCRE2_UCHAR Xocchars[6];
+#endif
} heapframe;
#endif
@@ -454,6 +411,115 @@ typedef struct heapframe {
***************************************************************************/
+/* When HEAP_MATCH_RECURSE is not defined, the match() function implements
+backtrack points by calling itself recursively in all but one case. The one
+special case is when processing OP_RECURSE, which specifies recursion in the
+pattern. The entire ovector must be saved and restored while processing
+OP_RECURSE. If the ovector is small enough, instead of calling match()
+directly, op_recurse_ovecsave() is called. This function uses the system stack
+to save the ovector while calling match() to process the pattern recursion. */
+
+#ifndef HEAP_MATCH_RECURSE
+
+/* We need a prototype for match() because it is mutually recursive with
+op_recurse_ovecsave(). */
+
+static int
+match(REGISTER PCRE2_SPTR eptr, REGISTER PCRE2_SPTR ecode, PCRE2_SPTR mstart,
+ PCRE2_SIZE offset_top, match_block *mb, eptrblock *eptrb, uint32_t rdepth);
+
+
+/*************************************************
+* Process OP_RECURSE, stacking ovector *
+*************************************************/
+
+/* When this function is called, mb->recursive has already been updated to
+point to a new recursion data block, and all its fields other than ovec_save
+have been set.
+
+This function exists so that the local vector variable ovecsave is no longer
+defined in the match() function, as it was in PCRE1. It is used only when there
+is recursion in the pattern, so it wastes a lot of stack to have it defined for
+every call of match(). We now use this function as an indirect way of calling
+match() only in the case when ovecsave is needed. (David Wheeler used to say
+"All problems in computer science can be solved by another level of
+indirection.")
+
+HOWEVER: when this file is compiled by gcc in an optimizing mode, because this
+function is called only once, and only from within match(), gcc will "inline"
+it - that is, move it inside match() - and this completely negates its reason
+for existence. Therefore, we mark it as non-inline when gcc is in use.
+
+Arguments:
+ eptr pointer to current character in subject
+ callpat the recursion point in the pattern
+ mstart pointer to the current match start position (can be modified
+ by encountering \K)
+ offset_top current top pointer (highest ovector offset used + 1)
+ mb pointer to "static" info block 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: a match() return code
+*/
+
+static int
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+__attribute__ ((noinline))
+#endif
+op_recurse_ovecsave(REGISTER PCRE2_SPTR eptr, PCRE2_SPTR callpat,
+ PCRE2_SPTR mstart, PCRE2_SIZE offset_top, match_block *mb, eptrblock *eptrb,
+ uint32_t rdepth)
+{
+register int rrc;
+BOOL cbegroup = *callpat >= OP_SBRA;
+recursion_info *new_recursive = mb->recursive;
+PCRE2_SIZE ovecsave[OP_RECURSE_STACK_SAVE_MAX];
+
+/* Save the ovector */
+
+new_recursive->ovec_save = ovecsave;
+memcpy(ovecsave, mb->ovector, mb->offset_end * sizeof(PCRE2_SIZE));
+
+/* Do the recursion. After processing each alternative, restore the ovector
+data and the last captured value. */
+
+do
+ {
+ if (cbegroup) mb->match_function_type |= MATCH_CBEGROUP;
+ rrc = match(eptr, callpat + PRIV(OP_lengths)[*callpat], mstart, offset_top,
+ mb, eptrb, rdepth + 1);
+ memcpy(mb->ovector, new_recursive->ovec_save,
+ mb->offset_end * sizeof(PCRE2_SIZE));
+ mb->capture_last = new_recursive->saved_capture_last;
+ if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) return rrc;
+
+ /* PCRE does not allow THEN, SKIP, PRUNE or COMMIT to escape beyond a
+ recursion; they cause a NOMATCH for the entire recursion. These codes
+ are defined in a range that can be tested for. */
+
+ if (rrc >= MATCH_BACKTRACK_MIN && rrc <= MATCH_BACKTRACK_MAX)
+ return MATCH_NOMATCH;
+
+ /* Any return code other than NOMATCH is an error. Otherwise, advance to the
+ next alternative or to the end of the recursing subpattern. If there were
+ nested recursions, mb->recursive might be changed, so reset it before
+ looping. */
+
+ if (rrc != MATCH_NOMATCH) return rrc;
+ mb->recursive = new_recursive;
+ callpat += GET(callpat, 1);
+ }
+while (*callpat == OP_ALT); /* Loop for the alternatives */
+
+/* None of the alternatives matched. */
+
+return MATCH_NOMATCH;
+}
+#endif /* HEAP_MATCH_RECURSE */
+
+
/*************************************************
* Match from current position *
@@ -465,29 +531,29 @@ 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. */
+at the end of the subject and also past the earliest inspected character (i.e.
+something has been matched, even if not part of the actual matched string). For
+hard partial matching, we then return immediately. The second one is used when
+we already know we are past the end of the subject. */
#define CHECK_PARTIAL()\
- if (md->partial != 0 && eptr >= md->end_subject && \
- eptr > md->start_used_ptr) \
+ if (mb->partial != 0 && eptr >= mb->end_subject && \
+ eptr > mb->start_used_ptr) \
{ \
- md->hitend = TRUE; \
- if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \
+ mb->hitend = TRUE; \
+ if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL); \
}
#define SCHECK_PARTIAL()\
- if (md->partial != 0 && eptr > md->start_used_ptr) \
+ if (mb->partial != 0 && eptr > mb->start_used_ptr) \
{ \
- md->hitend = TRUE; \
- if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \
+ mb->hitend = TRUE; \
+ if (mb->partial > 1) RRETURN(PCRE2_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
+the mb 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.
@@ -496,8 +562,8 @@ Arguments:
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
+ offset_top current top pointer (highest ovector offset used + 1)
+ mb pointer to "static" info block for the match
eptrb pointer to chain of blocks containing eptr at start of
brackets - for testing for empty matches
rdepth the recursion depth
@@ -505,14 +571,13 @@ Arguments:
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
+ a negative PCRE2_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)
+match(REGISTER PCRE2_SPTR eptr, REGISTER PCRE2_SPTR ecode, PCRE2_SPTR mstart,
+ PCRE2_SIZE offset_top, match_block *mb, eptrblock *eptrb, uint32_t 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
@@ -520,7 +585,7 @@ so they can be ordinary variables in all cases. Mark some of them with
register int rrc; /* Returns from recursive calls */
register int i; /* Used for loops not involving calls to RMATCH() */
-register pcre_uint32 c; /* Character values not kept over RMATCH() calls */
+register uint32_t c; /* Character values not kept over RMATCH() calls */
register BOOL utf; /* Local copy of UTF flag for speed */
BOOL minimize, possessive; /* Quantifier options */
@@ -534,8 +599,8 @@ 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 = (heapframe *)md->match_frames_base;
+#ifdef HEAP_MATCH_RECURSE
+heapframe *frame = (heapframe *)mb->match_frames_base;
/* Copy in the original argument variables */
@@ -561,31 +626,26 @@ HEAP_RECURSE:
/* Ditto for the local variables */
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
#define charptr frame->Xcharptr
+#define prop_value frame->Xprop_value
+#define prop_type frame->Xprop_type
+#define prop_fail_result frame->Xprop_fail_result
+#define oclength frame->Xoclength
+#define occhars frame->Xocchars
#endif
+
+
#define callpat frame->Xcallpat
#define codelink frame->Xcodelink
#define data frame->Xdata
-#define next frame->Xnext
+#define next_ecode frame->Xnext_ecode
#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
@@ -599,15 +659,18 @@ HEAP_RECURSE:
#define save_offset1 frame->Xsave_offset1
#define save_offset2 frame->Xsave_offset2
#define save_offset3 frame->Xsave_offset3
-#define stacksave frame->Xstacksave
+
+#define condition frame->Xcondition
+#define cur_is_word frame->Xcur_is_word
+#define prev_is_word frame->Xprev_is_word
#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. */
+/* When normal stack-based recursion is being used for match(), local variables
+are allocated on the stack and get preserved during recursion in the usual way.
+In this environment, fi and i, and fc and c, can be the same variables. */
-#else /* NO_RECURSE not defined */
+#else /* HEAP_MATCH_RECURSE not defined */
#define fi i
#define fc c
@@ -619,101 +682,84 @@ 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;
+#ifdef SUPPORT_UNICODE
+PCRE2_SPTR 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
+PCRE2_SPTR callpat;
+PCRE2_SPTR data;
+PCRE2_SPTR next_ecode;
+PCRE2_SPTR pp;
+PCRE2_SPTR prev;
+PCRE2_SPTR saved_eptr;
+
+PCRE2_SIZE length;
+PCRE2_SIZE offset;
+PCRE2_SIZE save_offset1, save_offset2, save_offset3;
+
+uint32_t number;
+uint32_t op;
+uint32_t save_capture_last;
+
+#ifdef SUPPORT_UNICODE
+uint32_t prop_value;
int prop_type;
-unsigned int prop_value;
int prop_fail_result;
int oclength;
-pcre_uchar occhars[6];
+PCRE2_UCHAR occhars[6];
#endif
int codelink;
int ctype;
-int length;
int max;
int min;
-unsigned int number;
-int offset;
-unsigned int op;
-pcre_int32 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. */
+BOOL condition;
+BOOL cur_is_word;
+BOOL prev_is_word;
-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 */
+eptrblock newptrb;
+recursion_info new_recursive;
+#endif /* HEAP_MATCH_RECURSE not defined */
/* 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
+#define allow_zero cur_is_word
+#define cbegroup condition
+#define code_offset codelink
+#define condassert condition
+#define foc number
+#define matched_once prev_is_word
+#define save_mark data
/* These statements are here to stop the compiler complaining about unitialized
variables. */
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
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. */
+when HEAP_MATCH_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 */
+HEAP_MATCH_RECURSE is *not* defined, these just turn into a recursive call to
+match() and a "return", respectively. 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_UNICODE
+utf = (mb->poptions & PCRE2_UTF) != 0;
#else
utf = FALSE;
#endif
@@ -721,13 +767,13 @@ utf = FALSE;
/* 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);
+if (mb->match_call_count++ >= mb->match_limit) RRETURN(PCRE2_ERROR_MATCHLIMIT);
+if (rdepth >= mb->match_limit_recursion) RRETURN(PCRE2_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.
+string, the variable mb->match_function_type contains the MATCH_CBEGROUP bit.
+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
@@ -736,15 +782,15 @@ 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)
+if ((mb->match_function_type & MATCH_CBEGROUP) != 0)
{
newptrb.epb_saved_eptr = eptr;
newptrb.epb_prev = eptrb;
eptrb = &newptrb;
- md->match_function_type = 0;
+ mb->match_function_type &= ~MATCH_CBEGROUP;
}
-/* Now start processing the opcodes. */
+/* Now, at last, we can start processing the opcodes. */
for (;;)
{
@@ -754,24 +800,24 @@ for (;;)
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,
+ mb->nomatch_mark = ecode + 2;
+ mb->mark = NULL; /* In case previously set by assertion */
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, mb,
eptrb, RM55);
if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
- md->mark == NULL) md->mark = ecode + 2;
+ mb->mark == NULL) mb->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
+ argument. It is passed back in mb->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_TEST(ecode + 2, md->start_match_ptr) == 0)
+ PRIV(strcmp)(ecode + 2, mb->start_match_ptr) == 0)
{
- md->start_match_ptr = eptr;
+ mb->start_match_ptr = eptr;
RRETURN(MATCH_SKIP);
}
RRETURN(rrc);
@@ -780,32 +826,32 @@ for (;;)
RRETURN(MATCH_NOMATCH);
case OP_COMMIT:
- RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb,
eptrb, RM52);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
RRETURN(MATCH_COMMIT);
case OP_PRUNE:
- RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb,
eptrb, RM51);
if (rrc != MATCH_NOMATCH) 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,
+ mb->nomatch_mark = ecode + 2;
+ mb->mark = NULL; /* In case previously set by assertion */
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, mb,
eptrb, RM56);
if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
- md->mark == NULL) md->mark = ecode + 2;
+ mb->mark == NULL) mb->mark = ecode + 2;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
RRETURN(MATCH_PRUNE);
case OP_SKIP:
- RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb,
eptrb, RM53);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- md->start_match_ptr = eptr; /* Pass back current position */
+ mb->start_match_ptr = eptr; /* Pass back current position */
RRETURN(MATCH_SKIP);
/* Note that, for Perl compatibility, SKIP with an argument does NOT set
@@ -813,26 +859,26 @@ for (;;)
not a matching mark, we have to re-run the match, ignoring the SKIP_ARG
that failed and any that precede it (either they also failed, or were not
triggered). To do this, we maintain a count of executed SKIP_ARGs. If a
- SKIP_ARG gets to top level, the match is re-run with md->ignore_skip_arg
+ SKIP_ARG gets to top level, the match is re-run with mb->ignore_skip_arg
set to the count of the one that failed. */
case OP_SKIP_ARG:
- md->skip_arg_count++;
- if (md->skip_arg_count <= md->ignore_skip_arg)
+ mb->skip_arg_count++;
+ if (mb->skip_arg_count <= mb->ignore_skip_arg)
{
ecode += PRIV(OP_lengths)[*ecode] + ecode[1];
break;
}
- RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, mb,
eptrb, RM57);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- /* Pass back the current skip name by overloading md->start_match_ptr and
+ /* Pass back the current skip name by overloading mb->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 md->ignore_skip_arg set to the value of md->skip_arg_count. */
+ with mb->ignore_skip_arg set to the value of mb->skip_arg_count. */
- md->start_match_ptr = ecode + 2;
+ mb->start_match_ptr = ecode + 2;
RRETURN(MATCH_SKIP_ARG);
/* For THEN (and THEN_ARG) we pass back the address of the opcode, so that
@@ -840,21 +886,21 @@ for (;;)
match pointer to do this. */
case OP_THEN:
- RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb,
eptrb, RM54);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- md->start_match_ptr = ecode;
+ mb->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 */
+ mb->nomatch_mark = ecode + 2;
+ mb->mark = NULL; /* In case previously set by assertion */
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top,
- md, eptrb, RM58);
+ mb, eptrb, RM58);
if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
- md->mark == NULL) md->mark = ecode + 2;
+ mb->mark == NULL) mb->mark = ecode + 2;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- md->start_match_ptr = ecode;
+ mb->start_match_ptr = ecode;
RRETURN(MATCH_THEN);
/* Handle an atomic group that does not contain any capturing parentheses.
@@ -873,26 +919,26 @@ for (;;)
case OP_ONCE_NC:
prev = ecode;
saved_eptr = eptr;
- save_mark = md->mark;
+ save_mark = mb->mark;
do
{
- RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM64);
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, eptrb, RM64);
if (rrc == MATCH_MATCH) /* Note: _not_ MATCH_ACCEPT */
{
- mstart = md->start_match_ptr;
+ mstart = mb->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))
+ next_ecode = ecode + GET(ecode,1);
+ if (mb->start_match_ptr < next_ecode &&
+ (*ecode == OP_ALT || *next_ecode == OP_ALT))
rrc = MATCH_NOMATCH;
}
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode,1);
- md->mark = save_mark;
+ mb->mark = save_mark;
}
while (*ecode == OP_ALT);
@@ -905,8 +951,8 @@ for (;;)
do ecode += GET(ecode, 1); while (*ecode == OP_ALT);
- offset_top = md->end_offset_top;
- eptr = md->end_match_ptr;
+ offset_top = mb->end_offset_top;
+ eptr = mb->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.
@@ -925,14 +971,14 @@ for (;;)
if (*ecode == OP_KETRMIN)
{
- RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM65);
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, eptrb, RM65);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode = prev;
goto TAIL_RECURSE;
}
else /* OP_KETRMAX */
{
- RMATCH(eptr, prev, offset_top, md, eptrb, RM66);
+ RMATCH(eptr, prev, offset_top, mb, eptrb, RM66);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += 1 + LINK_SIZE;
goto TAIL_RECURSE;
@@ -958,29 +1004,20 @@ for (;;)
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)
+ if (offset < mb->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;
+ save_offset1 = mb->ovector[offset];
+ save_offset2 = mb->ovector[offset+1];
+ save_offset3 = mb->ovector[mb->offset_end - number];
+ save_capture_last = mb->capture_last;
+ save_mark = mb->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);
+ mb->ovector[mb->offset_end - number] = eptr - mb->start_subject;
for (;;)
{
- if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
- RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ if (op >= OP_SBRA) mb->match_function_type |= MATCH_CBEGROUP;
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb,
eptrb, RM1);
if (rrc == MATCH_ONCE) break; /* Backing up through an atomic group */
@@ -997,25 +1034,24 @@ for (;;)
if (rrc == MATCH_THEN)
{
- next = ecode + GET(ecode,1);
- if (md->start_match_ptr < next &&
- (*ecode == OP_ALT || *next == OP_ALT))
+ next_ecode = ecode + GET(ecode,1);
+ if (mb->start_match_ptr < next_ecode &&
+ (*ecode == OP_ALT || *next_ecode == OP_ALT))
rrc = MATCH_NOMATCH;
}
/* Anything other than NOMATCH is passed back. */
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- md->capture_last = save_capture_last;
+ mb->capture_last = save_capture_last;
ecode += GET(ecode, 1);
- md->mark = save_mark;
+ mb->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;
+ mb->ovector[offset] = save_offset1;
+ mb->ovector[offset+1] = save_offset2;
+ mb->ovector[mb->offset_end - number] = save_offset3;
/* At this point, rrc will be one of MATCH_ONCE or MATCH_NOMATCH. */
@@ -1028,11 +1064,6 @@ for (;;)
/* 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.
@@ -1049,25 +1080,24 @@ for (;;)
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
+ reached. This is tested by comparing mb->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;
+ mb->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)
+ else if (!mb->hasthen && ecode[GET(ecode, 1)] != OP_ALT)
{
ecode += PRIV(OP_lengths)[*ecode];
goto TAIL_RECURSE;
@@ -1075,9 +1105,9 @@ for (;;)
/* In all other cases, we have to make another call to match(). */
- save_mark = md->mark;
- save_capture_last = md->capture_last;
- RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb,
+ save_mark = mb->mark;
+ save_capture_last = mb->capture_last;
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb, eptrb,
RM2);
/* See comment in the code for capturing groups above about handling
@@ -1085,9 +1115,9 @@ for (;;)
if (rrc == MATCH_THEN)
{
- next = ecode + GET(ecode,1);
- if (md->start_match_ptr < next &&
- (*ecode == OP_ALT || *next == OP_ALT))
+ next_ecode = ecode + GET(ecode,1);
+ if (mb->start_match_ptr < next_ecode &&
+ (*ecode == OP_ALT || *next_ecode == OP_ALT))
rrc = MATCH_NOMATCH;
}
@@ -1095,31 +1125,32 @@ for (;;)
{
if (rrc == MATCH_ONCE)
{
- const pcre_uchar *scode = ecode;
+ PCRE2_SPTR 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;
+ if (mb->once_target == scode) rrc = MATCH_NOMATCH;
}
RRETURN(rrc);
}
ecode += GET(ecode, 1);
- md->mark = save_mark;
+ mb->mark = save_mark;
if (*ecode != OP_ALT) break;
- md->capture_last = save_capture_last;
+ mb->capture_last = save_capture_last;
}
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
+ here from BRAZERO with allow_zero set TRUE. The ovector 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. */
+ reducing the amount of stack needed. If the ovector is too small for
+ capturing, treat as non-capturing. */
case OP_CBRAPOS:
case OP_SCBRAPOS:
@@ -1128,25 +1159,15 @@ for (;;)
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) goto POSSESSIVE_NON_CAPTURE;
+ if (offset >= mb->offset_max) goto POSSESSIVE_NON_CAPTURE;
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;
+ code_offset = (int)(ecode - mb->start_code);
- DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
+ save_offset1 = mb->ovector[offset];
+ save_offset2 = mb->ovector[offset+1];
+ save_offset3 = mb->ovector[mb->offset_end - number];
+ save_capture_last = mb->capture_last;
/* 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
@@ -1159,24 +1180,23 @@ for (;;)
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,
+ mb->ovector[mb->offset_end - number] = eptr - mb->start_subject;
+ if (op >= OP_SBRA) mb->match_function_type |= MATCH_CBEGROUP;
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb,
eptrb, RM63);
if (rrc == MATCH_KETRPOS)
{
- offset_top = md->end_offset_top;
- ecode = md->start_code + code_offset;
- save_capture_last = md->capture_last;
+ offset_top = mb->end_offset_top;
+ ecode = mb->start_code + code_offset;
+ save_capture_last = mb->capture_last;
matched_once = TRUE;
- mstart = md->start_match_ptr; /* In case \K changed it */
- if (eptr == md->end_match_ptr) /* Matched an empty string */
+ mstart = mb->start_match_ptr; /* In case \K changed it */
+ if (eptr == mb->end_match_ptr) /* Matched an empty string */
{
do ecode += GET(ecode, 1); while (*ecode == OP_ALT);
break;
}
- eptr = md->end_match_ptr;
+ eptr = mb->end_match_ptr;
continue;
}
@@ -1185,23 +1205,23 @@ for (;;)
if (rrc == MATCH_THEN)
{
- next = ecode + GET(ecode,1);
- if (md->start_match_ptr < next &&
- (*ecode == OP_ALT || *next == OP_ALT))
+ next_ecode = ecode + GET(ecode,1);
+ if (mb->start_match_ptr < next_ecode &&
+ (*ecode == OP_ALT || *next_ecode == OP_ALT))
rrc = MATCH_NOMATCH;
}
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- md->capture_last = save_capture_last;
+ mb->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;
+ mb->ovector[offset] = save_offset1;
+ mb->ovector[offset+1] = save_offset2;
+ mb->ovector[mb->offset_end - number] = save_offset3;
}
if (allow_zero || matched_once)
@@ -1209,7 +1229,6 @@ for (;;)
ecode += 1 + LINK_SIZE;
break;
}
-
RRETURN(MATCH_NOMATCH);
/* Non-capturing possessive bracket with unlimited repeat. We come here
@@ -1223,26 +1242,26 @@ for (;;)
POSSESSIVE_NON_CAPTURE:
matched_once = FALSE;
- code_offset = (int)(ecode - md->start_code);
- save_capture_last = md->capture_last;
+ code_offset = (int)(ecode - mb->start_code);
+ save_capture_last = mb->capture_last;
for (;;)
{
- if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP;
- RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md,
+ if (op >= OP_SBRA) mb->match_function_type |= MATCH_CBEGROUP;
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, mb,
eptrb, RM48);
if (rrc == MATCH_KETRPOS)
{
- offset_top = md->end_offset_top;
- ecode = md->start_code + code_offset;
+ offset_top = mb->end_offset_top;
+ ecode = mb->start_code + code_offset;
matched_once = TRUE;
- mstart = md->start_match_ptr; /* In case \K reset it */
- if (eptr == md->end_match_ptr) /* Matched an empty string */
+ mstart = mb->start_match_ptr; /* In case \K reset it */
+ if (eptr == mb->end_match_ptr) /* Matched an empty string */
{
do ecode += GET(ecode, 1); while (*ecode == OP_ALT);
break;
}
- eptr = md->end_match_ptr;
+ eptr = mb->end_match_ptr;
continue;
}
@@ -1251,16 +1270,16 @@ for (;;)
if (rrc == MATCH_THEN)
{
- next = ecode + GET(ecode,1);
- if (md->start_match_ptr < next &&
- (*ecode == OP_ALT || *next == OP_ALT))
+ next_ecode = ecode + GET(ecode,1);
+ if (mb->start_match_ptr < next_ecode &&
+ (*ecode == OP_ALT || *next_ecode == OP_ALT))
rrc = MATCH_NOMATCH;
}
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
ecode += GET(ecode, 1);
if (*ecode != OP_ALT) break;
- md->capture_last = save_capture_last;
+ mb->capture_last = save_capture_last;
}
if (matched_once || allow_zero)
@@ -1291,41 +1310,52 @@ for (;;)
/* Because of the way auto-callout works during compile, a callout item is
inserted between OP_COND and an assertion condition. */
- if (*ecode == OP_CALLOUT)
+ if (*ecode == OP_CALLOUT || *ecode == OP_CALLOUT_STR)
{
- if (PUBL(callout) != NULL)
+ unsigned int callout_length = (*ecode == OP_CALLOUT)
+ ? PRIV(OP_lengths)[OP_CALLOUT] : GET(ecode, 1 + 2*LINK_SIZE);
+
+ if (mb->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;
-#if defined COMPILE_PCRE8
- cb.subject = (PCRE_SPTR)md->start_subject;
-#elif defined COMPILE_PCRE16
- cb.subject = (PCRE_SPTR16)md->start_subject;
-#elif defined COMPILE_PCRE32
- cb.subject = (PCRE_SPTR32)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);
+ pcre2_callout_block cb;
+ cb.version = 1;
cb.capture_top = offset_top/2;
- cb.capture_last = md->capture_last & CAPLMASK;
- /* Internal change requires this for API compatibility. */
- if (cb.capture_last == 0) cb.capture_last = -1;
- cb.callout_data = md->callout_data;
- cb.mark = md->nomatch_mark;
- if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH);
+ cb.capture_last = mb->capture_last & CAPLMASK;
+ cb.offset_vector = mb->ovector;
+ cb.mark = mb->nomatch_mark;
+ cb.subject = mb->start_subject;
+ cb.subject_length = (PCRE2_SIZE)(mb->end_subject - mb->start_subject);
+ cb.start_match = (PCRE2_SIZE)(mstart - mb->start_subject);
+ cb.current_position = (PCRE2_SIZE)(eptr - mb->start_subject);
+ cb.pattern_position = GET(ecode, 1);
+ cb.next_item_length = GET(ecode, 1 + LINK_SIZE);
+
+ if (*ecode == OP_CALLOUT)
+ {
+ cb.callout_number = ecode[1 + 2*LINK_SIZE];
+ cb.callout_string_offset = 0;
+ cb.callout_string = NULL;
+ cb.callout_string_length = 0;
+ }
+ else
+ {
+ cb.callout_number = 0;
+ cb.callout_string_offset = GET(ecode, 1 + 3*LINK_SIZE);
+ cb.callout_string = ecode + (1 + 4*LINK_SIZE) + 1;
+ cb.callout_string_length =
+ callout_length - (1 + 4*LINK_SIZE) - 2;
+ }
+
+ if ((rrc = mb->callout(&cb, mb->callout_data)) > 0)
+ RRETURN(MATCH_NOMATCH);
if (rrc < 0) RRETURN(rrc);
}
/* Advance ecode past the callout, so it now points to the condition. We
must adjust codelink so that the value of ecode+codelink is unchanged. */
- ecode += PRIV(OP_lengths)[OP_CALLOUT];
- codelink -= PRIV(OP_lengths)[OP_CALLOUT];
+ ecode += callout_length;
+ codelink -= callout_length;
}
/* Test the various possible conditions */
@@ -1333,63 +1363,69 @@ for (;;)
condition = FALSE;
switch(condcode = *ecode)
{
- case OP_RREF: /* Numbered group recursion test */
- if (md->recursive != NULL) /* Not recursing => FALSE */
+ case OP_RREF: /* Numbered group recursion test */
+ if (mb->recursive != NULL) /* Not recursing => FALSE */
{
- unsigned int recno = GET2(ecode, 1); /* Recursion group number*/
- condition = (recno == RREF_ANY || recno == md->recursive->group_num);
+ uint32_t recno = GET2(ecode, 1); /* Recursion group number*/
+ condition = (recno == RREF_ANY || recno == mb->recursive->group_num);
}
break;
case OP_DNRREF: /* Duplicate named group recursion test */
- if (md->recursive != NULL)
+ if (mb->recursive != NULL)
{
int count = GET2(ecode, 1 + IMM2_SIZE);
- pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
+ PCRE2_SPTR slot = mb->name_table + GET2(ecode, 1) * mb->name_entry_size;
while (count-- > 0)
{
- unsigned int recno = GET2(slot, 0);
- condition = recno == md->recursive->group_num;
+ uint32_t recno = GET2(slot, 0);
+ condition = recno == mb->recursive->group_num;
if (condition) break;
- slot += md->name_entry_size;
+ slot += mb->name_entry_size;
}
}
break;
- case OP_CREF: /* Numbered group used test */
+ case OP_CREF: /* Numbered group used test */
offset = GET2(ecode, 1) << 1; /* Doubled ref number */
- condition = offset < offset_top && md->offset_vector[offset] >= 0;
+ condition = offset < offset_top &&
+ mb->ovector[offset] != PCRE2_UNSET;
break;
case OP_DNCREF: /* Duplicate named group used test */
{
int count = GET2(ecode, 1 + IMM2_SIZE);
- pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
+ PCRE2_SPTR slot = mb->name_table + GET2(ecode, 1) * mb->name_entry_size;
while (count-- > 0)
{
offset = GET2(slot, 0) << 1;
- condition = offset < offset_top && md->offset_vector[offset] >= 0;
+ condition = offset < offset_top &&
+ mb->ovector[offset] != PCRE2_UNSET;
if (condition) break;
- slot += md->name_entry_size;
+ slot += mb->name_entry_size;
}
}
break;
- case OP_DEF: /* DEFINE - always false */
- case OP_FAIL: /* From optimized (?!) condition */
+ case OP_FALSE:
+ case OP_FAIL: /* The assertion (?!) becomes OP_FAIL */
+ break;
+
+ case OP_TRUE:
+ condition = TRUE;
break;
/* 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. */
+ the MATCH_CONDASSERT bit in mb->match_function_type causes it to stop at
+ the end of an assertion. */
default:
- md->match_function_type = MATCH_CONDASSERT;
- RMATCH(eptr, ecode, offset_top, md, NULL, RM3);
+ mb->match_function_type |= MATCH_CONDASSERT;
+ RMATCH(eptr, ecode, offset_top, mb, NULL, RM3);
if (rrc == MATCH_MATCH)
{
- if (md->end_offset_top > offset_top)
- offset_top = md->end_offset_top; /* Captures may have happened */
+ if (mb->end_offset_top > offset_top)
+ offset_top = mb->end_offset_top; /* Captures may have happened */
condition = TRUE;
/* Advance ecode past the assertion to the start of the first branch,
@@ -1435,8 +1471,8 @@ for (;;)
goto TAIL_RECURSE;
}
- md->match_function_type = MATCH_CBEGROUP;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM49);
+ mb->match_function_type |= MATCH_CBEGROUP;
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM49);
RRETURN(rrc);
}
@@ -1454,18 +1490,12 @@ for (;;)
case OP_CLOSE:
number = GET2(ecode, 1); /* Must be less than 65536 */
offset = number << 1;
-
-#ifdef PCRE_DEBUG
- printf("end bracket %d at *ACCEPT", number);
- printf("\n");
-#endif
-
- md->capture_last = (md->capture_last & OVFLMASK) | number;
- if (offset >= md->offset_max) md->capture_last |= OVFLBIT; else
+ mb->capture_last = (mb->capture_last & OVFLMASK) | number;
+ if (offset >= mb->offset_max) mb->capture_last |= OVFLBIT; else
{
- md->offset_vector[offset] =
- md->offset_vector[md->offset_end - number];
- md->offset_vector[offset+1] = (int)(eptr - md->start_subject);
+ mb->ovector[offset] =
+ mb->ovector[mb->offset_end - number];
+ mb->ovector[offset+1] = eptr - mb->start_subject;
/* If this group is at or above the current highwater mark, ensure that
any groups between the current high water mark and this group are marked
@@ -1473,9 +1503,9 @@ for (;;)
if (offset >= offset_top)
{
- register int *iptr = md->offset_vector + offset_top;
- register int *iend = md->offset_vector + offset;
- while (iptr < iend) *iptr++ = -1;
+ register PCRE2_SIZE *iptr = mb->ovector + offset_top;
+ register PCRE2_SIZE *iend = mb->ovector + offset;
+ while (iptr < iend) *iptr++ = PCRE2_UNSET;
offset_top = offset + 2;
}
}
@@ -1483,29 +1513,32 @@ for (;;)
break;
- /* End of the pattern, either real or forced. */
+ /* End of the pattern, either real or forced. In an assertion ACCEPT,
+ update the last used pointer. */
- case OP_END:
- case OP_ACCEPT:
case OP_ASSERT_ACCEPT:
+ if (eptr > mb->last_used_ptr) mb->last_used_ptr = eptr;
+
+ case OP_ACCEPT:
+ case OP_END:
/* 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
+ in a recursion if either PCRE2_NOTEMPTY is set, or if PCRE2_NOTEMPTY_ATSTART
is set and we have matched at the start of the subject. In both cases,
backtracking will then try other alternatives, if any. */
if (eptr == mstart && op != OP_ASSERT_ACCEPT &&
- md->recursive == NULL &&
- (md->notempty ||
- (md->notempty_atstart &&
- mstart == md->start_subject + md->start_offset)))
+ mb->recursive == NULL &&
+ ((mb->moptions & PCRE2_NOTEMPTY) != 0 ||
+ ((mb->moptions & PCRE2_NOTEMPTY_ATSTART) != 0 &&
+ mstart == mb->start_subject + mb->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) */
+ mb->end_match_ptr = eptr; /* Record where we ended */
+ mb->end_offset_top = offset_top; /* and how many extracts were taken */
+ mb->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. */
@@ -1520,17 +1553,17 @@ for (;;)
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
+ mb->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)
+ save_mark = mb->mark;
+ if ((mb->match_function_type & MATCH_CONDASSERT) != 0)
{
condassert = TRUE;
- md->match_function_type = 0;
+ mb->match_function_type &= ~MATCH_CONDASSERT;
}
else condassert = FALSE;
@@ -1538,29 +1571,29 @@ for (;;)
do
{
- RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM4);
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, NULL, RM4);
/* A match means that the assertion is true; break out of the loop
that matches its alternatives. */
if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT)
{
- mstart = md->start_match_ptr; /* In case \K reset it */
+ mstart = mb->start_match_ptr; /* In case \K reset it */
break;
}
/* If not matched, restore the previous mark setting. */
- md->mark = save_mark;
+ mb->mark = save_mark;
/* 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))
+ next_ecode = ecode + GET(ecode,1);
+ if (mb->start_match_ptr < next_ecode &&
+ (*ecode == OP_ALT || *next_ecode == OP_ALT))
rrc = MATCH_NOMATCH;
}
@@ -1589,7 +1622,7 @@ for (;;)
do ecode += GET(ecode,1); while (*ecode == OP_ALT);
ecode += 1 + LINK_SIZE;
- offset_top = md->end_offset_top;
+ offset_top = mb->end_offset_top;
continue;
/* Negative assertion: all branches must fail to match for the assertion to
@@ -1597,11 +1630,11 @@ for (;;)
case OP_ASSERT_NOT:
case OP_ASSERTBACK_NOT:
- save_mark = md->mark;
- if (md->match_function_type == MATCH_CONDASSERT)
+ save_mark = mb->mark;
+ if ((mb->match_function_type & MATCH_CONDASSERT) != 0)
{
condassert = TRUE;
- md->match_function_type = 0;
+ mb->match_function_type &= ~MATCH_CONDASSERT;
}
else condassert = FALSE;
@@ -1609,8 +1642,8 @@ for (;;)
do
{
- RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM5);
- md->mark = save_mark; /* Always restore the mark setting */
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, NULL, RM5);
+ mb->mark = save_mark; /* Always restore the mark setting */
switch(rrc)
{
@@ -1625,9 +1658,9 @@ for (;;)
THEN. */
case MATCH_THEN:
- next = ecode + GET(ecode,1);
- if (md->start_match_ptr < next &&
- (*ecode == OP_ALT || *next == OP_ALT))
+ next_ecode = ecode + GET(ecode,1);
+ if (mb->start_match_ptr < next_ecode &&
+ (*ecode == OP_ALT || *next_ecode == OP_ALT))
{
rrc = MATCH_NOMATCH;
break;
@@ -1671,14 +1704,14 @@ for (;;)
back a number of characters, not bytes. */
case OP_REVERSE:
-#ifdef SUPPORT_UTF
+ i = GET(ecode, 1);
+#ifdef SUPPORT_UNICODE
if (utf)
{
- i = GET(ecode, 1);
while (i-- > 0)
{
+ if (eptr <= mb->start_subject) RRETURN(MATCH_NOMATCH);
eptr--;
- if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH);
BACKCHAR(eptr);
}
}
@@ -1688,13 +1721,13 @@ for (;;)
/* 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);
+ if (i > eptr - mb->start_subject) RRETURN(MATCH_NOMATCH);
+ eptr -= i;
}
/* Save the earliest consulted character, then skip to next op code */
- if (eptr < md->start_used_ptr) md->start_used_ptr = eptr;
+ if (eptr < mb->start_used_ptr) mb->start_used_ptr = eptr;
ecode += 1 + LINK_SIZE;
break;
@@ -1703,34 +1736,49 @@ for (;;)
function is able to force a failure. */
case OP_CALLOUT:
- if (PUBL(callout) != NULL)
+ case OP_CALLOUT_STR:
{
- PUBL(callout_block) cb;
- cb.version = 2; /* Version 1 of the callout block */
- cb.callout_number = ecode[1];
- cb.offset_vector = md->offset_vector;
-#if defined COMPILE_PCRE8
- cb.subject = (PCRE_SPTR)md->start_subject;
-#elif defined COMPILE_PCRE16
- cb.subject = (PCRE_SPTR16)md->start_subject;
-#elif defined COMPILE_PCRE32
- cb.subject = (PCRE_SPTR32)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 & CAPLMASK;
- /* Internal change requires this for API compatibility. */
- if (cb.capture_last == 0) cb.capture_last = -1;
- 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);
+ unsigned int callout_length = (*ecode == OP_CALLOUT)
+ ? PRIV(OP_lengths)[OP_CALLOUT] : GET(ecode, 1 + 2*LINK_SIZE);
+
+ if (mb->callout != NULL)
+ {
+ pcre2_callout_block cb;
+ cb.version = 1;
+ cb.callout_number = ecode[LINK_SIZE + 1];
+ cb.capture_top = offset_top/2;
+ cb.capture_last = mb->capture_last & CAPLMASK;
+ cb.offset_vector = mb->ovector;
+ cb.mark = mb->nomatch_mark;
+ cb.subject = mb->start_subject;
+ cb.subject_length = (PCRE2_SIZE)(mb->end_subject - mb->start_subject);
+ cb.start_match = (PCRE2_SIZE)(mstart - mb->start_subject);
+ cb.current_position = (PCRE2_SIZE)(eptr - mb->start_subject);
+ cb.pattern_position = GET(ecode, 1);
+ cb.next_item_length = GET(ecode, 1 + LINK_SIZE);
+
+ if (*ecode == OP_CALLOUT)
+ {
+ cb.callout_number = ecode[1 + 2*LINK_SIZE];
+ cb.callout_string_offset = 0;
+ cb.callout_string = NULL;
+ cb.callout_string_length = 0;
+ }
+ else
+ {
+ cb.callout_number = 0;
+ cb.callout_string_offset = GET(ecode, 1 + 3*LINK_SIZE);
+ cb.callout_string = ecode + (1 + 4*LINK_SIZE) + 1;
+ cb.callout_string_length =
+ callout_length - (1 + 4*LINK_SIZE) - 2;
+ }
+
+ if ((rrc = mb->callout(&cb, mb->callout_data)) > 0)
+ RRETURN(MATCH_NOMATCH);
+ if (rrc < 0) RRETURN(rrc);
+ }
+ ecode += callout_length;
}
- ecode += 2 + 2*LINK_SIZE;
break;
/* Recursion either matches the current regex, or some subexpression. The
@@ -1743,7 +1791,7 @@ for (;;)
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.
+ OP_RECURSE_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
@@ -1752,75 +1800,106 @@ for (;;)
case OP_RECURSE:
{
+ ovecsave_frame *fr;
recursion_info *ri;
- unsigned int recno;
+ uint32_t recno;
- callpat = md->start_code + GET(ecode, 1);
- recno = (callpat == md->start_code)? 0 :
- GET2(callpat, 1 + LINK_SIZE);
+ callpat = mb->start_code + GET(ecode, 1);
+ recno = (callpat == mb->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.) */
+ /* Check for repeating a pattern 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)
+ for (ri = mb->recursive; ri != NULL; ri = ri->prevrec)
if (recno == ri->group_num && eptr == ri->subject_position)
- RRETURN(PCRE_ERROR_RECURSELOOP);
+ RRETURN(PCRE2_ERROR_RECURSELOOP);
/* Add to "recursing stack" */
new_recursive.group_num = recno;
- new_recursive.saved_capture_last = md->capture_last;
+ new_recursive.saved_capture_last = mb->capture_last;
new_recursive.subject_position = eptr;
- new_recursive.prevrec = md->recursive;
- md->recursive = &new_recursive;
+ new_recursive.prevrec = mb->recursive;
+ mb->recursive = &new_recursive;
/* Where to continue from afterwards */
ecode += 1 + LINK_SIZE;
- /* Now save the offset data */
+ /* When we are using the system stack for match() recursion we can call a
+ function that uses the system stack for preserving the ovector while
+ processing the pattern recursion, but only if the ovector is small
+ enough. */
- new_recursive.saved_max = md->offset_end;
- if (new_recursive.saved_max <= REC_STACK_SAVE_MAX)
- new_recursive.offset_save = stacksave;
+#ifndef HEAP_MATCH_RECURSE
+ if (mb->offset_end <= OP_RECURSE_STACK_SAVE_MAX)
+ {
+ rrc = op_recurse_ovecsave(eptr, callpat, mstart, offset_top, mb,
+ eptrb, rdepth);
+ mb->recursive = new_recursive.prevrec;
+ if (rrc != MATCH_MATCH && rrc != MATCH_ACCEPT) RRETURN(rrc);
+
+ /* 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 = mb->end_match_ptr;
+ mstart = mb->start_match_ptr;
+ break; /* End of processing OP_RECURSE */
+ }
+#endif
+ /* If the ovector is too big, or if we are using the heap for match()
+ recursion, we have to use the heap for saving the ovector. Used ovecsave
+ frames are kept on a chain and re-used. This makes a small improvement in
+ execution time on Linux. */
+
+ if (mb->ovecsave_chain != NULL)
+ {
+ new_recursive.ovec_save = mb->ovecsave_chain->saved_ovec;
+ mb->ovecsave_chain = mb->ovecsave_chain->next;
+ }
else
{
- new_recursive.offset_save =
- (int *)(PUBL(malloc))(new_recursive.saved_max * sizeof(int));
- if (new_recursive.offset_save == NULL) RRETURN(PCRE_ERROR_NOMEMORY);
+ fr = (ovecsave_frame *)(mb->memctl.malloc(sizeof(ovecsave_frame *) +
+ mb->offset_end * sizeof(PCRE2_SIZE), mb->memctl.memory_data));
+ if (fr == NULL) RRETURN(PCRE2_ERROR_NOMEMORY);
+ new_recursive.ovec_save = fr->saved_ovec;
}
- 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 and the last captured value. If there were nested
- recursions, md->recursive might be changed, so reset it before looping.
- */
+ memcpy(new_recursive.ovec_save, mb->ovector,
+ mb->offset_end * sizeof(PCRE2_SIZE));
+
+ /* Do the recursion. After processing each alternative, restore the
+ ovector data and the last captured value. This code has the same overall
+ logic as the code in the op_recurse_ovecsave() function, but is adapted
+ to use RMATCH/RRETURN and to release the heap block containing the saved
+ ovector. */
- DPRINTF(("Recursing into group %d\n", new_recursive.group_num));
cbegroup = (*callpat >= OP_SBRA);
do
{
- if (cbegroup) md->match_function_type = MATCH_CBEGROUP;
+ if (cbegroup) mb->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->capture_last = new_recursive.saved_capture_last;
- md->recursive = new_recursive.prevrec;
+ mb, eptrb, RM6);
+ memcpy(mb->ovector, new_recursive.ovec_save,
+ mb->offset_end * sizeof(PCRE2_SIZE));
+ mb->capture_last = new_recursive.saved_capture_last;
+ mb->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);
+ fr = (ovecsave_frame *)
+ ((uint8_t *)new_recursive.ovec_save - sizeof(ovecsave_frame *));
+ fr->next = mb->ovecsave_chain;
+ mb->ovecsave_chain = fr;
- /* Set where we got to in the subject, and reset the start in case
+ /* 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;
+ eptr = mb->end_match_ptr;
+ mstart = mb->start_match_ptr;
goto RECURSION_MATCHED; /* Exit loop; end processing */
}
@@ -1830,31 +1909,25 @@ for (;;)
if (rrc >= MATCH_BACKTRACK_MIN && rrc <= MATCH_BACKTRACK_MAX)
{
- if (new_recursive.offset_save != stacksave)
- (PUBL(free))(new_recursive.offset_save);
- RRETURN(MATCH_NOMATCH);
+ rrc = MATCH_NOMATCH;
+ goto RECURSION_RETURN;
}
/* Any return code other than NOMATCH is an error. */
- if (rrc != MATCH_NOMATCH)
- {
- 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;
+ if (rrc != MATCH_NOMATCH) goto RECURSION_RETURN;
+ mb->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_RETURN:
+ mb->recursive = new_recursive.prevrec;
+ fr = (ovecsave_frame *)
+ ((uint8_t *)new_recursive.ovec_save - sizeof(ovecsave_frame *));
+ fr->next = mb->ovecsave_chain;
+ mb->ovecsave_chain = fr;
+ RRETURN(rrc);
}
RECURSION_MATCHED:
@@ -1874,25 +1947,25 @@ for (;;)
optional ones preceded by BRAZERO or BRAMINZERO. */
case OP_BRAZERO:
- next = ecode + 1;
- RMATCH(eptr, next, offset_top, md, eptrb, RM10);
+ next_ecode = ecode + 1;
+ RMATCH(eptr, next_ecode, offset_top, mb, eptrb, RM10);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- do next += GET(next, 1); while (*next == OP_ALT);
- ecode = next + 1 + LINK_SIZE;
+ do next_ecode += GET(next_ecode, 1); while (*next_ecode == OP_ALT);
+ ecode = next_ecode + 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);
+ next_ecode = ecode + 1;
+ do next_ecode += GET(next_ecode, 1); while (*next_ecode == OP_ALT);
+ RMATCH(eptr, next_ecode + 1+LINK_SIZE, offset_top, mb, 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;
+ next_ecode = ecode+1;
+ do next_ecode += GET(next_ecode,1); while (*next_ecode == OP_ALT);
+ ecode = next_ecode + 1 + LINK_SIZE;
break;
/* BRAPOSZERO occurs before a possessive bracket group. Don't do anything
@@ -1931,10 +2004,11 @@ for (;;)
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 */
+ mb->end_match_ptr = eptr; /* For ONCE_NC */
+ mb->end_offset_top = offset_top;
+ mb->start_match_ptr = mstart;
+ if (eptr > mb->last_used_ptr) mb->last_used_ptr = eptr;
+ RRETURN(MATCH_MATCH); /* Sets mb->mark */
}
/* For capturing groups we have to check the group number back at the start
@@ -1951,24 +2025,20 @@ for (;;)
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)
+ if (mb->recursive != NULL && mb->recursive->group_num == number)
{
- md->end_match_ptr = eptr;
- md->start_match_ptr = mstart;
+ mb->end_match_ptr = eptr;
+ mb->start_match_ptr = mstart;
+ if (eptr > mb->last_used_ptr) mb->last_used_ptr = eptr;
RRETURN(MATCH_MATCH);
}
/* Deal with capturing */
- md->capture_last = (md->capture_last & OVFLMASK) | number;
- if (offset >= md->offset_max) md->capture_last |= OVFLBIT; else
+ mb->capture_last = (mb->capture_last & OVFLMASK) | number;
+ if (offset >= mb->offset_max) mb->capture_last |= OVFLBIT; 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
@@ -1982,16 +2052,15 @@ for (;;)
if (offset > offset_top)
{
- register int *iptr = md->offset_vector + offset_top;
- register int *iend = md->offset_vector + offset;
- while (iptr < iend) *iptr++ = -1;
+ register PCRE2_SIZE *iptr = mb->ovector + offset_top;
+ register PCRE2_SIZE *iend = mb->ovector + offset;
+ while (iptr < iend) *iptr++ = PCRE2_UNSET;
}
/* 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);
+ mb->ovector[offset] = mb->ovector[mb->offset_end - number];
+ mb->ovector[offset+1] = eptr - mb->start_subject;
if (offset_top <= offset) offset_top = offset + 2;
}
}
@@ -2003,9 +2072,10 @@ for (;;)
if (*ecode == OP_KETRPOS)
{
- md->start_match_ptr = mstart; /* In case \K reset it */
- md->end_match_ptr = eptr;
- md->end_offset_top = offset_top;
+ mb->start_match_ptr = mstart; /* In case \K reset it */
+ mb->end_match_ptr = eptr;
+ mb->end_offset_top = offset_top;
+ if (eptr > mb->last_used_ptr) mb->last_used_ptr = eptr;
RRETURN(MATCH_KETRPOS);
}
@@ -2022,9 +2092,9 @@ for (;;)
{
if (*prev == OP_ONCE)
{
- RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM12);
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, eptrb, RM12);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- md->once_target = prev; /* Level at which to change to MATCH_NOMATCH */
+ mb->once_target = prev; /* Level at which to change to MATCH_NOMATCH */
RRETURN(MATCH_ONCE);
}
ecode += 1 + LINK_SIZE; /* Carry on at this level */
@@ -2039,18 +2109,18 @@ for (;;)
if (*ecode == OP_KETRMIN)
{
- RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM7);
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, eptrb, RM7);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (*prev == OP_ONCE)
{
- RMATCH(eptr, prev, offset_top, md, eptrb, RM8);
+ RMATCH(eptr, prev, offset_top, mb, eptrb, RM8);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- md->once_target = prev; /* Level at which to change to MATCH_NOMATCH */
+ mb->once_target = prev; /* Level at which to change to MATCH_NOMATCH */
RRETURN(MATCH_ONCE);
}
if (*prev >= OP_SBRA) /* Could match an empty string */
{
- RMATCH(eptr, prev, offset_top, md, eptrb, RM50);
+ RMATCH(eptr, prev, offset_top, mb, eptrb, RM50);
RRETURN(rrc);
}
ecode = prev;
@@ -2058,14 +2128,14 @@ for (;;)
}
else /* OP_KETRMAX */
{
- RMATCH(eptr, prev, offset_top, md, eptrb, RM13);
- if (rrc == MATCH_ONCE && md->once_target == prev) rrc = MATCH_NOMATCH;
+ RMATCH(eptr, prev, offset_top, mb, eptrb, RM13);
+ if (rrc == MATCH_ONCE && mb->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);
+ RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, mb, eptrb, RM9);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- md->once_target = prev;
+ mb->once_target = prev;
RRETURN(MATCH_ONCE);
}
ecode += 1 + LINK_SIZE;
@@ -2076,21 +2146,26 @@ for (;;)
/* Not multiline mode: start of subject assertion, unless notbol. */
case OP_CIRC:
- if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH);
+ if ((mb->moptions & PCRE2_NOTBOL) != 0 && eptr == mb->start_subject)
+ RRETURN(MATCH_NOMATCH);
/* Start of subject assertion */
case OP_SOD:
- if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH);
+ if (eptr != mb->start_subject) RRETURN(MATCH_NOMATCH);
ecode++;
break;
- /* Multiline mode: start of subject unless notbol, or after any newline. */
+ /* Multiline mode: start of subject unless notbol, or after any newline
+ except for one at the very end, unless PCRE2_ALT_CIRCUMFLEX is set. */
case OP_CIRCM:
- if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH);
- if (eptr != md->start_subject &&
- (eptr == md->end_subject || !WAS_NEWLINE(eptr)))
+ if ((mb->moptions & PCRE2_NOTBOL) != 0 && eptr == mb->start_subject)
+ RRETURN(MATCH_NOMATCH);
+ if (eptr != mb->start_subject &&
+ ((eptr == mb->end_subject &&
+ (mb->poptions & PCRE2_ALT_CIRCUMFLEX) == 0) ||
+ !WAS_NEWLINE(eptr)))
RRETURN(MATCH_NOMATCH);
ecode++;
break;
@@ -2098,7 +2173,7 @@ for (;;)
/* Start of match assertion */
case OP_SOM:
- if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH);
+ if (eptr != mb->start_subject + mb->start_offset) RRETURN(MATCH_NOMATCH);
ecode++;
break;
@@ -2113,25 +2188,25 @@ for (;;)
unless noteol is set. */
case OP_DOLLM:
- if (eptr < md->end_subject)
+ if (eptr < mb->end_subject)
{
if (!IS_NEWLINE(eptr))
{
- if (md->partial != 0 &&
- eptr + 1 >= md->end_subject &&
+ if (mb->partial != 0 &&
+ eptr + 1 >= mb->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
UCHAR21TEST(eptr) == NLBLOCK->nl[0])
{
- md->hitend = TRUE;
- if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ mb->hitend = TRUE;
+ if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL);
}
RRETURN(MATCH_NOMATCH);
}
}
else
{
- if (md->noteol) RRETURN(MATCH_NOMATCH);
+ if ((mb->moptions & PCRE2_NOTEOL) != 0) RRETURN(MATCH_NOMATCH);
SCHECK_PARTIAL();
}
ecode++;
@@ -2141,15 +2216,15 @@ for (;;)
subject unless noteol is set. */
case OP_DOLL:
- if (md->noteol) RRETURN(MATCH_NOMATCH);
- if (!md->endonly) goto ASSERT_NL_OR_EOS;
+ if ((mb->moptions & PCRE2_NOTEOL) != 0) RRETURN(MATCH_NOMATCH);
+ if ((mb->poptions & PCRE2_DOLLAR_ENDONLY) == 0) 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);
+ if (eptr < mb->end_subject) RRETURN(MATCH_NOMATCH);
SCHECK_PARTIAL();
ecode++;
break;
@@ -2158,17 +2233,17 @@ for (;;)
case OP_EODN:
ASSERT_NL_OR_EOS:
- if (eptr < md->end_subject &&
- (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen))
+ if (eptr < mb->end_subject &&
+ (!IS_NEWLINE(eptr) || eptr != mb->end_subject - mb->nllen))
{
- if (md->partial != 0 &&
- eptr + 1 >= md->end_subject &&
+ if (mb->partial != 0 &&
+ eptr + 1 >= mb->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
UCHAR21TEST(eptr) == NLBLOCK->nl[0])
{
- md->hitend = TRUE;
- if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ mb->hitend = TRUE;
+ if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL);
}
RRETURN(MATCH_NOMATCH);
}
@@ -2190,19 +2265,18 @@ for (;;)
be "non-word" characters. Remember the earliest consulted character for
partial matching. */
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
/* Get status of previous character */
- if (eptr == md->start_subject) prev_is_word = FALSE; else
+ if (eptr == mb->start_subject) prev_is_word = FALSE; else
{
- PCRE_PUCHAR lastptr = eptr - 1;
+ PCRE2_SPTR lastptr = eptr - 1;
BACKCHAR(lastptr);
- if (lastptr < md->start_used_ptr) md->start_used_ptr = lastptr;
+ if (lastptr < mb->start_used_ptr) mb->start_used_ptr = lastptr;
GETCHAR(c, lastptr);
-#ifdef SUPPORT_UCP
- if (md->use_ucp)
+ if ((mb->poptions & PCRE2_UCP) != 0)
{
if (c == '_') prev_is_word = TRUE; else
{
@@ -2211,22 +2285,23 @@ for (;;)
}
}
else
-#endif
- prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
+ prev_is_word = c < 256 && (mb->ctypes[c] & ctype_word) != 0;
}
/* Get status of next character */
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
cur_is_word = FALSE;
}
else
{
+ PCRE2_SPTR nextptr = eptr + 1;
+ FORWARDCHARTEST(nextptr, mb->end_subject);
+ if (nextptr > mb->last_used_ptr) mb->last_used_ptr = nextptr;
GETCHAR(c, eptr);
-#ifdef SUPPORT_UCP
- if (md->use_ucp)
+ if ((mb->poptions & PCRE2_UCP) != 0)
{
if (c == '_') cur_is_word = TRUE; else
{
@@ -2235,24 +2310,23 @@ for (;;)
}
}
else
-#endif
- cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0;
+ cur_is_word = c < 256 && (mb->ctypes[c] & ctype_word) != 0;
}
}
else
-#endif
+#endif /* SUPPORT UTF */
- /* Not in UTF-8 mode, but we may still have PCRE_UCP set, and for
+ /* Not in UTF-8 mode, but we may still have PCRE2_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 == mb->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)
+ if (eptr <= mb->start_used_ptr) mb->start_used_ptr = eptr - 1;
+#ifdef SUPPORT_UNICODE
+ if ((mb->poptions & PCRE2_UCP) != 0)
{
c = eptr[-1];
if (c == '_') prev_is_word = TRUE; else
@@ -2264,31 +2338,34 @@ for (;;)
else
#endif
prev_is_word = MAX_255(eptr[-1])
- && ((md->ctypes[eptr[-1]] & ctype_word) != 0);
+ && ((mb->ctypes[eptr[-1]] & ctype_word) != 0);
}
/* Get status of next character */
- if (eptr >= md->end_subject)
+ if (eptr >= mb->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
+ if (eptr >= mb->last_used_ptr) mb->last_used_ptr = eptr + 1;
+#ifdef SUPPORT_UNICODE
+ if ((mb->poptions & PCRE2_UCP) != 0)
{
- int cat = UCD_CATEGORY(c);
- cur_is_word = (cat == ucp_L || cat == ucp_N);
+ c = *eptr;
+ if (c == '_') cur_is_word = TRUE; else
+ {
+ int cat = UCD_CATEGORY(c);
+ cur_is_word = (cat == ucp_L || cat == ucp_N);
+ }
}
- }
- else
+ else
#endif
- cur_is_word = MAX_255(*eptr)
- && ((md->ctypes[*eptr] & ctype_word) != 0);
+ cur_is_word = MAX_255(*eptr)
+ && ((mb->ctypes[*eptr] & ctype_word) != 0);
+ }
}
/* Now see if the situation is what we want */
@@ -2304,14 +2381,14 @@ for (;;)
case OP_ANY:
if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
- if (md->partial != 0 &&
- eptr + 1 >= md->end_subject &&
+ if (mb->partial != 0 &&
+ eptr + 1 >= mb->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
UCHAR21TEST(eptr) == NLBLOCK->nl[0])
{
- md->hitend = TRUE;
- if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ mb->hitend = TRUE;
+ if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL);
}
/* Fall through */
@@ -2319,23 +2396,24 @@ for (;;)
/* Match any single character whatsoever. */
case OP_ALLANY:
- if (eptr >= md->end_subject) /* DO NOT merge the eptr++ here; it must */
+ if (eptr >= mb->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++);
+#ifdef SUPPORT_UNICODE
+ if (utf) ACROSSCHAR(eptr < mb->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. */
+ /* Match a single code unit, even in UTF-8 mode. This opcode really does
+ match any code unit, even newline. (It really should be called ANYCODEUNIT,
+ of course - the byte name is from pre-16 bit days.) */
case OP_ANYBYTE:
- if (eptr >= md->end_subject) /* DO NOT merge the eptr++ here; it must */
+ if (eptr >= mb->end_subject) /* DO NOT merge the eptr++ here; it must */
{ /* not be updated before SCHECK_PARTIAL. */
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -2345,109 +2423,109 @@ for (;;)
break;
case OP_NOT_DIGIT:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (
-#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+#ifdef SUPPORT_WIDE_CHARS
c < 256 &&
#endif
- (md->ctypes[c] & ctype_digit) != 0
+ (mb->ctypes[c] & ctype_digit) != 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_DIGIT:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (
-#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+#ifdef SUPPORT_WIDE_CHARS
c > 255 ||
#endif
- (md->ctypes[c] & ctype_digit) == 0
+ (mb->ctypes[c] & ctype_digit) == 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_NOT_WHITESPACE:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (
-#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+#ifdef SUPPORT_WIDE_CHARS
c < 256 &&
#endif
- (md->ctypes[c] & ctype_space) != 0
+ (mb->ctypes[c] & ctype_space) != 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_WHITESPACE:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (
-#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+#ifdef SUPPORT_WIDE_CHARS
c > 255 ||
#endif
- (md->ctypes[c] & ctype_space) == 0
+ (mb->ctypes[c] & ctype_space) == 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_NOT_WORDCHAR:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (
-#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+#ifdef SUPPORT_WIDE_CHARS
c < 256 &&
#endif
- (md->ctypes[c] & ctype_word) != 0
+ (mb->ctypes[c] & ctype_word) != 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_WORDCHAR:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
if (
-#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8)
+#ifdef SUPPORT_WIDE_CHARS
c > 255 ||
#endif
- (md->ctypes[c] & ctype_word) == 0
+ (mb->ctypes[c] & ctype_word) == 0
)
RRETURN(MATCH_NOMATCH);
ecode++;
break;
case OP_ANYNL:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -2458,7 +2536,7 @@ for (;;)
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
}
@@ -2475,14 +2553,14 @@ for (;;)
case 0x2028:
case 0x2029:
#endif /* Not EBCDIC */
- if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+ if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) RRETURN(MATCH_NOMATCH);
break;
}
ecode++;
break;
case OP_NOT_HSPACE:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -2497,7 +2575,7 @@ for (;;)
break;
case OP_HSPACE:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -2512,7 +2590,7 @@ for (;;)
break;
case OP_NOT_VSPACE:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -2527,7 +2605,7 @@ for (;;)
break;
case OP_VSPACE:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -2541,20 +2619,20 @@ for (;;)
ecode++;
break;
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
/* Check the next character by Unicode property. We will get here only
if the support is in the binary; otherwise a compile-time error occurs. */
case OP_PROP:
case OP_NOTPROP:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(c, eptr);
{
- const pcre_uint32 *cp;
+ const uint32_t *cp;
const ucd_record *prop = GET_UCD(c);
switch(ecode[1])
@@ -2641,7 +2719,7 @@ for (;;)
/* This should never occur */
default:
- RRETURN(PCRE_ERROR_INTERNAL);
+ RRETURN(PCRE2_ERROR_INTERNAL);
}
ecode += 3;
@@ -2652,7 +2730,7 @@ for (;;)
is in the binary; otherwise a compile-time error occurs. */
case OP_EXTUNI:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -2662,7 +2740,7 @@ for (;;)
int lgb, rgb;
GETCHARINCTEST(c, eptr);
lgb = UCD_GRAPHBREAK(c);
- while (eptr < md->end_subject)
+ while (eptr < mb->end_subject)
{
int len = 1;
if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
@@ -2675,26 +2753,11 @@ for (;;)
CHECK_PARTIAL();
ecode++;
break;
-#endif /* SUPPORT_UCP */
+#endif /* SUPPORT_UNICODE */
/* 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). 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.
+ item to see if there is repeat information following.
The OP_REF and OP_REFI opcodes are used for a reference to a numbered group
or to a non-duplicated named group. For a duplicated named group, OP_DNREF
@@ -2706,24 +2769,18 @@ for (;;)
caseless = op == OP_DNREFI;
{
int count = GET2(ecode, 1+IMM2_SIZE);
- pcre_uchar *slot = md->name_table + GET2(ecode, 1) * md->name_entry_size;
+ PCRE2_SPTR slot = mb->name_table + GET2(ecode, 1) * mb->name_entry_size;
ecode += 1 + 2*IMM2_SIZE;
- /* Setting the default length first and initializing 'offset' avoids
- compiler warnings in the REF_REPEAT code. */
+ /* Initializing 'offset' avoids a compiler warning in the REF_REPEAT
+ code. */
- length = (md->jscript_compat)? 0 : -1;
offset = 0;
-
while (count-- > 0)
{
offset = GET2(slot, 0) << 1;
- if (offset < offset_top && md->offset_vector[offset] >= 0)
- {
- length = md->offset_vector[offset+1] - md->offset_vector[offset];
- break;
- }
- slot += md->name_entry_size;
+ if (offset < offset_top && mb->ovector[offset] != PCRE2_UNSET) break;
+ slot += mb->name_entry_size;
}
}
goto REF_REPEAT;
@@ -2733,10 +2790,6 @@ for (;;)
caseless = op == OP_REFI;
offset = GET2(ecode, 1) << 1; /* Doubled ref number */
ecode += 1 + IMM2_SIZE;
- 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 */
@@ -2765,25 +2818,36 @@ for (;;)
ecode += 1 + 2 * IMM2_SIZE;
break;
- default: /* No repeat follows */
- if ((length = match_ref(offset, eptr, length, md, caseless)) < 0)
+ default: /* No repeat follows */
{
- if (length == -2) eptr = md->end_subject; /* Partial match */
- CHECK_PARTIAL();
- RRETURN(MATCH_NOMATCH);
+ int rc = match_ref(offset, offset_top, eptr, mb, caseless, &length);
+ if (rc != 0)
+ {
+ if (rc > 0) eptr = mb->end_subject; /* Partial match */
+ 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. */
+ /* Handle repeated back references. If a set group has length zero, just
+ continue with the main loop, because it matches however many times. For an
+ unset reference, if the minimum is zero, we can also just continue. We an
+ also continue if PCRE2_MATCH_UNSET_BACKREF is set, because this makes unset
+ group be have as a zero-length group. For any other unset cases, carrying
+ on will result in NOMATCH. */
- if (length == 0) continue;
- if (length < 0 && min == 0) continue;
+ if (offset < offset_top && mb->ovector[offset] != PCRE2_UNSET)
+ {
+ if (mb->ovector[offset] == mb->ovector[offset + 1]) continue;
+ }
+ else /* Group is not set */
+ {
+ if (min == 0 || (mb->poptions & PCRE2_MATCH_UNSET_BACKREF) != 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
@@ -2791,10 +2855,11 @@ for (;;)
for (i = 1; i <= min; i++)
{
- int slength;
- if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
+ PCRE2_SIZE slength;
+ int rc = match_ref(offset, offset_top, eptr, mb, caseless, &slength);
+ if (rc != 0)
{
- if (slength == -2) eptr = md->end_subject; /* Partial match */
+ if (rc > 0) eptr = mb->end_subject; /* Partial match */
CHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
@@ -2812,13 +2877,15 @@ for (;;)
{
for (fi = min;; fi++)
{
- int slength;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM14);
+ int rc;
+ PCRE2_SIZE slength;
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM14);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
+ rc = match_ref(offset, offset_top, eptr, mb, caseless, &slength);
+ if (rc != 0)
{
- if (slength == -2) eptr = md->end_subject; /* Partial match */
+ if (rc > 0) eptr = mb->end_subject; /* Partial match */
CHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
@@ -2827,36 +2894,76 @@ for (;;)
/* Control never gets here */
}
- /* If maximizing, find the longest string and work backwards */
+ /* If maximizing, find the longest string and work backwards, as long as
+ the matched lengths for each iteration are the same. */
else
{
+ BOOL samelengths = TRUE;
pp = eptr;
+ length = mb->ovector[offset+1] - mb->ovector[offset];
+
for (i = min; i < max; i++)
{
- int slength;
- if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0)
+ PCRE2_SIZE slength;
+ int rc = match_ref(offset, offset_top, eptr, mb, caseless, &slength);
+
+ if (rc != 0)
{
/* Can't use CHECK_PARTIAL because we don't want to update eptr in
the soft partial matching case. */
- if (slength == -2 && md->partial != 0 &&
- md->end_subject > md->start_used_ptr)
+ if (rc > 0 && mb->partial != 0 &&
+ mb->end_subject > mb->start_used_ptr)
{
- md->hitend = TRUE;
- if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ mb->hitend = TRUE;
+ if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL);
}
break;
}
+
+ if (slength != length) samelengths = FALSE;
eptr += slength;
}
- while (eptr >= pp)
+ /* If the length matched for each repetition is the same as the length of
+ the captured group, we can easily work backwards. This is the normal
+ case. However, in caseless UTF-8 mode there are pairs of case-equivalent
+ characters whose lengths (in terms of code units) differ. However, this
+ is very rare, so we handle it by re-matching fewer and fewer times. */
+
+ if (samelengths)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM15);
- if (rrc != MATCH_NOMATCH) RRETURN(rrc);
- eptr -= length;
+ while (eptr >= pp)
+ {
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM15);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ eptr -= length;
+ }
+ }
+
+ /* The rare case of non-matching lengths. Re-scan the repetition for each
+ iteration. We know that match_ref() will succeed every time. */
+
+ else
+ {
+ max = i;
+ for (;;)
+ {
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM68);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (eptr == pp) break; /* Failed after minimal repetition */
+ eptr = pp;
+ max--;
+ for (i = min; i < max; i++)
+ {
+ PCRE2_SIZE slength;
+ (void)match_ref(offset, offset_top, eptr, mb, caseless, &slength);
+ eptr += slength;
+ }
+ }
}
+
RRETURN(MATCH_NOMATCH);
}
/* Control never gets here */
@@ -2877,9 +2984,9 @@ for (;;)
{
/* The data variable is saved across frames, so the byte map needs to
be stored there. */
-#define BYTE_MAP ((pcre_uint8 *)data)
+#define BYTE_MAP ((uint8_t *)data)
data = ecode + 1; /* Save for matching */
- ecode += 1 + (32 / sizeof(pcre_uchar)); /* Advance past the item */
+ ecode += 1 + (32 / sizeof(PCRE2_UCHAR)); /* Advance past the item */
switch (*ecode)
{
@@ -2918,12 +3025,12 @@ for (;;)
/* First, ensure the minimum number of matches are present. */
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -2943,13 +3050,13 @@ for (;;)
{
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
c = *eptr++;
-#ifndef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
if (c > 255)
{
if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
@@ -2970,15 +3077,15 @@ for (;;)
if (minimize)
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM16);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM16);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -2998,16 +3105,16 @@ for (;;)
{
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM17);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM17);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
c = *eptr++;
-#ifndef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
if (c > 255)
{
if (op == OP_CLASS) RRETURN(MATCH_NOMATCH);
@@ -3026,13 +3133,13 @@ for (;;)
{
pp = eptr;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -3051,7 +3158,7 @@ for (;;)
for (;;)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM18);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM18);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break; /* Stop if tried at original pos */
BACKCHAR(eptr);
@@ -3063,13 +3170,13 @@ for (;;)
{
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
c = *eptr;
-#ifndef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH != 8
if (c > 255)
{
if (op == OP_CLASS) break;
@@ -3084,7 +3191,7 @@ for (;;)
while (eptr >= pp)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM19);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM19);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
}
@@ -3102,7 +3209,7 @@ for (;;)
32-bit libraries, codepoints greater than 255 may be encountered even when
UTF is not supported. */
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
{
data = ecode + 1 + LINK_SIZE; /* Save for matching */
@@ -3147,7 +3254,7 @@ for (;;)
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -3168,10 +3275,10 @@ for (;;)
{
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM20);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM20);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -3190,12 +3297,12 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
GETCHARLENTEST(c, eptr, len);
#else
c = *eptr;
@@ -3208,10 +3315,10 @@ for (;;)
for(;;)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM21);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM21);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (eptr-- == pp) break; /* Stop if tried at original pos */
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf) BACKCHAR(eptr);
#endif
}
@@ -3225,24 +3332,27 @@ for (;;)
/* Match a single character, casefully */
case OP_CHAR:
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
length = 1;
ecode++;
GETCHARLEN(fc, ecode, length);
- if (length > md->end_subject - eptr)
+ if (length > (PCRE2_SIZE)(mb->end_subject - eptr))
{
CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */
RRETURN(MATCH_NOMATCH);
}
- while (length-- > 0) if (*ecode++ != UCHAR21INC(eptr)) RRETURN(MATCH_NOMATCH);
+ for (; length > 0; length--)
+ {
+ if (*ecode++ != UCHAR21INC(eptr)) RRETURN(MATCH_NOMATCH);
+ }
}
else
#endif
/* Not UTF mode */
{
- if (md->end_subject - eptr < 1)
+ if (mb->end_subject - eptr < 1)
{
SCHECK_PARTIAL(); /* This one can use SCHECK_PARTIAL() */
RRETURN(MATCH_NOMATCH);
@@ -3256,13 +3366,13 @@ for (;;)
subject, give up immediately. */
case OP_CHARI:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
length = 1;
@@ -3276,8 +3386,8 @@ for (;;)
if (fc < 128)
{
- pcre_uint32 cc = UCHAR21(eptr);
- if (md->lcc[fc] != TABLE_GET(cc, md->lcc, cc)) RRETURN(MATCH_NOMATCH);
+ uint32_t cc = UCHAR21(eptr);
+ if (mb->lcc[fc] != TABLE_GET(cc, mb->lcc, cc)) RRETURN(MATCH_NOMATCH);
ecode++;
eptr++;
}
@@ -3288,7 +3398,7 @@ for (;;)
else
{
- pcre_uint32 dc;
+ uint32_t dc;
GETCHARINC(dc, eptr);
ecode += length;
@@ -3297,7 +3407,7 @@ for (;;)
if (fc != dc)
{
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
if (dc != UCD_OTHERCASE(fc))
#endif
RRETURN(MATCH_NOMATCH);
@@ -3305,12 +3415,12 @@ for (;;)
}
}
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
/* Not UTF mode */
{
- if (TABLE_GET(ecode[1], md->lcc, ecode[1])
- != TABLE_GET(*eptr, md->lcc, *eptr)) RRETURN(MATCH_NOMATCH);
+ if (TABLE_GET(ecode[1], mb->lcc, ecode[1])
+ != TABLE_GET(*eptr, mb->lcc, *eptr)) RRETURN(MATCH_NOMATCH);
eptr++;
ecode += 2;
}
@@ -3399,7 +3509,7 @@ for (;;)
for speed. */
REPEATCHAR:
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
length = 1;
@@ -3412,23 +3522,19 @@ for (;;)
if (length > 1)
{
-#ifdef SUPPORT_UCP
- pcre_uint32 othercase;
+ uint32_t 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
+ if (eptr <= mb->end_subject - length &&
+ memcmp(eptr, charptr, CU2BYTES(length)) == 0) eptr += length;
else if (oclength > 0 &&
- eptr <= md->end_subject - oclength &&
- memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength;
-#endif /* SUPPORT_UCP */
+ eptr <= mb->end_subject - oclength &&
+ memcmp(eptr, occhars, CU2BYTES(oclength)) == 0) eptr += oclength;
else
{
CHECK_PARTIAL();
@@ -3442,16 +3548,14 @@ for (;;)
{
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM22);
+ RMATCH(eptr, ecode, offset_top, mb, 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
+ if (eptr <= mb->end_subject - length &&
+ memcmp(eptr, charptr, CU2BYTES(length)) == 0) eptr += length;
else if (oclength > 0 &&
- eptr <= md->end_subject - oclength &&
- memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength;
-#endif /* SUPPORT_UCP */
+ eptr <= mb->end_subject - oclength &&
+ memcmp(eptr, occhars, CU2BYTES(oclength)) == 0) eptr += oclength;
else
{
CHECK_PARTIAL();
@@ -3466,13 +3570,11 @@ for (;;)
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
+ if (eptr <= mb->end_subject - length &&
+ memcmp(eptr, charptr, CU2BYTES(length)) == 0) eptr += length;
else if (oclength > 0 &&
- eptr <= md->end_subject - oclength &&
- memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength;
-#endif /* SUPPORT_UCP */
+ eptr <= mb->end_subject - oclength &&
+ memcmp(eptr, occhars, CU2BYTES(oclength)) == 0) eptr += oclength;
else
{
CHECK_PARTIAL();
@@ -3481,17 +3583,17 @@ for (;;)
}
if (possessive) continue; /* No backtracking */
+
+ /* After \C in UTF mode, pp might be in the middle of a Unicode
+ character. Use <= pp to ensure backtracking doesn't go too far. */
+
for(;;)
{
if (eptr <= pp) goto TAIL_RECURSE;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM23);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM23);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
-#ifdef SUPPORT_UCP
eptr--;
BACKCHAR(eptr);
-#else /* without SUPPORT_UCP */
- eptr -= length;
-#endif /* SUPPORT_UCP */
}
}
/* Control never gets here */
@@ -3502,7 +3604,8 @@ for (;;)
value of fc will always be < 128. */
}
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
+
/* When not in UTF-8 mode, load a single-byte character. */
fc = *ecode++;
@@ -3515,32 +3618,24 @@ for (;;)
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, (char *)eptr));
-
if (op >= OP_STARI) /* Caseless */
{
-#ifdef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
/* fc must be < 128 if UTF is enabled. */
- foc = md->fcc[fc];
+ foc = mb->fcc[fc];
#else
-#ifdef SUPPORT_UTF
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
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 */
+#endif /* SUPPORT_UNICODE */
+ foc = TABLE_GET(fc, mb->fcc, fc);
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
for (i = 1; i <= min; i++)
{
- pcre_uint32 cc; /* Faster than pcre_uchar */
- if (eptr >= md->end_subject)
+ uint32_t cc; /* Faster than PCRE2_UCHAR */
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -3554,11 +3649,11 @@ for (;;)
{
for (fi = min;; fi++)
{
- pcre_uint32 cc; /* Faster than pcre_uchar */
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM24);
+ uint32_t cc; /* Faster than PCRE2_UCHAR */
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM24);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -3574,8 +3669,8 @@ for (;;)
pp = eptr;
for (i = min; i < max; i++)
{
- pcre_uint32 cc; /* Faster than pcre_uchar */
- if (eptr >= md->end_subject)
+ uint32_t cc; /* Faster than PCRE2_UCHAR */
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -3588,7 +3683,7 @@ for (;;)
for (;;)
{
if (eptr == pp) goto TAIL_RECURSE;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM25);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM25);
eptr--;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
@@ -3602,7 +3697,7 @@ for (;;)
{
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -3616,10 +3711,10 @@ for (;;)
{
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM26);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM26);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -3633,7 +3728,7 @@ for (;;)
pp = eptr;
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -3645,7 +3740,7 @@ for (;;)
for (;;)
{
if (eptr == pp) goto TAIL_RECURSE;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM27);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM27);
eptr--;
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
}
@@ -3659,15 +3754,15 @@ for (;;)
case OP_NOT:
case OP_NOTI:
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
- register pcre_uint32 ch, och;
+ register uint32_t ch, och;
ecode++;
GETCHARINC(ch, ecode);
@@ -3679,24 +3774,19 @@ for (;;)
}
else
{
-#ifdef SUPPORT_UCP
if (ch > 127)
och = UCD_OTHERCASE(ch);
-#else
- if (ch > 127)
- och = ch;
-#endif /* SUPPORT_UCP */
else
- och = TABLE_GET(ch, md->fcc, ch);
+ och = TABLE_GET(ch, mb->fcc, ch);
if (ch == c || och == c) RRETURN(MATCH_NOMATCH);
}
}
else
-#endif
+#endif /* SUPPORT_UNICODE */
{
- register pcre_uint32 ch = ecode[1];
+ register uint32_t ch = ecode[1];
c = *eptr++;
- if (ch == c || (op == OP_NOTI && TABLE_GET(ch, md->fcc, ch) == c))
+ if (ch == c || (op == OP_NOTI && TABLE_GET(ch, mb->fcc, ch) == c))
RRETURN(MATCH_NOMATCH);
ecode += 2;
}
@@ -3788,45 +3878,37 @@ for (;;)
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, (char *)eptr));
-
if (op >= OP_NOTSTARI) /* Caseless */
{
-#ifdef SUPPORT_UTF
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
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 /* SUPPORT_UNICODE */
+ foc = TABLE_GET(fc, mb->fcc, fc);
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
- register pcre_uint32 d;
+ register uint32_t d;
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(d, eptr);
- if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH);
+ if (fc == d || (uint32_t)foc == d) RRETURN(MATCH_NOMATCH);
}
}
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
/* Not UTF mode */
{
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -3840,34 +3922,34 @@ for (;;)
if (minimize)
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
- register pcre_uint32 d;
+ register uint32_t d;
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM28);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM28);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(d, eptr);
- if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH);
+ if (fc == d || (uint32_t)foc == d) RRETURN(MATCH_NOMATCH);
}
}
else
-#endif /*SUPPORT_UTF */
+#endif /*SUPPORT_UNICODE */
/* Not UTF mode */
{
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM29);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM29);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -3885,39 +3967,43 @@ for (;;)
{
pp = eptr;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
- register pcre_uint32 d;
+ register uint32_t d;
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(d, eptr, len);
- if (fc == d || (unsigned int)foc == d) break;
+ if (fc == d || (uint32_t)foc == d) break;
eptr += len;
}
if (possessive) continue; /* No backtracking */
+
+ /* After \C in UTF mode, pp might be in the middle of a Unicode
+ character. Use <= pp to ensure backtracking doesn't go too far. */
+
for(;;)
{
if (eptr <= pp) goto TAIL_RECURSE;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM30);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM30);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
BACKCHAR(eptr);
}
}
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
/* Not UTF mode */
{
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -3929,7 +4015,7 @@ for (;;)
for (;;)
{
if (eptr == pp) goto TAIL_RECURSE;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM31);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM31);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
}
@@ -3942,13 +4028,13 @@ for (;;)
else
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
- register pcre_uint32 d;
+ register uint32_t d;
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -3963,7 +4049,7 @@ for (;;)
{
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -3976,16 +4062,16 @@ for (;;)
if (minimize)
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
- register pcre_uint32 d;
+ register uint32_t d;
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM32);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM32);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4000,10 +4086,10 @@ for (;;)
{
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM33);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM33);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4020,14 +4106,14 @@ for (;;)
{
pp = eptr;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
- register pcre_uint32 d;
+ register uint32_t d;
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -4037,10 +4123,14 @@ for (;;)
eptr += len;
}
if (possessive) continue; /* No backtracking */
+
+ /* After \C in UTF mode, pp might be in the middle of a Unicode
+ character. Use <= pp to ensure backtracking doesn't go too far. */
+
for(;;)
{
if (eptr <= pp) goto TAIL_RECURSE;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM34);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM34);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
BACKCHAR(eptr);
@@ -4052,7 +4142,7 @@ for (;;)
{
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -4064,7 +4154,7 @@ for (;;)
for (;;)
{
if (eptr == pp) goto TAIL_RECURSE;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM35);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM35);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
}
@@ -4139,7 +4229,7 @@ for (;;)
REPEATTYPE:
ctype = *ecode++; /* Code for the character type */
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
if (ctype == OP_PROP || ctype == OP_NOTPROP)
{
prop_fail_result = ctype == OP_NOTPROP;
@@ -4157,7 +4247,7 @@ for (;;)
if (min > 0)
{
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
if (prop_type >= 0)
{
switch(prop_type)
@@ -4166,7 +4256,7 @@ for (;;)
if (prop_fail_result) RRETURN(MATCH_NOMATCH);
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4179,7 +4269,7 @@ for (;;)
for (i = 1; i <= min; i++)
{
int chartype;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4196,7 +4286,7 @@ for (;;)
case PT_GC:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4210,7 +4300,7 @@ for (;;)
case PT_PC:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4224,7 +4314,7 @@ for (;;)
case PT_SC:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4239,7 +4329,7 @@ for (;;)
for (i = 1; i <= min; i++)
{
int category;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4259,7 +4349,7 @@ for (;;)
case PT_PXSPACE: /* POSIX space */
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4284,7 +4374,7 @@ for (;;)
for (i = 1; i <= min; i++)
{
int category;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4300,8 +4390,8 @@ for (;;)
case PT_CLIST:
for (i = 1; i <= min; i++)
{
- const pcre_uint32 *cp;
- if (eptr >= md->end_subject)
+ const uint32_t *cp;
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4321,7 +4411,7 @@ for (;;)
case PT_UCNC:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4337,7 +4427,7 @@ for (;;)
/* This should not occur */
default:
- RRETURN(PCRE_ERROR_INTERNAL);
+ RRETURN(PCRE2_ERROR_INTERNAL);
}
}
@@ -4348,7 +4438,7 @@ for (;;)
{
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4358,7 +4448,7 @@ for (;;)
int lgb, rgb;
GETCHARINCTEST(c, eptr);
lgb = UCD_GRAPHBREAK(c);
- while (eptr < md->end_subject)
+ while (eptr < mb->end_subject)
{
int len = 1;
if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
@@ -4373,58 +4463,58 @@ for (;;)
}
else
-#endif /* SUPPORT_UCP */
+#endif /* SUPPORT_UNICODE */
/* Handle all other cases when the coding is UTF-8 */
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf) switch(ctype)
{
case OP_ANY:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
- if (md->partial != 0 &&
- eptr + 1 >= md->end_subject &&
+ if (mb->partial != 0 &&
+ eptr + 1 >= mb->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
UCHAR21(eptr) == NLBLOCK->nl[0])
{
- md->hitend = TRUE;
- if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ mb->hitend = TRUE;
+ if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL);
}
eptr++;
- ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++);
}
break;
case OP_ALLANY:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
eptr++;
- ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++);
}
break;
case OP_ANYBYTE:
- if (eptr > md->end_subject - min) RRETURN(MATCH_NOMATCH);
+ if (eptr > mb->end_subject - min) RRETURN(MATCH_NOMATCH);
eptr += min;
break;
case OP_ANYNL:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4435,7 +4525,7 @@ for (;;)
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
- if (eptr < md->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++;
+ if (eptr < mb->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++;
break;
case CHAR_LF:
@@ -4448,7 +4538,7 @@ for (;;)
case 0x2028:
case 0x2029:
#endif /* Not EBCDIC */
- if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+ if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) RRETURN(MATCH_NOMATCH);
break;
}
}
@@ -4457,7 +4547,7 @@ for (;;)
case OP_NOT_HSPACE:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4474,7 +4564,7 @@ for (;;)
case OP_HSPACE:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4491,7 +4581,7 @@ for (;;)
case OP_NOT_VSPACE:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4508,7 +4598,7 @@ for (;;)
case OP_VSPACE:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4525,13 +4615,13 @@ for (;;)
case OP_NOT_DIGIT:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINC(c, eptr);
- if (c < 128 && (md->ctypes[c] & ctype_digit) != 0)
+ if (c < 128 && (mb->ctypes[c] & ctype_digit) != 0)
RRETURN(MATCH_NOMATCH);
}
break;
@@ -4539,14 +4629,14 @@ for (;;)
case OP_DIGIT:
for (i = 1; i <= min; i++)
{
- pcre_uint32 cc;
- if (eptr >= md->end_subject)
+ uint32_t cc;
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
cc = UCHAR21(eptr);
- if (cc >= 128 || (md->ctypes[cc] & ctype_digit) == 0)
+ if (cc >= 128 || (mb->ctypes[cc] & ctype_digit) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
/* No need to skip more bytes - we know it's a 1-byte character */
@@ -4556,31 +4646,31 @@ for (;;)
case OP_NOT_WHITESPACE:
for (i = 1; i <= min; i++)
{
- pcre_uint32 cc;
- if (eptr >= md->end_subject)
+ uint32_t cc;
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
cc = UCHAR21(eptr);
- if (cc < 128 && (md->ctypes[cc] & ctype_space) != 0)
+ if (cc < 128 && (mb->ctypes[cc] & ctype_space) != 0)
RRETURN(MATCH_NOMATCH);
eptr++;
- ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++);
}
break;
case OP_WHITESPACE:
for (i = 1; i <= min; i++)
{
- pcre_uint32 cc;
- if (eptr >= md->end_subject)
+ uint32_t cc;
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
cc = UCHAR21(eptr);
- if (cc >= 128 || (md->ctypes[cc] & ctype_space) == 0)
+ if (cc >= 128 || (mb->ctypes[cc] & ctype_space) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
/* No need to skip more bytes - we know it's a 1-byte character */
@@ -4590,31 +4680,31 @@ for (;;)
case OP_NOT_WORDCHAR:
for (i = 1; i <= min; i++)
{
- pcre_uint32 cc;
- if (eptr >= md->end_subject)
+ uint32_t cc;
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
cc = UCHAR21(eptr);
- if (cc < 128 && (md->ctypes[cc] & ctype_word) != 0)
+ if (cc < 128 && (mb->ctypes[cc] & ctype_word) != 0)
RRETURN(MATCH_NOMATCH);
eptr++;
- ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++);
}
break;
case OP_WORDCHAR:
for (i = 1; i <= min; i++)
{
- pcre_uint32 cc;
- if (eptr >= md->end_subject)
+ uint32_t cc;
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
cc = UCHAR21(eptr);
- if (cc >= 128 || (md->ctypes[cc] & ctype_word) == 0)
+ if (cc >= 128 || (mb->ctypes[cc] & ctype_word) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
/* No need to skip more bytes - we know it's a 1-byte character */
@@ -4622,11 +4712,11 @@ for (;;)
break;
default:
- RRETURN(PCRE_ERROR_INTERNAL);
+ RRETURN(PCRE2_ERROR_INTERNAL);
} /* End switch(ctype) */
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
/* Code for the non-UTF-8 case for minimum matching of operators other
than OP_PROP and OP_NOTPROP. */
@@ -4636,27 +4726,27 @@ for (;;)
case OP_ANY:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH);
- if (md->partial != 0 &&
- eptr + 1 >= md->end_subject &&
+ if (mb->partial != 0 &&
+ eptr + 1 >= mb->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
*eptr == NLBLOCK->nl[0])
{
- md->hitend = TRUE;
- if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ mb->hitend = TRUE;
+ if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL);
}
eptr++;
}
break;
case OP_ALLANY:
- if (eptr > md->end_subject - min)
+ if (eptr > mb->end_subject - min)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4665,7 +4755,7 @@ for (;;)
break;
case OP_ANYBYTE:
- if (eptr > md->end_subject - min)
+ if (eptr > mb->end_subject - min)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4676,7 +4766,7 @@ for (;;)
case OP_ANYNL:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4686,7 +4776,7 @@ for (;;)
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
- if (eptr < md->end_subject && *eptr == CHAR_LF) eptr++;
+ if (eptr < mb->end_subject && *eptr == CHAR_LF) eptr++;
break;
case CHAR_LF:
@@ -4695,11 +4785,11 @@ for (;;)
case CHAR_VT:
case CHAR_FF:
case CHAR_NEL:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
case 0x2028:
case 0x2029:
#endif
- if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+ if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) RRETURN(MATCH_NOMATCH);
break;
}
}
@@ -4708,7 +4798,7 @@ for (;;)
case OP_NOT_HSPACE:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4717,7 +4807,7 @@ for (;;)
{
default: break;
HSPACE_BYTE_CASES:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
HSPACE_MULTIBYTE_CASES:
#endif
RRETURN(MATCH_NOMATCH);
@@ -4728,7 +4818,7 @@ for (;;)
case OP_HSPACE:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4737,7 +4827,7 @@ for (;;)
{
default: RRETURN(MATCH_NOMATCH);
HSPACE_BYTE_CASES:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
HSPACE_MULTIBYTE_CASES:
#endif
break;
@@ -4748,7 +4838,7 @@ for (;;)
case OP_NOT_VSPACE:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4756,7 +4846,7 @@ for (;;)
switch(*eptr++)
{
VSPACE_BYTE_CASES:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
VSPACE_MULTIBYTE_CASES:
#endif
RRETURN(MATCH_NOMATCH);
@@ -4768,7 +4858,7 @@ for (;;)
case OP_VSPACE:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4777,7 +4867,7 @@ for (;;)
{
default: RRETURN(MATCH_NOMATCH);
VSPACE_BYTE_CASES:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
VSPACE_MULTIBYTE_CASES:
#endif
break;
@@ -4788,12 +4878,12 @@ for (;;)
case OP_NOT_DIGIT:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0)
+ if (MAX_255(*eptr) && (mb->ctypes[*eptr] & ctype_digit) != 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
@@ -4802,12 +4892,12 @@ for (;;)
case OP_DIGIT:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0)
+ if (!MAX_255(*eptr) || (mb->ctypes[*eptr] & ctype_digit) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
@@ -4816,12 +4906,12 @@ for (;;)
case OP_NOT_WHITESPACE:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0)
+ if (MAX_255(*eptr) && (mb->ctypes[*eptr] & ctype_space) != 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
@@ -4830,12 +4920,12 @@ for (;;)
case OP_WHITESPACE:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0)
+ if (!MAX_255(*eptr) || (mb->ctypes[*eptr] & ctype_space) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
@@ -4844,12 +4934,12 @@ for (;;)
case OP_NOT_WORDCHAR:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0)
+ if (MAX_255(*eptr) && (mb->ctypes[*eptr] & ctype_word) != 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
@@ -4858,19 +4948,19 @@ for (;;)
case OP_WORDCHAR:
for (i = 1; i <= min; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
- if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0)
+ if (!MAX_255(*eptr) || (mb->ctypes[*eptr] & ctype_word) == 0)
RRETURN(MATCH_NOMATCH);
eptr++;
}
break;
default:
- RRETURN(PCRE_ERROR_INTERNAL);
+ RRETURN(PCRE2_ERROR_INTERNAL);
}
}
@@ -4884,7 +4974,7 @@ for (;;)
if (minimize)
{
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
if (prop_type >= 0)
{
switch(prop_type)
@@ -4892,10 +4982,10 @@ for (;;)
case PT_ANY:
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM36);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM36);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4909,10 +4999,10 @@ for (;;)
for (fi = min;; fi++)
{
int chartype;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM37);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM37);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4929,10 +5019,10 @@ for (;;)
case PT_GC:
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM38);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM38);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4946,10 +5036,10 @@ for (;;)
case PT_PC:
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM39);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM39);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4963,10 +5053,10 @@ for (;;)
case PT_SC:
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM40);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM40);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -4981,10 +5071,10 @@ for (;;)
for (fi = min;; fi++)
{
int category;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM59);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM59);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -5004,10 +5094,10 @@ for (;;)
case PT_PXSPACE: /* POSIX space */
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM61);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM61);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -5032,10 +5122,10 @@ for (;;)
for (fi = min;; fi++)
{
int category;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM62);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM62);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -5053,11 +5143,11 @@ for (;;)
case PT_CLIST:
for (fi = min;; fi++)
{
- const pcre_uint32 *cp;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM67);
+ const uint32_t *cp;
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM67);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -5077,10 +5167,10 @@ for (;;)
case PT_UCNC:
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM60);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM60);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -5095,7 +5185,7 @@ for (;;)
/* This should never occur */
default:
- RRETURN(PCRE_ERROR_INTERNAL);
+ RRETURN(PCRE2_ERROR_INTERNAL);
}
}
@@ -5106,10 +5196,10 @@ for (;;)
{
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM41);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM41);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -5119,7 +5209,7 @@ for (;;)
int lgb, rgb;
GETCHARINCTEST(c, eptr);
lgb = UCD_GRAPHBREAK(c);
- while (eptr < md->end_subject)
+ while (eptr < mb->end_subject)
{
int len = 1;
if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
@@ -5133,17 +5223,17 @@ for (;;)
}
}
else
-#endif /* SUPPORT_UCP */
+#endif /* SUPPORT_UNICODE */
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM42);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM42);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -5154,14 +5244,14 @@ for (;;)
switch(ctype)
{
case OP_ANY: /* This is the non-NL case */
- if (md->partial != 0 && /* Take care with CRLF partial */
- eptr >= md->end_subject &&
+ if (mb->partial != 0 && /* Take care with CRLF partial */
+ eptr >= mb->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
c == NLBLOCK->nl[0])
{
- md->hitend = TRUE;
- if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ mb->hitend = TRUE;
+ if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL);
}
break;
@@ -5174,7 +5264,7 @@ for (;;)
{
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
- if (eptr < md->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++;
+ if (eptr < mb->end_subject && UCHAR21(eptr) == CHAR_LF) eptr++;
break;
case CHAR_LF:
@@ -5187,7 +5277,7 @@ for (;;)
case 0x2028:
case 0x2029:
#endif /* Not EBCDIC */
- if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+ if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) RRETURN(MATCH_NOMATCH);
break;
}
break;
@@ -5225,37 +5315,37 @@ for (;;)
break;
case OP_NOT_DIGIT:
- if (c < 256 && (md->ctypes[c] & ctype_digit) != 0)
+ if (c < 256 && (mb->ctypes[c] & ctype_digit) != 0)
RRETURN(MATCH_NOMATCH);
break;
case OP_DIGIT:
- if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0)
+ if (c >= 256 || (mb->ctypes[c] & ctype_digit) == 0)
RRETURN(MATCH_NOMATCH);
break;
case OP_NOT_WHITESPACE:
- if (c < 256 && (md->ctypes[c] & ctype_space) != 0)
+ if (c < 256 && (mb->ctypes[c] & ctype_space) != 0)
RRETURN(MATCH_NOMATCH);
break;
case OP_WHITESPACE:
- if (c >= 256 || (md->ctypes[c] & ctype_space) == 0)
+ if (c >= 256 || (mb->ctypes[c] & ctype_space) == 0)
RRETURN(MATCH_NOMATCH);
break;
case OP_NOT_WORDCHAR:
- if (c < 256 && (md->ctypes[c] & ctype_word) != 0)
+ if (c < 256 && (mb->ctypes[c] & ctype_word) != 0)
RRETURN(MATCH_NOMATCH);
break;
case OP_WORDCHAR:
- if (c >= 256 || (md->ctypes[c] & ctype_word) == 0)
+ if (c >= 256 || (mb->ctypes[c] & ctype_word) == 0)
RRETURN(MATCH_NOMATCH);
break;
default:
- RRETURN(PCRE_ERROR_INTERNAL);
+ RRETURN(PCRE2_ERROR_INTERNAL);
}
}
}
@@ -5265,10 +5355,10 @@ for (;;)
{
for (fi = min;; fi++)
{
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM43);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM43);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (fi >= max) RRETURN(MATCH_NOMATCH);
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
@@ -5279,14 +5369,14 @@ for (;;)
switch(ctype)
{
case OP_ANY: /* This is the non-NL case */
- if (md->partial != 0 && /* Take care with CRLF partial */
- eptr >= md->end_subject &&
+ if (mb->partial != 0 && /* Take care with CRLF partial */
+ eptr >= mb->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
c == NLBLOCK->nl[0])
{
- md->hitend = TRUE;
- if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ mb->hitend = TRUE;
+ if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL);
}
break;
@@ -5299,7 +5389,7 @@ for (;;)
{
default: RRETURN(MATCH_NOMATCH);
case CHAR_CR:
- if (eptr < md->end_subject && *eptr == CHAR_LF) eptr++;
+ if (eptr < mb->end_subject && *eptr == CHAR_LF) eptr++;
break;
case CHAR_LF:
@@ -5308,11 +5398,11 @@ for (;;)
case CHAR_VT:
case CHAR_FF:
case CHAR_NEL:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
case 0x2028:
case 0x2029:
#endif
- if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH);
+ if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) RRETURN(MATCH_NOMATCH);
break;
}
break;
@@ -5322,7 +5412,7 @@ for (;;)
{
default: break;
HSPACE_BYTE_CASES:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
HSPACE_MULTIBYTE_CASES:
#endif
RRETURN(MATCH_NOMATCH);
@@ -5334,7 +5424,7 @@ for (;;)
{
default: RRETURN(MATCH_NOMATCH);
HSPACE_BYTE_CASES:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
HSPACE_MULTIBYTE_CASES:
#endif
break;
@@ -5346,7 +5436,7 @@ for (;;)
{
default: break;
VSPACE_BYTE_CASES:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
VSPACE_MULTIBYTE_CASES:
#endif
RRETURN(MATCH_NOMATCH);
@@ -5358,7 +5448,7 @@ for (;;)
{
default: RRETURN(MATCH_NOMATCH);
VSPACE_BYTE_CASES:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
VSPACE_MULTIBYTE_CASES:
#endif
break;
@@ -5366,31 +5456,31 @@ for (;;)
break;
case OP_NOT_DIGIT:
- if (MAX_255(c) && (md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH);
+ if (MAX_255(c) && (mb->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);
+ if (!MAX_255(c) || (mb->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);
+ if (MAX_255(c) && (mb->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);
+ if (!MAX_255(c) || (mb->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);
+ if (MAX_255(c) && (mb->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);
+ if (!MAX_255(c) || (mb->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH);
break;
default:
- RRETURN(PCRE_ERROR_INTERNAL);
+ RRETURN(PCRE2_ERROR_INTERNAL);
}
}
}
@@ -5405,7 +5495,7 @@ for (;;)
{
pp = eptr; /* Remember where we started */
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
if (prop_type >= 0)
{
switch(prop_type)
@@ -5414,7 +5504,7 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5430,7 +5520,7 @@ for (;;)
{
int chartype;
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5449,7 +5539,7 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5464,7 +5554,7 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5479,7 +5569,7 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5495,7 +5585,7 @@ for (;;)
{
int category;
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5517,7 +5607,7 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5545,7 +5635,7 @@ for (;;)
{
int category;
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5562,9 +5652,9 @@ for (;;)
case PT_CLIST:
for (i = min; i < max; i++)
{
- const pcre_uint32 *cp;
+ const uint32_t *cp;
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5587,7 +5677,7 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5602,16 +5692,20 @@ for (;;)
break;
default:
- RRETURN(PCRE_ERROR_INTERNAL);
+ RRETURN(PCRE2_ERROR_INTERNAL);
}
/* eptr is now past the end of the maximum run */
if (possessive) continue; /* No backtracking */
+
+ /* After \C in UTF mode, pp might be in the middle of a Unicode
+ character. Use <= pp to ensure backtracking doesn't go too far. */
+
for(;;)
{
if (eptr <= pp) goto TAIL_RECURSE;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM44);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM44);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
if (utf) BACKCHAR(eptr);
@@ -5625,7 +5719,7 @@ for (;;)
{
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5635,7 +5729,7 @@ for (;;)
int lgb, rgb;
GETCHARINCTEST(c, eptr);
lgb = UCD_GRAPHBREAK(c);
- while (eptr < md->end_subject)
+ while (eptr < mb->end_subject)
{
int len = 1;
if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); }
@@ -5660,10 +5754,10 @@ for (;;)
for(;;)
{
int lgb, rgb;
- PCRE_PUCHAR fptr;
+ PCRE2_SPTR fptr;
if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM45);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM45);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
/* Backtracking over an extended grapheme cluster involves inspecting
@@ -5696,9 +5790,9 @@ for (;;)
}
else
-#endif /* SUPPORT_UCP */
+#endif /* SUPPORT_UNICODE */
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
switch(ctype)
@@ -5706,23 +5800,23 @@ for (;;)
case OP_ANY:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (IS_NEWLINE(eptr)) break;
- if (md->partial != 0 && /* Take care with CRLF partial */
- eptr + 1 >= md->end_subject &&
+ if (mb->partial != 0 && /* Take care with CRLF partial */
+ eptr + 1 >= mb->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
UCHAR21(eptr) == NLBLOCK->nl[0])
{
- md->hitend = TRUE;
- if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ mb->hitend = TRUE;
+ if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL);
}
eptr++;
- ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++);
}
break;
@@ -5731,18 +5825,18 @@ for (;;)
{
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
eptr++;
- ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++);
+ ACROSSCHAR(eptr < mb->end_subject, *eptr, eptr++);
}
}
else
{
- eptr = md->end_subject; /* Unlimited UTF-8 repeat */
+ eptr = mb->end_subject; /* Unlimited UTF-8 repeat */
SCHECK_PARTIAL();
}
break;
@@ -5751,9 +5845,9 @@ for (;;)
case OP_ANYBYTE:
c = max - min;
- if (c > (unsigned int)(md->end_subject - eptr))
+ if (c > (uint32_t)(mb->end_subject - eptr))
{
- eptr = md->end_subject;
+ eptr = mb->end_subject;
SCHECK_PARTIAL();
}
else eptr += c;
@@ -5763,7 +5857,7 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5771,13 +5865,13 @@ for (;;)
GETCHARLEN(c, eptr, len);
if (c == CHAR_CR)
{
- if (++eptr >= md->end_subject) break;
+ if (++eptr >= mb->end_subject) break;
if (UCHAR21(eptr) == CHAR_LF) eptr++;
}
else
{
if (c != CHAR_LF &&
- (md->bsr_anycrlf ||
+ (mb->bsr_convention == PCRE2_BSR_ANYCRLF ||
(c != CHAR_VT && c != CHAR_FF && c != CHAR_NEL
#ifndef EBCDIC
&& c != 0x2028 && c != 0x2029
@@ -5795,7 +5889,7 @@ for (;;)
{
BOOL gotspace;
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5817,7 +5911,7 @@ for (;;)
{
BOOL gotspace;
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5837,13 +5931,13 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
- if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break;
+ if (c < 256 && (mb->ctypes[c] & ctype_digit) != 0) break;
eptr+= len;
}
break;
@@ -5852,13 +5946,13 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
- if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break;
+ if (c >= 256 ||(mb->ctypes[c] & ctype_digit) == 0) break;
eptr+= len;
}
break;
@@ -5867,13 +5961,13 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
- if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break;
+ if (c < 256 && (mb->ctypes[c] & ctype_space) != 0) break;
eptr+= len;
}
break;
@@ -5882,13 +5976,13 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
- if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break;
+ if (c >= 256 ||(mb->ctypes[c] & ctype_space) == 0) break;
eptr+= len;
}
break;
@@ -5897,13 +5991,13 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
- if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break;
+ if (c < 256 && (mb->ctypes[c] & ctype_word) != 0) break;
eptr+= len;
}
break;
@@ -5912,26 +6006,30 @@ for (;;)
for (i = min; i < max; i++)
{
int len = 1;
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
GETCHARLEN(c, eptr, len);
- if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break;
+ if (c >= 256 || (mb->ctypes[c] & ctype_word) == 0) break;
eptr+= len;
}
break;
default:
- RRETURN(PCRE_ERROR_INTERNAL);
+ RRETURN(PCRE2_ERROR_INTERNAL);
}
if (possessive) continue; /* No backtracking */
+
+ /* After \C in UTF mode, pp might be in the middle of a Unicode
+ character. Use <= pp to ensure backtracking doesn't go too far. */
+
for(;;)
{
if (eptr <= pp) goto TAIL_RECURSE;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM46);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM46);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
BACKCHAR(eptr);
@@ -5940,7 +6038,7 @@ for (;;)
}
}
else
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
/* Not UTF mode */
{
switch(ctype)
@@ -5948,20 +6046,20 @@ for (;;)
case OP_ANY:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
if (IS_NEWLINE(eptr)) break;
- if (md->partial != 0 && /* Take care with CRLF partial */
- eptr + 1 >= md->end_subject &&
+ if (mb->partial != 0 && /* Take care with CRLF partial */
+ eptr + 1 >= mb->end_subject &&
NLBLOCK->nltype == NLTYPE_FIXED &&
NLBLOCK->nllen == 2 &&
*eptr == NLBLOCK->nl[0])
{
- md->hitend = TRUE;
- if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL);
+ mb->hitend = TRUE;
+ if (mb->partial > 1) RRETURN(PCRE2_ERROR_PARTIAL);
}
eptr++;
}
@@ -5970,9 +6068,9 @@ for (;;)
case OP_ALLANY:
case OP_ANYBYTE:
c = max - min;
- if (c > (unsigned int)(md->end_subject - eptr))
+ if (c > (uint32_t)(mb->end_subject - eptr))
{
- eptr = md->end_subject;
+ eptr = mb->end_subject;
SCHECK_PARTIAL();
}
else eptr += c;
@@ -5981,7 +6079,7 @@ for (;;)
case OP_ANYNL:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -5989,14 +6087,14 @@ for (;;)
c = *eptr;
if (c == CHAR_CR)
{
- if (++eptr >= md->end_subject) break;
+ if (++eptr >= mb->end_subject) break;
if (*eptr == CHAR_LF) eptr++;
}
else
{
- if (c != CHAR_LF && (md->bsr_anycrlf ||
+ if (c != CHAR_LF && (mb->bsr_convention == PCRE2_BSR_ANYCRLF ||
(c != CHAR_VT && c != CHAR_FF && c != CHAR_NEL
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
&& c != 0x2028 && c != 0x2029
#endif
))) break;
@@ -6008,7 +6106,7 @@ for (;;)
case OP_NOT_HSPACE:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -6017,7 +6115,7 @@ for (;;)
{
default: eptr++; break;
HSPACE_BYTE_CASES:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
HSPACE_MULTIBYTE_CASES:
#endif
goto ENDLOOP00;
@@ -6029,7 +6127,7 @@ for (;;)
case OP_HSPACE:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -6038,7 +6136,7 @@ for (;;)
{
default: goto ENDLOOP01;
HSPACE_BYTE_CASES:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
HSPACE_MULTIBYTE_CASES:
#endif
eptr++; break;
@@ -6050,7 +6148,7 @@ for (;;)
case OP_NOT_VSPACE:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -6059,7 +6157,7 @@ for (;;)
{
default: eptr++; break;
VSPACE_BYTE_CASES:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
VSPACE_MULTIBYTE_CASES:
#endif
goto ENDLOOP02;
@@ -6071,7 +6169,7 @@ for (;;)
case OP_VSPACE:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
@@ -6080,7 +6178,7 @@ for (;;)
{
default: goto ENDLOOP03;
VSPACE_BYTE_CASES:
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#if PCRE2_CODE_UNIT_WIDTH != 8
VSPACE_MULTIBYTE_CASES:
#endif
eptr++; break;
@@ -6092,12 +6190,12 @@ for (;;)
case OP_NOT_DIGIT:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
- if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0) break;
+ if (MAX_255(*eptr) && (mb->ctypes[*eptr] & ctype_digit) != 0) break;
eptr++;
}
break;
@@ -6105,12 +6203,12 @@ for (;;)
case OP_DIGIT:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
- if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0) break;
+ if (!MAX_255(*eptr) || (mb->ctypes[*eptr] & ctype_digit) == 0) break;
eptr++;
}
break;
@@ -6118,12 +6216,12 @@ for (;;)
case OP_NOT_WHITESPACE:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
- if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0) break;
+ if (MAX_255(*eptr) && (mb->ctypes[*eptr] & ctype_space) != 0) break;
eptr++;
}
break;
@@ -6131,12 +6229,12 @@ for (;;)
case OP_WHITESPACE:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
- if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0) break;
+ if (!MAX_255(*eptr) || (mb->ctypes[*eptr] & ctype_space) == 0) break;
eptr++;
}
break;
@@ -6144,12 +6242,12 @@ for (;;)
case OP_NOT_WORDCHAR:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
- if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0) break;
+ if (MAX_255(*eptr) && (mb->ctypes[*eptr] & ctype_word) != 0) break;
eptr++;
}
break;
@@ -6157,25 +6255,25 @@ for (;;)
case OP_WORDCHAR:
for (i = min; i < max; i++)
{
- if (eptr >= md->end_subject)
+ if (eptr >= mb->end_subject)
{
SCHECK_PARTIAL();
break;
}
- if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0) break;
+ if (!MAX_255(*eptr) || (mb->ctypes[*eptr] & ctype_word) == 0) break;
eptr++;
}
break;
default:
- RRETURN(PCRE_ERROR_INTERNAL);
+ RRETURN(PCRE2_ERROR_INTERNAL);
}
if (possessive) continue; /* No backtracking */
for (;;)
{
if (eptr == pp) goto TAIL_RECURSE;
- RMATCH(eptr, ecode, offset_top, md, eptrb, RM47);
+ RMATCH(eptr, ecode, offset_top, mb, eptrb, RM47);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
if (ctype == OP_ANYNL && eptr > pp && *eptr == CHAR_LF &&
@@ -6190,8 +6288,7 @@ for (;;)
something seriously wrong in the code above or the OP_xxx definitions. */
default:
- DPRINTF(("Unknown opcode %d\n", *ecode));
- RRETURN(PCRE_ERROR_UNKNOWN_OPCODE);
+ RRETURN(PCRE2_ERROR_INTERNAL);
}
/* Do not stick any code in here without much thought; it is assumed
@@ -6206,7 +6303,7 @@ for (;;)
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
+#ifdef HEAP_MATCH_RECURSE
#define LBL(val) case val: goto L_RM##val;
HEAP_RETURN:
switch (frame->Xwhere)
@@ -6216,25 +6313,22 @@ switch (frame->Xwhere)
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(65) LBL(66) LBL(68)
+#ifdef SUPPORT_WIDE_CHARS
LBL(20) LBL(21)
#endif
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
LBL(16) LBL(18)
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) LBL(67)
-#endif /* SUPPORT_UCP */
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
default:
- DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere));
- return PCRE_ERROR_INTERNAL;
+ return PCRE2_ERROR_INTERNAL;
}
#undef LBL
-#endif /* NO_RECURSE */
+#endif /* HEAP_MATCH_RECURSE */
}
@@ -6244,7 +6338,7 @@ switch (frame->Xwhere)
Undefine all the macros that were defined above to handle this. */
-#ifdef NO_RECURSE
+#ifdef HEAP_MATCH_RECURSE
#undef eptr
#undef ecode
#undef mstart
@@ -6255,7 +6349,7 @@ Undefine all the macros that were defined above to handle this. */
#undef callpat
#undef charptr
#undef data
-#undef next
+#undef next_ecode
#undef pp
#undef prev
#undef saved_eptr
@@ -6277,11 +6371,9 @@ Undefine all the macros that were defined above to handle this. */
#undef save_offset1
#undef save_offset2
#undef save_offset3
-#undef stacksave
#undef newptrb
-
-#endif
+#endif /* HEAP_MATCH_RECURSE */
/* These two are defined as macros in both cases */
@@ -6292,7 +6384,7 @@ Undefine all the macros that were defined above to handle this. */
***************************************************************************/
-#ifdef NO_RECURSE
+#ifdef HEAP_MATCH_RECURSE
/*************************************************
* Release allocated heap frames *
*************************************************/
@@ -6300,378 +6392,336 @@ Undefine all the macros that were defined above to handle this. */
/* This function releases all the allocated frames. The base frame is on the
machine stack, and so must not be freed.
-Argument: the address of the base frame
+Argument:
+ frame_base the address of the base frame
+ mb the match block
+
Returns: nothing
*/
static void
-release_match_heapframes (heapframe *frame_base)
+release_match_heapframes (heapframe *frame_base, match_block *mb)
{
heapframe *nextframe = frame_base->Xnextframe;
while (nextframe != NULL)
{
heapframe *oldframe = nextframe;
nextframe = nextframe->Xnextframe;
- (PUBL(stack_free))(oldframe);
+ mb->stack_memctl.free(oldframe, mb->stack_memctl.memory_data);
}
}
-#endif
+#endif /* HEAP_MATCH_RECURSE */
+
/*************************************************
-* Execute a Regular Expression *
+* Match a Regular Expression *
*************************************************/
-/* This function applies a compiled re to a subject string and picks out
+/* This function applies a compiled pattern to a subject string and picks out
portions of the string if it matches. Two elements in the vector are set for
each substring: the offsets to the start and end of the substring.
Arguments:
- argument_re points to the compiled expression
- extra_data points to extra data or is NULL
+ code points to the compiled expression
subject points to the subject string
length length of subject string (may contain binary zeros)
start_offset where to start in the subject string
options option bits
- 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
+ match_data points to a match_data block
+ mcontext points a PCRE2 context
+
+Returns: > 0 => success; value is the number of ovector pairs filled
+ = 0 => success, but ovector is not big enough
+ -1 => failed to match (PCRE2_ERROR_NOMATCH)
+ -2 => partial match (PCRE2_ERROR_PARTIAL)
+ < -2 => some kind of unexpected problem
*/
-#if defined 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)
-#elif defined COMPILE_PCRE16
-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)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
-pcre32_exec(const pcre32 *argument_re, const pcre32_extra *extra_data,
- PCRE_SPTR32 subject, int length, int start_offset, int options, int *offsets,
- int offsetcount)
-#endif
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
+ PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext)
{
-int rc, ocount, arg_offset_max;
-int newline;
-BOOL using_temporary_offsets = FALSE;
+int rc;
+int ocount;
+
+const uint8_t *start_bits = NULL;
+
+const pcre2_real_code *re = (const pcre2_real_code *)code;
+
BOOL anchored;
-BOOL startline;
BOOL firstline;
+BOOL has_first_cu = FALSE;
+BOOL has_req_cu = FALSE;
+BOOL startline;
+BOOL using_temporary_offsets = FALSE;
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 match_partial = NULL;
-PCRE_PUCHAR req_char_ptr = start_match - 1;
-
-const pcre_study_data *study;
-const REAL_PCRE *re = (const REAL_PCRE *)argument_re;
-
-#ifdef NO_RECURSE
+
+PCRE2_UCHAR first_cu = 0;
+PCRE2_UCHAR first_cu2 = 0;
+PCRE2_UCHAR req_cu = 0;
+PCRE2_UCHAR req_cu2 = 0;
+
+PCRE2_SPTR bumpalong_limit;
+PCRE2_SPTR end_subject;
+PCRE2_SPTR start_match = subject + start_offset;
+PCRE2_SPTR req_cu_ptr = start_match - 1;
+PCRE2_SPTR start_partial = NULL;
+PCRE2_SPTR match_partial = NULL;
+
+/* We need to have mb pointing to a match block, because the IS_NEWLINE macro
+is used below, and it expects NLBLOCK to be defined as a pointer. */
+
+match_block actual_match_block;
+match_block *mb = &actual_match_block;
+
+#ifdef HEAP_MATCH_RECURSE
heapframe frame_zero;
frame_zero.Xprevframe = NULL; /* Marks the top level */
frame_zero.Xnextframe = NULL; /* None are allocated yet */
-md->match_frames_base = &frame_zero;
+mb->match_frames_base = &frame_zero;
#endif
-/* Check for the special magic call that measures the size of the stack used
-per recursive call of match(). Without the funny casting for sizeof, a Windows
-compiler gave this error: "unary minus operator applied to unsigned type,
-result still unsigned". Hopefully the cast fixes that. */
+/* A length equal to PCRE2_ZERO_TERMINATED implies a zero-terminated
+subject string. */
-if (re == NULL && extra_data == NULL && subject == NULL && length == -999 &&
- start_offset == -999)
-#ifdef NO_RECURSE
- return -((int)sizeof(heapframe));
-#else
- return match(NULL, NULL, NULL, 0, NULL, NULL, 0);
-#endif
+if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject);
+end_subject = subject + length;
/* 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 (length < 0) return PCRE_ERROR_BADLENGTH;
-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)
+if ((options & ~PUBLIC_MATCH_OPTIONS) != 0) return PCRE2_ERROR_BADOPTION;
+if (code == NULL || subject == NULL || match_data == NULL)
+ return PCRE2_ERROR_NULL;
+if (start_offset > length) return PCRE2_ERROR_BADOFFSET;
+
+/* Check that the first field in the block is the magic number. */
+
+if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;
+
+/* Check the code unit width. */
+
+if ((re->flags & PCRE2_MODE_MASK) != PCRE2_CODE_UNIT_WIDTH/8)
+ return PCRE2_ERROR_BADMODE;
+
+/* PCRE2_NOTEMPTY and PCRE2_NOTEMPTY_ATSTART are match-time flags in the
+options variable for this function. Users of PCRE2 who are not calling the
+function directly would like to have a way of setting these flags, in the same
+way that they can set pcre2_compile() flags like PCRE2_NO_AUTOPOSSESS with
+constructions like (*NO_AUTOPOSSESS). To enable this, (*NOTEMPTY) and
+(*NOTEMPTY_ATSTART) set bits in the pattern's "flag" function which can now be
+transferred to the options for this function. The bits are guaranteed to be
+adjacent, but do not have the same values. This bit of Boolean trickery assumes
+that the match-time bits are not more significant than the flag bits. If by
+accident this is not the case, a compile-time division by zero error will
+occur. */
+
+#define FF (PCRE2_NOTEMPTY_SET|PCRE2_NE_ATST_SET)
+#define OO (PCRE2_NOTEMPTY|PCRE2_NOTEMPTY_ATSTART)
+options |= (re->flags & FF) / ((FF & (~FF+1)) / (OO & (~OO+1)));
+#undef FF
+#undef OO
+
+/* A NULL match context means "use a default context" */
+
+if (mcontext == NULL)
+ mcontext = (pcre2_match_context *)(&PRIV(default_match_context));
+
+/* These two settings are used in the code for checking a UTF string that
+follows immediately afterwards. Other values in the mb block are used only
+during interpretive pcre_match() processing, not when the JIT support is in
+use, so they are set up later. */
+
+utf = (re->overall_options & PCRE2_UTF) != 0;
+mb->partial = ((options & PCRE2_PARTIAL_HARD) != 0)? 2 :
+ ((options & PCRE2_PARTIAL_SOFT) != 0)? 1 : 0;
+
+/* Check a UTF string for validity if required. For 8-bit and 16-bit strings,
+we must also check that a starting offset does not point into the middle of a
+multiunit character. We check only the portion of the subject that is going to
+be inspected during matching - from the offset minus the maximum back reference
+to the given length. This saves time when a small part of a large subject is
+being matched by the use of a starting offset. Note that the maximum lookbehind
+is a number of characters, not code units. */
+
+#ifdef SUPPORT_UNICODE
+if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)
{
- int erroroffset;
- int errorcode = PRIV(valid_utf)((PCRE_PUCHAR)subject, length, &erroroffset);
- if (errorcode != 0)
+ PCRE2_SPTR check_subject = start_match; /* start_match includes offset */
+
+ if (start_offset > 0)
{
- if (offsetcount >= 2)
+#if PCRE2_CODE_UNIT_WIDTH != 32
+ unsigned int i;
+ if (start_match < end_subject && NOT_FIRSTCU(*start_match))
+ return PCRE2_ERROR_BADUTFOFFSET;
+ for (i = re->max_lookbehind; i > 0 && check_subject > subject; i--)
{
- offsets[0] = erroroffset;
- offsets[1] = errorcode;
+ check_subject--;
+ while (check_subject > subject &&
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ (*check_subject & 0xc0) == 0x80)
+#else /* 16-bit */
+ (*check_subject & 0xfc00) == 0xdc00)
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
+ check_subject--;
}
-#if defined COMPILE_PCRE8
- return (errorcode <= PCRE_UTF8_ERR5 && md->partial > 1)?
- PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8;
-#elif defined COMPILE_PCRE16
- return (errorcode <= PCRE_UTF16_ERR1 && md->partial > 1)?
- PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16;
-#elif defined COMPILE_PCRE32
- return PCRE_ERROR_BADUTF32;
-#endif
+#else
+ /* In the 32-bit library, one code unit equals one character. However,
+ we cannot just subtract the lookbehind and then compare pointers, because
+ a very large lookbehind could create an invalid pointer. */
+
+ if (start_offset >= re->max_lookbehind)
+ check_subject -= re->max_lookbehind;
+ else
+ check_subject = subject;
+#endif /* PCRE2_CODE_UNIT_WIDTH != 32 */
+ }
+
+ /* Validate the relevant portion of the subject. After an error, adjust the
+ offset to be an absolute offset in the whole string. */
+
+ match_data->rc = PRIV(valid_utf)(check_subject,
+ length - (check_subject - subject), &(match_data->startchar));
+ if (match_data->rc != 0)
+ {
+ match_data->startchar += check_subject - subject;
+ return match_data->rc;
}
-#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
- /* 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
}
-#endif
+#endif /* SUPPORT_UNICODE */
+
+/* It is an error to set an offset limit without setting the flag at compile
+time. */
+
+if (mcontext->offset_limit != PCRE2_UNSET &&
+ (re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0)
+ return PCRE2_ERROR_BADOFFSETLIMIT;
/* 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. */
+an unsupported option is set or if JIT returns BADOPTION (which means that the
+selected normal or partial matching mode was not compiled). */
#ifdef SUPPORT_JIT
-if (extra_data != NULL
- && (extra_data->flags & (PCRE_EXTRA_EXECUTABLE_JIT |
- PCRE_EXTRA_TABLES)) == PCRE_EXTRA_EXECUTABLE_JIT
- && extra_data->executable_jit != NULL
- && (options & ~PUBLIC_JIT_EXEC_OPTIONS) == 0)
+if (re->executable_jit != NULL && (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0)
{
- rc = PRIV(jit_exec)(extra_data, (const pcre_uchar *)subject, length,
- start_offset, options, offsets, offsetcount);
-
- /* PCRE_ERROR_NULL means that the selected normal or partial matching
- mode is not compiled. In this case we simply fallback to interpreter. */
-
- if (rc != PCRE_ERROR_JIT_BADOPTION) return rc;
+ rc = pcre2_jit_match(code, subject, length, start_offset, options,
+ match_data, mcontext);
+ if (rc != PCRE2_ERROR_JIT_BADOPTION) return rc;
}
#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;
-
-/* The two limit values override the defaults, whatever their value. */
+/* Carry on with non-JIT matching. */
-if (extra_data != NULL)
- {
- unsigned long 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;
- }
-
-/* Limits in the regex override only if they are smaller. */
-
-if ((re->flags & PCRE_MLSET) != 0 && re->limit_match < md->match_limit)
- md->match_limit = re->limit_match;
-
-if ((re->flags & PCRE_RLSET) != 0 &&
- re->limit_recursion < md->match_limit_recursion)
- md->match_limit_recursion = re->limit_recursion;
-
-/* 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);
+anchored = ((re->overall_options | options) & PCRE2_ANCHORED) != 0;
+firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0;
+startline = (re->flags & PCRE2_STARTLINE) != 0;
+bumpalong_limit = (mcontext->offset_limit == PCRE2_UNSET)?
+ end_subject : subject + mcontext->offset_limit;
-/* Set up other data */
+/* Fill in the fields in the match block. */
-anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
-startline = (re->flags & PCRE_STARTLINE) != 0;
-firstline = (re->options & PCRE_FIRSTLINE) != 0;
+mb->callout = mcontext->callout;
+mb->callout_data = mcontext->callout_data;
+mb->memctl = mcontext->memctl;
+#ifdef HEAP_MATCH_RECURSE
+mb->stack_memctl = mcontext->stack_memctl;
+#endif
-/* The code starts after the real_pcre block and the capture name table. */
+mb->start_subject = subject;
+mb->start_offset = start_offset;
+mb->end_subject = end_subject;
+mb->hasthen = (re->flags & PCRE2_HASTHEN) != 0;
-md->start_code = (const pcre_uchar *)re + re->name_table_offset +
- re->name_count * re->name_entry_size;
+mb->moptions = options; /* Match options */
+mb->poptions = re->overall_options; /* Pattern options */
-md->start_subject = (PCRE_PUCHAR)subject;
-md->start_offset = start_offset;
-md->end_subject = md->start_subject + length;
-end_subject = md->end_subject;
+mb->ignore_skip_arg = 0;
+mb->mark = mb->nomatch_mark = NULL; /* In case never set */
+mb->recursive = NULL; /* No recursion at top level */
+mb->ovecsave_chain = NULL; /* No ovecsave blocks yet */
+mb->hitend = FALSE;
-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 = 0;
+/* The name table is needed for finding all the numbers associated with a
+given name, for condition testing. The code follows the name table. */
-/* Some options are unpacked into BOOL variables in the hope that testing
-them will be faster than individual option bits. */
+mb->name_table = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code));
+mb->name_count = re->name_count;
+mb->name_entry_size = re->name_entry_size;
+mb->start_code = mb->name_table + re->name_count * re->name_entry_size;
-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;
+/* Limits set in the pattern override the match context only if they are
+smaller. */
-md->hitend = FALSE;
-md->mark = md->nomatch_mark = NULL; /* In case never set */
+mb->match_limit = (mcontext->match_limit < re->limit_match)?
+ mcontext->match_limit : re->limit_match;
+mb->match_limit_recursion = (mcontext->recursion_limit < re->limit_recursion)?
+ mcontext->recursion_limit : re->limit_recursion;
-md->recursive = NULL; /* No recursion at top level */
-md->hasthen = (re->flags & PCRE_HASTHEN) != 0;
+/* Pointers to the individual character tables */
-md->lcc = tables + lcc_offset;
-md->fcc = tables + fcc_offset;
-md->ctypes = tables + ctypes_offset;
+mb->lcc = re->tables + lcc_offset;
+mb->fcc = re->tables + fcc_offset;
+mb->ctypes = re->tables + ctypes_offset;
-/* Handle different \R options. */
+/* Process the \R and newline settings. */
-switch (options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE))
+mb->bsr_convention = re->bsr_convention;
+mb->nltype = NLTYPE_FIXED;
+switch(re->newline_convention)
{
- 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
+ case PCRE2_NEWLINE_CR:
+ mb->nllen = 1;
+ mb->nl[0] = CHAR_CR;
break;
- case PCRE_BSR_ANYCRLF:
- md->bsr_anycrlf = TRUE;
+ case PCRE2_NEWLINE_LF:
+ mb->nllen = 1;
+ mb->nl[0] = CHAR_NL;
break;
- case PCRE_BSR_UNICODE:
- md->bsr_anycrlf = FALSE;
+ case PCRE2_NEWLINE_CRLF:
+ mb->nllen = 2;
+ mb->nl[0] = CHAR_CR;
+ mb->nl[1] = CHAR_NL;
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. */
+ case PCRE2_NEWLINE_ANY:
+ mb->nltype = NLTYPE_ANY;
+ break;
-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;
- }
+ case PCRE2_NEWLINE_ANYCRLF:
+ mb->nltype = NLTYPE_ANYCRLF;
+ break;
-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;
- }
+ default: return PCRE2_ERROR_INTERNAL;
}
-/* 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. */
+hold, we get a temporary chunk of memory to use during the matching. Otherwise,
+we can use the vector supplied. The size of the ovector is three times the
+value in the oveccount field. Two-thirds of it is pairs for storing matching
+offsets, and the top third is working space. */
-ocount = offsetcount - (offsetcount % 3);
-arg_offset_max = (2*ocount)/3;
-
-if (re->top_backref > 0 && re->top_backref >= ocount/3)
+if (re->top_backref >= match_data->oveccount)
{
ocount = re->top_backref * 3 + 3;
- md->offset_vector = (int *)(PUBL(malloc))(ocount * sizeof(int));
- if (md->offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
+ mb->ovector = (PCRE2_SIZE *)(mb->memctl.malloc(ocount * sizeof(PCRE2_SIZE),
+ mb->memctl.memory_data));
+ if (mb->ovector == NULL) return PCRE2_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->capture_last = 0;
+else
+ {
+ ocount = 3 * match_data->oveccount;
+ mb->ovector = match_data->ovector;
+ }
+
+mb->offset_end = ocount;
+mb->offset_max = (2*ocount)/3;
/* 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
@@ -6679,56 +6729,52 @@ 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)
+if (ocount > 0)
{
- 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;
- if (offsetcount > 0) md->offset_vector[0] = -1;
- if (offsetcount > 1) md->offset_vector[1] = -1;
+ register PCRE2_SIZE *iptr = mb->ovector + ocount;
+ register PCRE2_SIZE *iend = iptr - re->top_bracket;
+ if (iend < mb->ovector + 2) iend = mb->ovector + 2;
+ while (--iptr >= iend) *iptr = PCRE2_UNSET;
+ mb->ovector[0] = mb->ovector[1] = PCRE2_UNSET;
}
-/* 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. */
+/* Set up the first code unit to match, if available. The first_codeunit 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 code unit may
+be unset for an unanchored pattern, of course. If there's no first code unit
+there may be a bitmap of possible first characters. */
if (!anchored)
{
- if ((re->flags & PCRE_FIRSTSET) != 0)
+ if ((re->flags & PCRE2_FIRSTSET) != 0)
{
- has_first_char = TRUE;
- first_char = first_char2 = (pcre_uchar)(re->first_char);
- if ((re->flags & PCRE_FCH_CASELESS) != 0)
+ has_first_cu = TRUE;
+ first_cu = first_cu2 = (PCRE2_UCHAR)(re->first_codeunit);
+ if ((re->flags & PCRE2_FIRSTCASELESS) != 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);
+ first_cu2 = TABLE_GET(first_cu, mb->fcc, first_cu);
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
+ if (utf && first_cu > 127) first_cu2 = UCD_OTHERCASE(first_cu);
#endif
}
}
else
- if (!startline && study != NULL &&
- (study->flags & PCRE_STUDY_MAPPED) != 0)
- start_bits = study->start_bits;
+ if (!startline && (re->flags & PCRE2_FIRSTMAPSET) != 0)
+ start_bits = re->start_bitmap;
}
/* For anchored or unanchored matches, there may be a "last known required
character" set. */
-if ((re->flags & PCRE_REQCHSET) != 0)
+if ((re->flags & PCRE2_LASTSET) != 0)
{
- has_req_char = TRUE;
- req_char = req_char2 = (pcre_uchar)(re->req_char);
- if ((re->flags & PCRE_RCH_CASELESS) != 0)
+ has_req_cu = TRUE;
+ req_cu = req_cu2 = (PCRE2_UCHAR)(re->last_codeunit);
+ if ((re->flags & PCRE2_LASTCASELESS) != 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);
+ req_cu2 = TABLE_GET(req_cu, mb->fcc, req_cu);
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
+ if (utf && req_cu > 127) req_cu2 = UCD_OTHERCASE(req_cu);
#endif
}
}
@@ -6741,63 +6787,73 @@ the loop runs just once. */
for(;;)
{
- PCRE_PUCHAR save_end_subject = end_subject;
- PCRE_PUCHAR new_start_match;
+ PCRE2_SPTR new_start_match;
+ mb->capture_last = 0;
+
+ /* ----------------- Start of match optimizations ---------------- */
- /* 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. */
+ /* There are some optimizations that avoid running the match if a known
+ starting point is not found, or if a known later code unit is not present.
+ However, there is an option (settable at compile time) that disables these,
+ for testing and for ensuring that all callouts do actually occur. */
- if (firstline)
+ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
{
- PCRE_PUCHAR t = start_match;
-#ifdef SUPPORT_UTF
- if (utf)
+ PCRE2_SPTR save_end_subject = end_subject;
+
+ /* 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 the optimization scans at a newline. If the match fails at the
+ newline, later code breaks this loop. */
+
+ if (firstline)
{
- while (t < md->end_subject && !IS_NEWLINE(t))
+ PCRE2_SPTR t = start_match;
+#ifdef SUPPORT_UNICODE
+ if (utf)
{
- t++;
- ACROSSCHAR(t < end_subject, *t, t++);
+ while (t < mb->end_subject && !IS_NEWLINE(t))
+ {
+ t++;
+ ACROSSCHAR(t < end_subject, *t, t++);
+ }
}
- }
- else
+ 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. */
+ while (t < mb->end_subject && !IS_NEWLINE(t)) t++;
+ end_subject = t;
+ }
- if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0)
- {
- /* Advance to a unique first char if there is one. */
+ /* Advance to a unique first code unit if there is one. In 8-bit mode, the
+ use of memchr() gives a big speed up. */
- if (has_first_char)
+ if (has_first_cu)
{
- pcre_uchar smc;
-
- if (first_char != first_char2)
+ PCRE2_UCHAR smc;
+ if (first_cu != first_cu2)
while (start_match < end_subject &&
- (smc = UCHAR21TEST(start_match)) != first_char && smc != first_char2)
+ (smc = UCHAR21TEST(start_match)) != first_cu && smc != first_cu2)
start_match++;
else
- while (start_match < end_subject && UCHAR21TEST(start_match) != first_char)
+ {
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ while (start_match < end_subject && UCHAR21TEST(start_match) != first_cu)
start_match++;
+#else
+ start_match = memchr(start_match, first_cu, end_subject - start_match);
+ if (start_match == NULL) start_match = end_subject;
+#endif
+ }
}
/* Or to just after a linebreak for a multiline match */
else if (startline)
{
- if (start_match > md->start_subject + start_offset)
+ if (start_match > mb->start_subject + start_offset)
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
while (start_match < end_subject && !WAS_NEWLINE(start_match))
@@ -6812,131 +6868,137 @@ for(;;)
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 we have just passed a CR and the newline option is ANY or
+ ANYCRLF, and we are now at a LF, advance the match position by one more
+ code unit. */
if (start_match[-1] == CHAR_CR &&
- (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) &&
+ (mb->nltype == NLTYPE_ANY || mb->nltype == NLTYPE_ANYCRLF) &&
start_match < end_subject &&
UCHAR21TEST(start_match) == CHAR_NL)
start_match++;
}
}
- /* Or to a non-unique first byte after study */
+ /* Or to a non-unique first code unit if any have been identified. The
+ bitmap contains only 256 bits. When code units are 16 or 32 bits wide, all
+ code units greater than 254 set the 255 bit. */
else if (start_bits != NULL)
{
while (start_match < end_subject)
{
- register pcre_uint32 c = UCHAR21TEST(start_match);
-#ifndef COMPILE_PCRE8
+ register uint32_t c = UCHAR21TEST(start_match);
+#if PCRE2_CODE_UNIT_WIDTH != 8
if (c > 255) c = 255;
#endif
if ((start_bits[c/8] & (1 << (c&7))) != 0) break;
start_match++;
}
}
- } /* Starting optimizations */
- /* Restore fudged end_subject */
+ /* Restore fudged end_subject */
- end_subject = save_end_subject;
+ end_subject = save_end_subject;
- /* The following two optimizations are disabled for partial matching or if
- disabling is explicitly requested. */
+ /* The following two optimizations are disabled for partial matching. */
- 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)
+ if (!mb->partial)
{
- 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);
+ /* The minimum matching length is a lower bound; no actual string of that
+ length may actually match the pattern. Although the value is, strictly,
+ in characters, we treat it as code units to avoid spending too much time
+ in this optimization. */
- /* We don't need to repeat the search if we haven't yet reached the
- place we found it at last time. */
+ if (end_subject - start_match < re->minlength)
+ {
+ rc = MATCH_NOMATCH;
+ break;
+ }
- if (p > req_char_ptr)
+ /* If req_cu is set, we know that that code unit must appear in the
+ subject for the match to succeed. If the first code unit is set, req_cu
+ must be later in the subject; otherwise the test starts at the match
+ point. This optimization can save a huge amount of backtracking in
+ patterns with nested unlimited repeats that aren't going to match.
+ Writing separate code for cased/caseless versions makes it go faster, as
+ does using an autoincrement and backing off on a match.
+
+ 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_cu && end_subject - start_match < REQ_CU_MAX)
{
- if (req_char != req_char2)
+ register PCRE2_SPTR p = start_match + (has_first_cu? 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_cu_ptr)
{
- while (p < end_subject)
+ if (req_cu != req_cu2)
{
- register pcre_uint32 pp = UCHAR21INCTEST(p);
- if (pp == req_char || pp == req_char2) { p--; break; }
+ while (p < end_subject)
+ {
+ register uint32_t pp = UCHAR21INCTEST(p);
+ if (pp == req_cu || pp == req_cu2) { p--; break; }
+ }
}
- }
- else
- {
- while (p < end_subject)
+ else
{
- if (UCHAR21INCTEST(p) == req_char) { p--; break; }
+ while (p < end_subject)
+ {
+ if (UCHAR21INCTEST(p) == req_cu) { p--; break; }
+ }
}
- }
- /* If we can't find the required character, break the matching loop,
- forcing a match failure. */
+ /* If we can't find the required code unit, break the matching loop,
+ forcing a match failure. */
- if (p >= end_subject)
- {
- rc = MATCH_NOMATCH;
- break;
- }
+ 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. */
+ /* If we have found the required code unit, save the point where we
+ found it, so that we don't search again next time round the loop if
+ the start hasn't passed this code unit yet. */
- req_char_ptr = p;
+ req_cu_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
+ /* ------------ End of start of match optimizations ------------ */
+
+ /* Give no match if we have passed the bumpalong limit. */
+
+ if (start_match > bumpalong_limit)
+ {
+ rc = MATCH_NOMATCH;
+ break;
+ }
/* OK, we can now run the match. If "hitend" is set afterwards, remember the
first starting point for which a partial match was found. */
- 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;
- md->skip_arg_count = 0;
- rc = match(start_match, md->start_code, start_match, 2, md, NULL, 0);
- if (md->hitend && start_partial == NULL)
+ mb->start_match_ptr = start_match;
+ mb->start_used_ptr = start_match;
+ mb->last_used_ptr = start_match;
+ mb->match_call_count = 0;
+ mb->match_function_type = 0;
+ mb->end_offset_top = 0;
+ mb->skip_arg_count = 0;
+ rc = match(start_match, mb->start_code, start_match, 2, mb, NULL, 0);
+
+ if (mb->hitend && start_partial == NULL)
{
- start_partial = md->start_used_ptr;
+ start_partial = mb->start_used_ptr;
match_partial = start_match;
}
@@ -6951,16 +7013,16 @@ for(;;)
case MATCH_SKIP_ARG:
new_start_match = start_match;
- md->ignore_skip_arg = md->skip_arg_count;
+ mb->ignore_skip_arg = mb->skip_arg_count;
break;
/* SKIP passes back the next starting point explicitly, but if it is no
greater than the match we have just done, treat it as NOMATCH. */
case MATCH_SKIP:
- if (md->start_match_ptr > start_match)
+ if (mb->start_match_ptr > start_match)
{
- new_start_match = md->start_match_ptr;
+ new_start_match = mb->start_match_ptr;
break;
}
/* Fall through */
@@ -6971,9 +7033,9 @@ for(;;)
case MATCH_NOMATCH:
case MATCH_PRUNE:
case MATCH_THEN:
- md->ignore_skip_arg = 0;
+ mb->ignore_skip_arg = 0;
new_start_match = start_match + 1;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
ACROSSCHAR(new_start_match < end_subject, *new_start_match,
new_start_match++);
@@ -6997,7 +7059,7 @@ for(;;)
rc = MATCH_NOMATCH;
- /* If PCRE_FIRSTLINE is set, the match must happen before or at the first
+ /* If PCRE2_FIRSTLINE is set, the match must happen before or at the first
newline in the subject (though it may continue over the newline). Therefore,
if we have just failed to match, starting at a newline, do not continue. */
@@ -7014,160 +7076,168 @@ for(;;)
/* 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
+ or ANY or ANYCRLF, advance the match position by one more code unit. In
normal matching start_match will aways be greater than the first position at
this stage, but a failed *SKIP can cause a return at the same point, which is
why the first test exists. */
- if (start_match > (PCRE_PUCHAR)subject + start_offset &&
+ if (start_match > 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))
+ (re->flags & PCRE2_HASCRORLF) == 0 &&
+ (mb->nltype == NLTYPE_ANY ||
+ mb->nltype == NLTYPE_ANYCRLF ||
+ mb->nllen == 2))
start_match++;
- md->mark = NULL; /* Reset for start of next match attempt */
+ mb->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:
+/* When we reach here, one of the stopping conditions is true:
-(1) The pattern is anchored or the match was failed by (*COMMIT);
+(1) The match succeeded, either completely, or partially;
-(2) We are past the end of the subject;
+(2) The pattern is anchored or the match was failed by (*COMMIT);
-(3) PCRE_FIRSTLINE is set and we have failed to match at a newline, because
+(3) We are past the end of the subject or the bumpalong limit;
+
+(4) PCRE2_FIRSTLINE is set and we have failed to match at a newline, because
this option requests that a match occur at or before the first newline in
the subject.
-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. */
+(5) Some kind of error occurred.
+
+*/
ENDLOOP:
+#ifdef HEAP_MATCH_RECURSE
+release_match_heapframes(&frame_zero, mb);
+#endif
+
+/* Release any frames that were saved from recursions. */
+
+while (mb->ovecsave_chain != NULL)
+ {
+ ovecsave_frame *this = mb->ovecsave_chain;
+ mb->ovecsave_chain = this->next;
+ mb->memctl.free(this, mb->memctl.memory_data);
+ }
+
+/* Fill in fields that are always returned in the match data. */
+
+match_data->code = re;
+match_data->subject = subject;
+match_data->mark = mb->mark;
+match_data->matchedby = PCRE2_MATCHEDBY_INTERPRETER;
+
+/* Handle a fully successful match. */
+
if (rc == MATCH_MATCH || rc == MATCH_ACCEPT)
{
+ uint32_t arg_offset_max = 2 * match_data->oveccount;
+
+ /* When 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 memory 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. */
+
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"));
+ memcpy(match_data->ovector + 2, mb->ovector + 2,
+ (arg_offset_max - 2) * sizeof(PCRE2_SIZE));
}
- if (md->end_offset_top > arg_offset_max) md->capture_last |= OVFLBIT;
- DPRINTF(("Freeing temporary memory\n"));
- (PUBL(free))(md->offset_vector);
+ if (mb->end_offset_top > arg_offset_max) mb->capture_last |= OVFLBIT;
+ mb->memctl.free(mb->ovector, mb->memctl.memory_data);
}
/* Set the return code to the number of captured strings, or 0 if there were
- too many to fit into the vector. */
-
- rc = ((md->capture_last & OVFLBIT) != 0 &&
- 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)
+ too many to fit into the ovector. */
+
+ match_data->rc = ((mb->capture_last & OVFLBIT) != 0)?
+ 0 : mb->end_offset_top/2;
+
+ /* If there is space in the offset vector, set any pairs that follow the
+ highest-numbered captured string but are less than the number of capturing
+ groups in the pattern (and are within the ovector) to PCRE2_UNSET. It is
+ documented that this happens. In earlier versions, the whole set of potential
+ capturing offsets was initialized each time round the loop, but this is
+ handled differently now. "Gaps" are set to PCRE2_UNSET dynamically instead
+ (this fixed a bug). Thus, it is only those at the end that need setting here.
+ We can't just mark them all unset at the start of the whole thing because
+ they may get set in one branch that is not the final matching branch. */
+
+ if (mb->end_offset_top/2 <= re->top_bracket)
{
- register int *iptr, *iend;
- int resetcount = 2 + re->top_bracket * 2;
- if (resetcount > offsetcount) resetcount = offsetcount;
- iptr = offsets + md->end_offset_top;
- iend = offsets + resetcount;
- while (iptr < iend) *iptr++ = -1;
+ register PCRE2_SIZE *iptr, *iend;
+ int resetcount = re->top_bracket + 1;
+ if (resetcount > match_data->oveccount) resetcount = match_data->oveccount;
+ iptr = match_data->ovector + mb->end_offset_top;
+ iend = match_data->ovector + 2 * resetcount;
+ while (iptr < iend) *iptr++ = PCRE2_UNSET;
}
/* 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
+ mb->start_match_ptr might be modified if \K was encountered on the success
matching path. */
- if (offsetcount < 2) rc = 0; else
+ if (match_data->oveccount < 1) rc = 0; else
{
- offsets[0] = (int)(md->start_match_ptr - md->start_subject);
- offsets[1] = (int)(md->end_match_ptr - md->start_subject);
+ match_data->ovector[0] = mb->start_match_ptr - mb->start_subject;
+ match_data->ovector[1] = mb->end_match_ptr - mb->start_subject;
}
- /* Return MARK data if requested */
+ /* Set the remaining returned values */
- if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0)
- *(extra_data->mark) = (pcre_uchar *)md->mark;
- DPRINTF((">>>> returning %d\n", rc));
-#ifdef NO_RECURSE
- release_match_heapframes(&frame_zero);
-#endif
- return rc;
+ match_data->startchar = start_match - subject;
+ match_data->leftchar = mb->start_used_ptr - subject;
+ match_data->rightchar = ((mb->last_used_ptr > mb->end_match_ptr)?
+ mb->last_used_ptr : mb->end_match_ptr) - subject;
+ return match_data->rc;
}
-/* Control gets here if there has been an error, or if the overall match
-attempt has failed at all permitted starting positions. */
+/* Control gets here if there has been a partial match, an error, or if the
+overall match attempt has failed at all permitted starting positions. Any mark
+data is in the nomatch_mark field. */
-if (using_temporary_offsets)
- {
- DPRINTF(("Freeing temporary memory\n"));
- (PUBL(free))(md->offset_vector);
- }
+match_data->mark = mb->nomatch_mark;
/* 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));
-#ifdef NO_RECURSE
- release_match_heapframes(&frame_zero);
-#endif
- return rc;
- }
+if (rc != MATCH_NOMATCH && rc != PCRE2_ERROR_PARTIAL)
+ match_data->rc = rc;
-/* Handle partial matches - disable any mark data */
+/* Else handle a partial match. */
-if (match_partial != NULL)
+else if (match_partial != NULL)
{
- DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n"));
- md->mark = NULL;
- if (offsetcount > 1)
+ if (match_data->oveccount > 0)
{
- offsets[0] = (int)(start_partial - (PCRE_PUCHAR)subject);
- offsets[1] = (int)(end_subject - (PCRE_PUCHAR)subject);
- if (offsetcount > 2)
- offsets[2] = (int)(match_partial - (PCRE_PUCHAR)subject);
+ match_data->ovector[0] = match_partial - subject;
+ match_data->ovector[1] = end_subject - subject;
}
- rc = PCRE_ERROR_PARTIAL;
+ match_data->startchar = match_partial - subject;
+ match_data->leftchar = start_partial - subject;
+ match_data->rightchar = end_subject - subject;
+ match_data->rc = PCRE2_ERROR_PARTIAL;
}
-/* This is the classic nomatch case */
+/* Else this is the classic nomatch case. */
-else
- {
- DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));
- rc = PCRE_ERROR_NOMATCH;
- }
+else match_data->rc = PCRE2_ERROR_NOMATCH;
-/* Return the MARK data if it has been requested. */
+/* Free any temporary offsets. */
-if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0)
- *(extra_data->mark) = (pcre_uchar *)md->nomatch_mark;
-#ifdef NO_RECURSE
- release_match_heapframes(&frame_zero);
-#endif
-return rc;
+if (using_temporary_offsets)
+ mb->memctl.free(mb->ovector, mb->memctl.memory_data);
+return match_data->rc;
}
-/* End of pcre_exec.c */
+/* End of pcre2_match.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_match_data.c b/src/3rdparty/pcre2/src/pcre2_match_data.c
new file mode 100644
index 0000000000..85ac998348
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_match_data.c
@@ -0,0 +1,147 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre2_internal.h"
+
+
+
+/*************************************************
+* Create a match data block given ovector size *
+*************************************************/
+
+/* A minimum of 1 is imposed on the number of ovector triplets. */
+
+PCRE2_EXP_DEFN pcre2_match_data * PCRE2_CALL_CONVENTION
+pcre2_match_data_create(uint32_t oveccount, pcre2_general_context *gcontext)
+{
+pcre2_match_data *yield;
+if (oveccount < 1) oveccount = 1;
+yield = PRIV(memctl_malloc)(
+ sizeof(pcre2_match_data) + 3*oveccount*sizeof(PCRE2_SIZE),
+ (pcre2_memctl *)gcontext);
+if (yield == NULL) return NULL;
+yield->oveccount = oveccount;
+return yield;
+}
+
+
+
+/*************************************************
+* Create a match data block using pattern data *
+*************************************************/
+
+/* If no context is supplied, use the memory allocator from the code. */
+
+PCRE2_EXP_DEFN pcre2_match_data * PCRE2_CALL_CONVENTION
+pcre2_match_data_create_from_pattern(const pcre2_code *code,
+ pcre2_general_context *gcontext)
+{
+if (gcontext == NULL) gcontext = (pcre2_general_context *)code;
+return pcre2_match_data_create(((pcre2_real_code *)code)->top_bracket + 1,
+ gcontext);
+}
+
+
+
+/*************************************************
+* Free a match data block *
+*************************************************/
+
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_match_data_free(pcre2_match_data *match_data)
+{
+if (match_data != NULL)
+ match_data->memctl.free(match_data, match_data->memctl.memory_data);
+}
+
+
+
+/*************************************************
+* Get last mark in match *
+*************************************************/
+
+PCRE2_EXP_DEFN PCRE2_SPTR PCRE2_CALL_CONVENTION
+pcre2_get_mark(pcre2_match_data *match_data)
+{
+return match_data->mark;
+}
+
+
+
+/*************************************************
+* Get pointer to ovector *
+*************************************************/
+
+PCRE2_EXP_DEFN PCRE2_SIZE * PCRE2_CALL_CONVENTION
+pcre2_get_ovector_pointer(pcre2_match_data *match_data)
+{
+return match_data->ovector;
+}
+
+
+
+/*************************************************
+* Get number of ovector slots *
+*************************************************/
+
+PCRE2_EXP_DEFN uint32_t PCRE2_CALL_CONVENTION
+pcre2_get_ovector_count(pcre2_match_data *match_data)
+{
+return match_data->oveccount;
+}
+
+
+
+/*************************************************
+* Get starting code unit in match *
+*************************************************/
+
+PCRE2_EXP_DEFN PCRE2_SIZE PCRE2_CALL_CONVENTION
+pcre2_get_startchar(pcre2_match_data *match_data)
+{
+return match_data->startchar;
+}
+
+/* End of pcre2_match_data.c */
diff --git a/src/3rdparty/pcre/pcre_newline.c b/src/3rdparty/pcre2/src/pcre2_newline.c
index b8f5a4de19..6e9366db93 100644
--- a/src/3rdparty/pcre/pcre_newline.c
+++ b/src/3rdparty/pcre2/src/pcre2_newline.c
@@ -6,7 +6,8 @@
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
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -41,7 +42,7 @@ 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
+referring to a different set of newline characters. At present, PCRE2 supports
only NLTYPE_FIXED, which gets handled without these functions, NLTYPE_ANYCRLF,
and NLTYPE_ANY. The full list of Unicode newline characters is taken from
http://unicode.org/unicode/reports/tr18/. */
@@ -51,7 +52,7 @@ http://unicode.org/unicode/reports/tr18/. */
#include "config.h"
#endif
-#include "pcre_internal.h"
+#include "pcre2_internal.h"
@@ -59,8 +60,10 @@ http://unicode.org/unicode/reports/tr18/. */
* 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.
+/* This function is called only via the IS_NEWLINE macro, which does so only
+when the newline type is NLTYPE_ANY or NLTYPE_ANYCRLF. The case of a fixed
+newline (NLTYPE_FIXED) is handled inline. It is guaranteed that the code unit
+pointed to by ptr is less than the end of the string.
Arguments:
ptr pointer to possible newline
@@ -73,28 +76,30 @@ Returns: TRUE or FALSE
*/
BOOL
-PRIV(is_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR endptr, int *lenptr,
- BOOL utf)
+PRIV(is_newline)(PCRE2_SPTR ptr, uint32_t type, PCRE2_SPTR endptr,
+ uint32_t *lenptr, BOOL utf)
{
-pcre_uint32 c;
-(void)utf;
-#ifdef SUPPORT_UTF
-if (utf)
- {
- GETCHAR(c, ptr);
- }
-else
-#endif /* SUPPORT_UTF */
- c = *ptr;
+uint32_t c;
-/* Note that this function is called only for ANY or ANYCRLF. */
+#ifdef SUPPORT_UNICODE
+if (utf) { GETCHAR(c, ptr); } else c = *ptr;
+#else
+(void)utf;
+c = *ptr;
+#endif /* SUPPORT_UNICODE */
if (type == NLTYPE_ANYCRLF) switch(c)
{
- case CHAR_LF: *lenptr = 1; return TRUE;
- case CHAR_CR: *lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1;
- return TRUE;
- default: return FALSE;
+ case CHAR_LF:
+ *lenptr = 1;
+ return TRUE;
+
+ case CHAR_CR:
+ *lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1;
+ return TRUE;
+
+ default:
+ return FALSE;
}
/* NLTYPE_ANY */
@@ -106,25 +111,36 @@ else switch(c)
#endif
case CHAR_LF:
case CHAR_VT:
- case CHAR_FF: *lenptr = 1; return TRUE;
+ case CHAR_FF:
+ *lenptr = 1;
+ return TRUE;
case CHAR_CR:
*lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1;
return TRUE;
#ifndef EBCDIC
-#ifdef COMPILE_PCRE8
- case CHAR_NEL: *lenptr = utf? 2 : 1; return TRUE;
- case 0x2028: /* LS */
- case 0x2029: *lenptr = 3; return TRUE; /* PS */
-#else /* COMPILE_PCRE16 || COMPILE_PCRE32 */
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ case CHAR_NEL:
+ *lenptr = utf? 2 : 1;
+ return TRUE;
+
+ case 0x2028: /* LS */
+ case 0x2029: /* PS */
+ *lenptr = 3;
+ return TRUE;
+
+#else /* 16-bit or 32-bit code units */
case CHAR_NEL:
- case 0x2028: /* LS */
- case 0x2029: *lenptr = 1; return TRUE; /* PS */
-#endif /* COMPILE_PCRE8 */
-#endif /* Not EBCDIC */
+ case 0x2028: /* LS */
+ case 0x2029: /* PS */
+ *lenptr = 1;
+ return TRUE;
+#endif
+#endif /* Not EBCDIC */
- default: return FALSE;
+ default:
+ return FALSE;
}
}
@@ -134,8 +150,10 @@ else switch(c)
* 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.
+/* This function is called only via the WAS_NEWLINE macro, which does so only
+when the newline type is NLTYPE_ANY or NLTYPE_ANYCRLF. The case of a fixed
+newline (NLTYPE_FIXED) is handled inline. It is guaranteed that the initial
+value of ptr is greater than the start of the string that is being processed.
Arguments:
ptr pointer to possible newline
@@ -148,23 +166,23 @@ Returns: TRUE or FALSE
*/
BOOL
-PRIV(was_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR startptr, int *lenptr,
- BOOL utf)
+PRIV(was_newline)(PCRE2_SPTR ptr, uint32_t type, PCRE2_SPTR startptr,
+ uint32_t *lenptr, BOOL utf)
{
-pcre_uint32 c;
-(void)utf;
+uint32_t c;
ptr--;
-#ifdef SUPPORT_UTF
+
+#ifdef SUPPORT_UNICODE
if (utf)
{
BACKCHAR(ptr);
GETCHAR(c, ptr);
}
-else
-#endif /* SUPPORT_UTF */
- c = *ptr;
-
-/* Note that this function is called only for ANY or ANYCRLF. */
+else c = *ptr;
+#else
+(void)utf;
+c = *ptr;
+#endif /* SUPPORT_UNICODE */
if (type == NLTYPE_ANYCRLF) switch(c)
{
@@ -172,8 +190,12 @@ if (type == NLTYPE_ANYCRLF) switch(c)
*lenptr = (ptr > startptr && ptr[-1] == CHAR_CR)? 2 : 1;
return TRUE;
- case CHAR_CR: *lenptr = 1; return TRUE;
- default: return FALSE;
+ case CHAR_CR:
+ *lenptr = 1;
+ return TRUE;
+
+ default:
+ return FALSE;
}
/* NLTYPE_ANY */
@@ -189,22 +211,33 @@ else switch(c)
#endif
case CHAR_VT:
case CHAR_FF:
- case CHAR_CR: *lenptr = 1; return TRUE;
+ case CHAR_CR:
+ *lenptr = 1;
+ return TRUE;
#ifndef EBCDIC
-#ifdef COMPILE_PCRE8
- case CHAR_NEL: *lenptr = utf? 2 : 1; return TRUE;
- case 0x2028: /* LS */
- case 0x2029: *lenptr = 3; return TRUE; /* PS */
-#else /* COMPILE_PCRE16 || COMPILE_PCRE32 */
+#if PCRE2_CODE_UNIT_WIDTH == 8
case CHAR_NEL:
- case 0x2028: /* LS */
- case 0x2029: *lenptr = 1; return TRUE; /* PS */
-#endif /* COMPILE_PCRE8 */
-#endif /* NotEBCDIC */
+ *lenptr = utf? 2 : 1;
+ return TRUE;
+
+ case 0x2028: /* LS */
+ case 0x2029: /* PS */
+ *lenptr = 3;
+ return TRUE;
+
+#else /* 16-bit or 32-bit code units */
+ case CHAR_NEL:
+ case 0x2028: /* LS */
+ case 0x2029: /* PS */
+ *lenptr = 1;
+ return TRUE;
+#endif
+#endif /* Not EBCDIC */
- default: return FALSE;
+ default:
+ return FALSE;
}
}
-/* End of pcre_newline.c */
+/* End of pcre2_newline.c */
diff --git a/src/3rdparty/pcre/pcre_ord2utf8.c b/src/3rdparty/pcre2/src/pcre2_ord2utf.c
index 95f1beb963..75252b763a 100644
--- a/src/3rdparty/pcre/pcre_ord2utf8.c
+++ b/src/3rdparty/pcre2/src/pcre2_ord2utf.c
@@ -6,7 +6,8 @@
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
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -38,39 +39,51 @@ POSSIBILITY OF SUCH DAMAGE.
*/
-/* This file contains a private PCRE function that converts an ordinal
-character value into a UTF8 string. */
+/* This file contains a function that converts a Unicode character code point
+into a UTF string. The behaviour is different for each code unit width. */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#define COMPILE_PCRE8
+#include "pcre2_internal.h"
+
+
+/* If SUPPORT_UNICODE is not defined, this function will never be called.
+Supply a dummy function because some compilers do not like empty source
+modules. */
+
+#ifndef SUPPORT_UNICODE
+unsigned int
+PRIV(ord2utf)(uint32_t cvalue, PCRE2_UCHAR *buffer)
+{
+(void)(cvalue);
+(void)(buffer);
+return 0;
+}
+#else /* SUPPORT_UNICODE */
-#include "pcre_internal.h"
/*************************************************
-* Convert character value to UTF-8 *
+* Convert code point to UTF *
*************************************************/
-/* This function takes an integer value in the range 0 - 0x10ffff
-and encodes it as a UTF-8 character in 1 to 4 pcre_uchars.
-
+/*
Arguments:
cvalue the character value
- buffer pointer to buffer for result - at least 6 pcre_uchars long
+ buffer pointer to buffer for result
-Returns: number of characters placed in the buffer
+Returns: number of code units placed in the buffer
*/
-unsigned
-int
-PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer)
+unsigned int
+PRIV(ord2utf)(uint32_t cvalue, PCRE2_UCHAR *buffer)
{
-#ifdef SUPPORT_UTF
+/* Convert to UTF-8 */
+#if PCRE2_CODE_UNIT_WIDTH == 8
register int i, j;
-
for (i = 0; i < PRIV(utf8_table1_size); i++)
if ((int)cvalue <= PRIV(utf8_table1)[i]) break;
buffer += i;
@@ -82,13 +95,26 @@ for (j = i; j > 0; j--)
*buffer = PRIV(utf8_table2)[i] | cvalue;
return i + 1;
-#else
+/* Convert to UTF-16 */
-(void)(cvalue); /* Keep compiler happy; this function won't ever be */
-(void)(buffer); /* called when SUPPORT_UTF is not defined. */
-return 0;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+if (cvalue <= 0xffff)
+ {
+ *buffer = (PCRE2_UCHAR)cvalue;
+ return 1;
+ }
+cvalue -= 0x10000;
+*buffer++ = 0xd800 | (cvalue >> 10);
+*buffer = 0xdc00 | (cvalue & 0x3ff);
+return 2;
+
+/* Convert to UTF-32 */
+#else
+*buffer = (PCRE2_UCHAR)cvalue;
+return 1;
#endif
}
+#endif /* SUPPORT_UNICODE */
-/* End of pcre_ord2utf8.c */
+/* End of pcre_ord2utf.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_pattern_info.c b/src/3rdparty/pcre2/src/pcre2_pattern_info.c
new file mode 100644
index 0000000000..5b32a905b0
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_pattern_info.c
@@ -0,0 +1,410 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre2_internal.h"
+
+
+/*************************************************
+* Return info about compiled pattern *
+*************************************************/
+
+/*
+Arguments:
+ code points to compiled code
+ what what information is required
+ where where to put the information; if NULL, return length
+
+Returns: 0 when data returned
+ > 0 when length requested
+ < 0 on error or unset value
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_pattern_info(const pcre2_code *code, uint32_t what, void *where)
+{
+const pcre2_real_code *re = (pcre2_real_code *)code;
+
+if (where == NULL) /* Requests field length */
+ {
+ switch(what)
+ {
+ case PCRE2_INFO_ALLOPTIONS:
+ case PCRE2_INFO_ARGOPTIONS:
+ case PCRE2_INFO_BACKREFMAX:
+ case PCRE2_INFO_BSR:
+ case PCRE2_INFO_CAPTURECOUNT:
+ case PCRE2_INFO_FIRSTCODETYPE:
+ case PCRE2_INFO_FIRSTCODEUNIT:
+ case PCRE2_INFO_HASBACKSLASHC:
+ case PCRE2_INFO_HASCRORLF:
+ case PCRE2_INFO_JCHANGED:
+ case PCRE2_INFO_LASTCODETYPE:
+ case PCRE2_INFO_LASTCODEUNIT:
+ case PCRE2_INFO_MATCHEMPTY:
+ case PCRE2_INFO_MATCHLIMIT:
+ case PCRE2_INFO_MAXLOOKBEHIND:
+ case PCRE2_INFO_MINLENGTH:
+ case PCRE2_INFO_NAMEENTRYSIZE:
+ case PCRE2_INFO_NAMECOUNT:
+ case PCRE2_INFO_NEWLINE:
+ case PCRE2_INFO_RECURSIONLIMIT:
+ return sizeof(uint32_t);
+
+ case PCRE2_INFO_FIRSTBITMAP:
+ return sizeof(const uint8_t *);
+
+ case PCRE2_INFO_JITSIZE:
+ case PCRE2_INFO_SIZE:
+ return sizeof(size_t);
+
+ case PCRE2_INFO_NAMETABLE:
+ return sizeof(PCRE2_SPTR);
+ }
+ }
+
+if (re == NULL) return PCRE2_ERROR_NULL;
+
+/* Check that the first field in the block is the magic number. If it is not,
+return with PCRE2_ERROR_BADMAGIC. */
+
+if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;
+
+/* Check that this pattern was compiled in the correct bit mode */
+
+if ((re->flags & (PCRE2_CODE_UNIT_WIDTH/8)) == 0) return PCRE2_ERROR_BADMODE;
+
+switch(what)
+ {
+ case PCRE2_INFO_ALLOPTIONS:
+ *((uint32_t *)where) = re->overall_options;
+ break;
+
+ case PCRE2_INFO_ARGOPTIONS:
+ *((uint32_t *)where) = re->compile_options;
+ break;
+
+ case PCRE2_INFO_BACKREFMAX:
+ *((uint32_t *)where) = re->top_backref;
+ break;
+
+ case PCRE2_INFO_BSR:
+ *((uint32_t *)where) = re->bsr_convention;
+ break;
+
+ case PCRE2_INFO_CAPTURECOUNT:
+ *((uint32_t *)where) = re->top_bracket;
+ break;
+
+ case PCRE2_INFO_FIRSTCODETYPE:
+ *((uint32_t *)where) = ((re->flags & PCRE2_FIRSTSET) != 0)? 1 :
+ ((re->flags & PCRE2_STARTLINE) != 0)? 2 : 0;
+ break;
+
+ case PCRE2_INFO_FIRSTCODEUNIT:
+ *((uint32_t *)where) = ((re->flags & PCRE2_FIRSTSET) != 0)?
+ re->first_codeunit : 0;
+ break;
+
+ case PCRE2_INFO_FIRSTBITMAP:
+ *((const uint8_t **)where) = ((re->flags & PCRE2_FIRSTMAPSET) != 0)?
+ &(re->start_bitmap[0]) : NULL;
+ break;
+
+ case PCRE2_INFO_HASBACKSLASHC:
+ *((uint32_t *)where) = (re->flags & PCRE2_HASBKC) != 0;
+ break;
+
+ case PCRE2_INFO_HASCRORLF:
+ *((uint32_t *)where) = (re->flags & PCRE2_HASCRORLF) != 0;
+ break;
+
+ case PCRE2_INFO_JCHANGED:
+ *((uint32_t *)where) = (re->flags & PCRE2_JCHANGED) != 0;
+ break;
+
+ case PCRE2_INFO_JITSIZE:
+#ifdef SUPPORT_JIT
+ *((size_t *)where) = (re->executable_jit != NULL)?
+ PRIV(jit_get_size)(re->executable_jit) : 0;
+#else
+ *((size_t *)where) = 0;
+#endif
+ break;
+
+ case PCRE2_INFO_LASTCODETYPE:
+ *((uint32_t *)where) = ((re->flags & PCRE2_LASTSET) != 0)? 1 : 0;
+ break;
+
+ case PCRE2_INFO_LASTCODEUNIT:
+ *((uint32_t *)where) = ((re->flags & PCRE2_LASTSET) != 0)?
+ re->last_codeunit : 0;
+ break;
+
+ case PCRE2_INFO_MATCHEMPTY:
+ *((uint32_t *)where) = (re->flags & PCRE2_MATCH_EMPTY) != 0;
+ break;
+
+ case PCRE2_INFO_MATCHLIMIT:
+ *((uint32_t *)where) = re->limit_match;
+ if (re->limit_match == UINT32_MAX) return PCRE2_ERROR_UNSET;
+ break;
+
+ case PCRE2_INFO_MAXLOOKBEHIND:
+ *((uint32_t *)where) = re->max_lookbehind;
+ break;
+
+ case PCRE2_INFO_MINLENGTH:
+ *((uint32_t *)where) = re->minlength;
+ break;
+
+ case PCRE2_INFO_NAMEENTRYSIZE:
+ *((uint32_t *)where) = re->name_entry_size;
+ break;
+
+ case PCRE2_INFO_NAMECOUNT:
+ *((uint32_t *)where) = re->name_count;
+ break;
+
+ case PCRE2_INFO_NAMETABLE:
+ *((PCRE2_SPTR *)where) = (PCRE2_SPTR)((char *)re + sizeof(pcre2_real_code));
+ break;
+
+ case PCRE2_INFO_NEWLINE:
+ *((uint32_t *)where) = re->newline_convention;
+ break;
+
+ case PCRE2_INFO_RECURSIONLIMIT:
+ *((uint32_t *)where) = re->limit_recursion;
+ if (re->limit_recursion == UINT32_MAX) return PCRE2_ERROR_UNSET;
+ break;
+
+ case PCRE2_INFO_SIZE:
+ *((size_t *)where) = re->blocksize;
+ break;
+
+ default: return PCRE2_ERROR_BADOPTION;
+ }
+
+return 0;
+}
+
+
+
+/*************************************************
+* Callout enumerator *
+*************************************************/
+
+/*
+Arguments:
+ code points to compiled code
+ callback function called for each callout block
+ callout_data user data passed to the callback
+
+Returns: 0 when successfully completed
+ < 0 on local error
+ != 0 for callback error
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_callout_enumerate(const pcre2_code *code,
+ int (*callback)(pcre2_callout_enumerate_block *, void *), void *callout_data)
+{
+pcre2_real_code *re = (pcre2_real_code *)code;
+pcre2_callout_enumerate_block cb;
+PCRE2_SPTR cc;
+#ifdef SUPPORT_UNICODE
+BOOL utf = (re->overall_options & PCRE2_UTF) != 0;
+#endif
+
+if (re == NULL) return PCRE2_ERROR_NULL;
+
+/* Check that the first field in the block is the magic number. If it is not,
+return with PCRE2_ERROR_BADMAGIC. */
+
+if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;
+
+/* Check that this pattern was compiled in the correct bit mode */
+
+if ((re->flags & (PCRE2_CODE_UNIT_WIDTH/8)) == 0) return PCRE2_ERROR_BADMODE;
+
+cb.version = 0;
+cc = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code))
+ + re->name_count * re->name_entry_size;
+
+while (TRUE)
+ {
+ int rc;
+ switch (*cc)
+ {
+ case OP_END:
+ return 0;
+
+ case OP_CHAR:
+ case OP_CHARI:
+ case OP_NOT:
+ case OP_NOTI:
+ case OP_STAR:
+ case OP_MINSTAR:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_UPTO:
+ case OP_MINUPTO:
+ case OP_EXACT:
+ case OP_POSSTAR:
+ case OP_POSPLUS:
+ case OP_POSQUERY:
+ case OP_POSUPTO:
+ case OP_STARI:
+ case OP_MINSTARI:
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_QUERYI:
+ case OP_MINQUERYI:
+ case OP_UPTOI:
+ case OP_MINUPTOI:
+ case OP_EXACTI:
+ case OP_POSSTARI:
+ case OP_POSPLUSI:
+ case OP_POSQUERYI:
+ case OP_POSUPTOI:
+ case OP_NOTSTAR:
+ case OP_NOTMINSTAR:
+ case OP_NOTPLUS:
+ case OP_NOTMINPLUS:
+ case OP_NOTQUERY:
+ case OP_NOTMINQUERY:
+ case OP_NOTUPTO:
+ case OP_NOTMINUPTO:
+ case OP_NOTEXACT:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPOSPLUS:
+ case OP_NOTPOSQUERY:
+ case OP_NOTPOSUPTO:
+ case OP_NOTSTARI:
+ case OP_NOTMINSTARI:
+ case OP_NOTPLUSI:
+ case OP_NOTMINPLUSI:
+ case OP_NOTQUERYI:
+ case OP_NOTMINQUERYI:
+ case OP_NOTUPTOI:
+ case OP_NOTMINUPTOI:
+ case OP_NOTEXACTI:
+ case OP_NOTPOSSTARI:
+ case OP_NOTPOSPLUSI:
+ case OP_NOTPOSQUERYI:
+ case OP_NOTPOSUPTOI:
+ cc += PRIV(OP_lengths)[*cc];
+#ifdef SUPPORT_UNICODE
+ if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
+#endif
+ break;
+
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEEXACT:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEPOSQUERY:
+ case OP_TYPEPOSUPTO:
+ cc += PRIV(OP_lengths)[*cc];
+#ifdef SUPPORT_UNICODE
+ if (cc[-1] == OP_PROP || cc[-1] == OP_NOTPROP) cc += 2;
+#endif
+ break;
+
+#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
+ case OP_XCLASS:
+ cc += GET(cc, 1);
+ break;
+#endif
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ cc += PRIV(OP_lengths)[*cc] + cc[1];
+ break;
+
+ case OP_CALLOUT:
+ cb.pattern_position = GET(cc, 1);
+ cb.next_item_length = GET(cc, 1 + LINK_SIZE);
+ cb.callout_number = cc[1 + 2*LINK_SIZE];
+ cb.callout_string_offset = 0;
+ cb.callout_string_length = 0;
+ cb.callout_string = NULL;
+ rc = callback(&cb, callout_data);
+ if (rc != 0) return rc;
+ cc += PRIV(OP_lengths)[*cc];
+ break;
+
+ case OP_CALLOUT_STR:
+ cb.pattern_position = GET(cc, 1);
+ cb.next_item_length = GET(cc, 1 + LINK_SIZE);
+ cb.callout_number = 0;
+ cb.callout_string_offset = GET(cc, 1 + 3*LINK_SIZE);
+ cb.callout_string_length =
+ GET(cc, 1 + 2*LINK_SIZE) - (1 + 4*LINK_SIZE) - 2;
+ cb.callout_string = cc + (1 + 4*LINK_SIZE) + 1;
+ rc = callback(&cb, callout_data);
+ if (rc != 0) return rc;
+ cc += GET(cc, 1 + 2*LINK_SIZE);
+ break;
+
+ default:
+ cc += PRIV(OP_lengths)[*cc];
+ break;
+ }
+ }
+}
+
+/* End of pcre2_pattern_info.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_printint.c b/src/3rdparty/pcre2/src/pcre2_printint.c
new file mode 100644
index 0000000000..2d30926a74
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_printint.c
@@ -0,0 +1,832 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+/* This module contains a PCRE private debugging function for printing out the
+internal form of a compiled regular expression, along with some supporting
+local functions. This source file is #included in pcre2test.c at each supported
+code unit width, with PCRE2_SUFFIX set appropriately, just like the functions
+that comprise the library. It can also optionally be included in
+pcre2_compile.c for detailed debugging in error situations. */
+
+
+/* Tables of operator names. The same 8-bit table is used for all code unit
+widths, so it must be defined only once. The list itself is defined in
+pcre2_internal.h, which is #included by pcre2test before this file. */
+
+#ifndef OP_LISTS_DEFINED
+static const char *OP_names[] = { OP_NAME_LIST };
+#define OP_LISTS_DEFINED
+#endif
+
+/* The functions and tables herein must all have mode-dependent names. */
+
+#define OP_lengths PCRE2_SUFFIX(OP_lengths_)
+#define get_ucpname PCRE2_SUFFIX(get_ucpname_)
+#define pcre2_printint PCRE2_SUFFIX(pcre2_printint_)
+#define print_char PCRE2_SUFFIX(print_char_)
+#define print_custring PCRE2_SUFFIX(print_custring_)
+#define print_custring_bylen PCRE2_SUFFIX(print_custring_bylen_)
+#define print_prop PCRE2_SUFFIX(print_prop_)
+
+/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that
+the definition is next to the definition of the opcodes in pcre2_internal.h.
+The contents of the table are, however, mode-dependent. */
+
+static const uint8_t OP_lengths[] = { OP_LENGTHS };
+
+
+
+/*************************************************
+* Print one character from a string *
+*************************************************/
+
+/* In UTF mode the character may occupy more than one code unit.
+
+Arguments:
+ f file to write to
+ ptr pointer to first code unit of the character
+ utf TRUE if string is UTF (will be FALSE if UTF is not supported)
+
+Returns: number of additional code units used
+*/
+
+static unsigned int
+print_char(FILE *f, PCRE2_SPTR ptr, BOOL utf)
+{
+uint32_t c = *ptr;
+BOOL one_code_unit = !utf;
+
+/* If UTF is supported and requested, check for a valid single code unit. */
+
+#ifdef SUPPORT_UNICODE
+if (utf)
+ {
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ one_code_unit = c < 0x80;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+ one_code_unit = (c & 0xfc00) != 0xd800;
+#else
+ one_code_unit = (c & 0xfffff800u) != 0xd800u;
+#endif /* CODE_UNIT_WIDTH */
+ }
+#endif /* SUPPORT_UNICODE */
+
+/* Handle a valid one-code-unit character at any width. */
+
+if (one_code_unit)
+ {
+ if (PRINTABLE(c)) fprintf(f, "%c", (char)c);
+ else if (c < 0x80) fprintf(f, "\\x%02x", c);
+ else fprintf(f, "\\x{%02x}", c);
+ return 0;
+ }
+
+/* Code for invalid UTF code units and multi-unit UTF characters is different
+for each width. If UTF is not supported, control should never get here, but we
+need a return statement to keep the compiler happy. */
+
+#ifndef SUPPORT_UNICODE
+return 0;
+#else
+
+/* Malformed UTF-8 should occur only if the sanity check has been turned off.
+Rather than swallow random bytes, just stop if we hit a bad one. Print it with
+\X instead of \x as an indication. */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+if ((c & 0xc0) != 0xc0)
+ {
+ fprintf(f, "\\X{%x}", c); /* Invalid starting byte */
+ return 0;
+ }
+else
+ {
+ int i;
+ int a = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */
+ int s = 6*a;
+ c = (c & PRIV(utf8_table3)[a]) << s;
+ for (i = 1; i <= a; i++)
+ {
+ if ((ptr[i] & 0xc0) != 0x80)
+ {
+ fprintf(f, "\\X{%x}", c); /* Invalid secondary byte */
+ return i - 1;
+ }
+ s -= 6;
+ c |= (ptr[i] & 0x3f) << s;
+ }
+ fprintf(f, "\\x{%x}", c);
+ return a;
+}
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
+
+/* UTF-16: rather than swallow a low surrogate, just stop if we hit a bad one.
+Print it with \X instead of \x as an indication. */
+
+#if PCRE2_CODE_UNIT_WIDTH == 16
+if ((ptr[1] & 0xfc00) != 0xdc00)
+ {
+ fprintf(f, "\\X{%x}", c);
+ return 0;
+ }
+c = (((c & 0x3ff) << 10) | (ptr[1] & 0x3ff)) + 0x10000;
+fprintf(f, "\\x{%x}", c);
+return 1;
+#endif /* PCRE2_CODE_UNIT_WIDTH == 16 */
+
+/* For UTF-32 we get here only for a malformed code unit, which should only
+occur if the sanity check has been turned off. Print it with \X instead of \x
+as an indication. */
+
+#if PCRE2_CODE_UNIT_WIDTH == 32
+fprintf(f, "\\X{%x}", c);
+return 0;
+#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */
+#endif /* SUPPORT_UNICODE */
+}
+
+
+
+/*************************************************
+* Print string as a list of code units *
+*************************************************/
+
+/* These take no account of UTF as they always print each individual code unit.
+The string is zero-terminated for print_custring(); the length is given for
+print_custring_bylen().
+
+Arguments:
+ f file to write to
+ ptr point to the string
+ len length for print_custring_bylen()
+
+Returns: nothing
+*/
+
+static void
+print_custring(FILE *f, PCRE2_SPTR ptr)
+{
+while (*ptr != '\0')
+ {
+ register uint32_t c = *ptr++;
+ if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);
+ }
+}
+
+static void
+print_custring_bylen(FILE *f, PCRE2_SPTR ptr, PCRE2_UCHAR len)
+{
+for (; len > 0; len--)
+ {
+ register uint32_t c = *ptr++;
+ if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);
+ }
+}
+
+
+
+/*************************************************
+* Find Unicode property name *
+*************************************************/
+
+/* When there is no UTF/UCP support, the table of names does not exist. This
+function should not be called in such configurations, because a pattern that
+tries to use Unicode properties won't compile. Rather than put lots of #ifdefs
+into the main code, however, we just put one into this function. */
+
+static const char *
+get_ucpname(unsigned int ptype, unsigned int pvalue)
+{
+#ifdef SUPPORT_UNICODE
+int i;
+for (i = PRIV(utt_size) - 1; i >= 0; i--)
+ {
+ if (ptype == PRIV(utt)[i].type && pvalue == PRIV(utt)[i].value) break;
+ }
+return (i >= 0)? PRIV(utt_names) + PRIV(utt)[i].name_offset : "??";
+#else /* No UTF support */
+(void)ptype;
+(void)pvalue;
+return "??";
+#endif /* SUPPORT_UNICODE */
+}
+
+
+
+/*************************************************
+* Print Unicode property value *
+*************************************************/
+
+/* "Normal" properties can be printed from tables. The PT_CLIST property is a
+pseudo-property that contains a pointer to a list of case-equivalent
+characters.
+
+Arguments:
+ f file to write to
+ code pointer in the compiled code
+ before text to print before
+ after text to print after
+
+Returns: nothing
+*/
+
+static void
+print_prop(FILE *f, PCRE2_SPTR code, const char *before, const char *after)
+{
+if (code[1] != PT_CLIST)
+ {
+ fprintf(f, "%s%s %s%s", before, OP_names[*code], get_ucpname(code[1],
+ code[2]), after);
+ }
+else
+ {
+ const char *not = (*code == OP_PROP)? "" : "not ";
+ const uint32_t *p = PRIV(ucd_caseless_sets) + code[2];
+ fprintf (f, "%s%sclist", before, not);
+ while (*p < NOTACHAR) fprintf(f, " %04x", *p++);
+ fprintf(f, "%s", after);
+ }
+}
+
+
+
+/*************************************************
+* Print compiled pattern *
+*************************************************/
+
+/* The print_lengths flag controls whether offsets and lengths of items are
+printed. Lenths can be turned off from pcre2test so that automatic tests on
+bytecode can be written that do not depend on the value of LINK_SIZE.
+
+Arguments:
+ re a compiled pattern
+ f the file to write to
+ print_lengths show various lengths
+
+Returns: nothing
+*/
+
+static void
+pcre2_printint(pcre2_code *re, FILE *f, BOOL print_lengths)
+{
+PCRE2_SPTR codestart, nametable, code;
+uint32_t nesize = re->name_entry_size;
+BOOL utf = (re->overall_options & PCRE2_UTF) != 0;
+
+nametable = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code));
+code = codestart = nametable + re->name_count * re->name_entry_size;
+
+for(;;)
+ {
+ PCRE2_SPTR ccode;
+ uint32_t c;
+ int i;
+ const char *flag = " ";
+ unsigned int extra = 0;
+
+ if (print_lengths)
+ fprintf(f, "%3d ", (int)(code - codestart));
+ else
+ fprintf(f, " ");
+
+ switch(*code)
+ {
+/* ========================================================================== */
+ /* These cases are never obeyed. This is a fudge that causes a compile-
+ time error if the vectors OP_names or OP_lengths, which are indexed
+ by opcode, are not the correct length. It seems to be the only way to do
+ such a check at compile time, as the sizeof() operator does not work in
+ the C preprocessor. */
+
+ case OP_TABLE_LENGTH:
+ case OP_TABLE_LENGTH +
+ ((sizeof(OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) &&
+ (sizeof(OP_lengths) == OP_TABLE_LENGTH)):
+ break;
+/* ========================================================================== */
+
+ case OP_END:
+ fprintf(f, " %s\n", OP_names[*code]);
+ fprintf(f, "------------------------------------------------------------------\n");
+ return;
+
+ case OP_CHAR:
+ fprintf(f, " ");
+ do
+ {
+ code++;
+ code += 1 + print_char(f, code, utf);
+ }
+ while (*code == OP_CHAR);
+ fprintf(f, "\n");
+ continue;
+
+ case OP_CHARI:
+ fprintf(f, " /i ");
+ do
+ {
+ code++;
+ code += 1 + print_char(f, code, utf);
+ }
+ while (*code == OP_CHARI);
+ fprintf(f, "\n");
+ continue;
+
+ case OP_CBRA:
+ case OP_CBRAPOS:
+ case OP_SCBRA:
+ case OP_SCBRAPOS:
+ if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
+ else fprintf(f, " ");
+ fprintf(f, "%s %d", OP_names[*code], GET2(code, 1+LINK_SIZE));
+ break;
+
+ case OP_BRA:
+ case OP_BRAPOS:
+ case OP_SBRA:
+ case OP_SBRAPOS:
+ case OP_KETRMAX:
+ case OP_KETRMIN:
+ case OP_KETRPOS:
+ case OP_ALT:
+ case OP_KET:
+ case OP_ASSERT:
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ case OP_ONCE:
+ case OP_ONCE_NC:
+ case OP_COND:
+ case OP_SCOND:
+ case OP_REVERSE:
+ if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
+ else fprintf(f, " ");
+ fprintf(f, "%s", OP_names[*code]);
+ break;
+
+ case OP_CLOSE:
+ fprintf(f, " %s %d", OP_names[*code], GET2(code, 1));
+ break;
+
+ case OP_CREF:
+ fprintf(f, "%3d %s", GET2(code,1), OP_names[*code]);
+ break;
+
+ case OP_DNCREF:
+ {
+ PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;
+ fprintf(f, " %s Cond ref <", flag);
+ print_custring(f, entry);
+ fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
+ }
+ break;
+
+ case OP_RREF:
+ c = GET2(code, 1);
+ if (c == RREF_ANY)
+ fprintf(f, " Cond recurse any");
+ else
+ fprintf(f, " Cond recurse %d", c);
+ break;
+
+ case OP_DNRREF:
+ {
+ PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;
+ fprintf(f, " %s Cond recurse <", flag);
+ print_custring(f, entry);
+ fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
+ }
+ break;
+
+ case OP_FALSE:
+ fprintf(f, " Cond false");
+ break;
+
+ case OP_TRUE:
+ fprintf(f, " Cond true");
+ break;
+
+ case OP_STARI:
+ case OP_MINSTARI:
+ case OP_POSSTARI:
+ case OP_PLUSI:
+ case OP_MINPLUSI:
+ case OP_POSPLUSI:
+ case OP_QUERYI:
+ case OP_MINQUERYI:
+ case OP_POSQUERYI:
+ flag = "/i";
+ /* Fall through */
+ case OP_STAR:
+ case OP_MINSTAR:
+ case OP_POSSTAR:
+ case OP_PLUS:
+ case OP_MINPLUS:
+ case OP_POSPLUS:
+ case OP_QUERY:
+ case OP_MINQUERY:
+ case OP_POSQUERY:
+ case OP_TYPESTAR:
+ case OP_TYPEMINSTAR:
+ case OP_TYPEPOSSTAR:
+ case OP_TYPEPLUS:
+ case OP_TYPEMINPLUS:
+ case OP_TYPEPOSPLUS:
+ case OP_TYPEQUERY:
+ case OP_TYPEMINQUERY:
+ case OP_TYPEPOSQUERY:
+ fprintf(f, " %s ", flag);
+
+ if (*code >= OP_TYPESTAR)
+ {
+ if (code[1] == OP_PROP || code[1] == OP_NOTPROP)
+ {
+ print_prop(f, code + 1, "", " ");
+ extra = 2;
+ }
+ else fprintf(f, "%s", OP_names[code[1]]);
+ }
+ else extra = print_char(f, code+1, utf);
+ fprintf(f, "%s", OP_names[*code]);
+ break;
+
+ case OP_EXACTI:
+ case OP_UPTOI:
+ case OP_MINUPTOI:
+ case OP_POSUPTOI:
+ flag = "/i";
+ /* Fall through */
+ case OP_EXACT:
+ case OP_UPTO:
+ case OP_MINUPTO:
+ case OP_POSUPTO:
+ fprintf(f, " %s ", flag);
+ extra = print_char(f, code + 1 + IMM2_SIZE, utf);
+ fprintf(f, "{");
+ if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,");
+ fprintf(f, "%d}", GET2(code,1));
+ if (*code == OP_MINUPTO || *code == OP_MINUPTOI) fprintf(f, "?");
+ else if (*code == OP_POSUPTO || *code == OP_POSUPTOI) fprintf(f, "+");
+ break;
+
+ case OP_TYPEEXACT:
+ case OP_TYPEUPTO:
+ case OP_TYPEMINUPTO:
+ case OP_TYPEPOSUPTO:
+ if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
+ {
+ print_prop(f, code + IMM2_SIZE + 1, " ", " ");
+ extra = 2;
+ }
+ else fprintf(f, " %s", OP_names[code[1 + IMM2_SIZE]]);
+ fprintf(f, "{");
+ if (*code != OP_TYPEEXACT) fprintf(f, "0,");
+ fprintf(f, "%d}", GET2(code,1));
+ if (*code == OP_TYPEMINUPTO) fprintf(f, "?");
+ else if (*code == OP_TYPEPOSUPTO) fprintf(f, "+");
+ break;
+
+ case OP_NOTI:
+ flag = "/i";
+ /* Fall through */
+ case OP_NOT:
+ fprintf(f, " %s [^", flag);
+ extra = print_char(f, code + 1, utf);
+ fprintf(f, "]");
+ break;
+
+ case OP_NOTSTARI:
+ case OP_NOTMINSTARI:
+ case OP_NOTPOSSTARI:
+ case OP_NOTPLUSI:
+ case OP_NOTMINPLUSI:
+ case OP_NOTPOSPLUSI:
+ case OP_NOTQUERYI:
+ case OP_NOTMINQUERYI:
+ case OP_NOTPOSQUERYI:
+ flag = "/i";
+ /* Fall through */
+
+ case OP_NOTSTAR:
+ case OP_NOTMINSTAR:
+ case OP_NOTPOSSTAR:
+ case OP_NOTPLUS:
+ case OP_NOTMINPLUS:
+ case OP_NOTPOSPLUS:
+ case OP_NOTQUERY:
+ case OP_NOTMINQUERY:
+ case OP_NOTPOSQUERY:
+ fprintf(f, " %s [^", flag);
+ extra = print_char(f, code + 1, utf);
+ fprintf(f, "]%s", OP_names[*code]);
+ break;
+
+ case OP_NOTEXACTI:
+ case OP_NOTUPTOI:
+ case OP_NOTMINUPTOI:
+ case OP_NOTPOSUPTOI:
+ flag = "/i";
+ /* Fall through */
+
+ case OP_NOTEXACT:
+ case OP_NOTUPTO:
+ case OP_NOTMINUPTO:
+ case OP_NOTPOSUPTO:
+ fprintf(f, " %s [^", flag);
+ extra = print_char(f, code + 1 + IMM2_SIZE, utf);
+ fprintf(f, "]{");
+ if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,");
+ fprintf(f, "%d}", GET2(code,1));
+ if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?");
+ else
+ if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+");
+ break;
+
+ case OP_RECURSE:
+ if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
+ else fprintf(f, " ");
+ fprintf(f, "%s", OP_names[*code]);
+ break;
+
+ case OP_REFI:
+ flag = "/i";
+ /* Fall through */
+ case OP_REF:
+ fprintf(f, " %s \\%d", flag, GET2(code,1));
+ ccode = code + OP_lengths[*code];
+ goto CLASS_REF_REPEAT;
+
+ case OP_DNREFI:
+ flag = "/i";
+ /* Fall through */
+ case OP_DNREF:
+ {
+ PCRE2_SPTR entry = nametable + (GET2(code, 1) * nesize) + IMM2_SIZE;
+ fprintf(f, " %s \\k<", flag);
+ print_custring(f, entry);
+ fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
+ }
+ ccode = code + OP_lengths[*code];
+ goto CLASS_REF_REPEAT;
+
+ case OP_CALLOUT:
+ fprintf(f, " %s %d %d %d", OP_names[*code], code[1 + 2*LINK_SIZE],
+ GET(code, 1), GET(code, 1 + LINK_SIZE));
+ break;
+
+ case OP_CALLOUT_STR:
+ c = code[1 + 4*LINK_SIZE];
+ fprintf(f, " %s %c", OP_names[*code], c);
+ extra = GET(code, 1 + 2*LINK_SIZE);
+ print_custring_bylen(f, code + 2 + 4*LINK_SIZE, extra - 3 - 4*LINK_SIZE);
+ for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)
+ if (c == PRIV(callout_start_delims)[i])
+ {
+ c = PRIV(callout_end_delims)[i];
+ break;
+ }
+ fprintf(f, "%c %d %d %d", c, GET(code, 1 + 3*LINK_SIZE), GET(code, 1),
+ GET(code, 1 + LINK_SIZE));
+ break;
+
+ case OP_PROP:
+ case OP_NOTPROP:
+ print_prop(f, code, " ", "");
+ break;
+
+ /* OP_XCLASS cannot occur in 8-bit, non-UTF mode. However, there's no harm
+ in having this code always here, and it makes it less messy without all
+ those #ifdefs. */
+
+ case OP_CLASS:
+ case OP_NCLASS:
+ case OP_XCLASS:
+ {
+ unsigned int min, max;
+ BOOL printmap;
+ BOOL invertmap = FALSE;
+ uint8_t *map;
+ uint8_t inverted_map[32];
+
+ fprintf(f, " [");
+
+ if (*code == OP_XCLASS)
+ {
+ extra = GET(code, 1);
+ ccode = code + LINK_SIZE + 1;
+ printmap = (*ccode & XCL_MAP) != 0;
+ if ((*ccode & XCL_NOT) != 0)
+ {
+ invertmap = (*ccode & XCL_HASPROP) == 0;
+ fprintf(f, "^");
+ }
+ ccode++;
+ }
+ else
+ {
+ printmap = TRUE;
+ ccode = code + 1;
+ }
+
+ /* Print a bit map */
+
+ if (printmap)
+ {
+ map = (uint8_t *)ccode;
+ if (invertmap)
+ {
+ for (i = 0; i < 32; i++) inverted_map[i] = ~map[i];
+ map = inverted_map;
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ if ((map[i/8] & (1 << (i&7))) != 0)
+ {
+ int j;
+ for (j = i+1; j < 256; j++)
+ if ((map[j/8] & (1 << (j&7))) == 0) break;
+ if (i == '-' || i == ']') fprintf(f, "\\");
+ if (PRINTABLE(i)) fprintf(f, "%c", i);
+ else fprintf(f, "\\x%02x", i);
+ if (--j > i)
+ {
+ if (j != i + 1) fprintf(f, "-");
+ if (j == '-' || j == ']') fprintf(f, "\\");
+ if (PRINTABLE(j)) fprintf(f, "%c", j);
+ else fprintf(f, "\\x%02x", j);
+ }
+ i = j;
+ }
+ }
+ ccode += 32 / sizeof(PCRE2_UCHAR);
+ }
+
+ /* For an XCLASS there is always some additional data */
+
+ if (*code == OP_XCLASS)
+ {
+ PCRE2_UCHAR ch;
+ while ((ch = *ccode++) != XCL_END)
+ {
+ BOOL not = FALSE;
+ const char *notch = "";
+
+ switch(ch)
+ {
+ case XCL_NOTPROP:
+ not = TRUE;
+ notch = "^";
+ /* Fall through */
+
+ case XCL_PROP:
+ {
+ unsigned int ptype = *ccode++;
+ unsigned int pvalue = *ccode++;
+
+ switch(ptype)
+ {
+ case PT_PXGRAPH:
+ fprintf(f, "[:%sgraph:]", notch);
+ break;
+
+ case PT_PXPRINT:
+ fprintf(f, "[:%sprint:]", notch);
+ break;
+
+ case PT_PXPUNCT:
+ fprintf(f, "[:%spunct:]", notch);
+ break;
+
+ default:
+ fprintf(f, "\\%c{%s}", (not? 'P':'p'),
+ get_ucpname(ptype, pvalue));
+ break;
+ }
+ }
+ break;
+
+ default:
+ ccode += 1 + print_char(f, ccode, utf);
+ if (ch == XCL_RANGE)
+ {
+ fprintf(f, "-");
+ ccode += 1 + print_char(f, ccode, utf);
+ }
+ break;
+ }
+ }
+ }
+
+ /* Indicate a non-UTF class which was created by negation */
+
+ fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : "");
+
+ /* Handle repeats after a class or a back reference */
+
+ CLASS_REF_REPEAT:
+ switch(*ccode)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRPLUS:
+ case OP_CRMINPLUS:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRPOSSTAR:
+ case OP_CRPOSPLUS:
+ case OP_CRPOSQUERY:
+ fprintf(f, "%s", OP_names[*ccode]);
+ extra += OP_lengths[*ccode];
+ break;
+
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSRANGE:
+ min = GET2(ccode,1);
+ max = GET2(ccode,1 + IMM2_SIZE);
+ if (max == 0) fprintf(f, "{%u,}", min);
+ else fprintf(f, "{%u,%u}", min, max);
+ if (*ccode == OP_CRMINRANGE) fprintf(f, "?");
+ else if (*ccode == OP_CRPOSRANGE) fprintf(f, "+");
+ extra += OP_lengths[*ccode];
+ break;
+
+ /* Do nothing if it's not a repeat; this code stops picky compilers
+ warning about the lack of a default code path. */
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case OP_MARK:
+ case OP_PRUNE_ARG:
+ case OP_SKIP_ARG:
+ case OP_THEN_ARG:
+ fprintf(f, " %s ", OP_names[*code]);
+ print_custring_bylen(f, code + 2, code[1]);
+ extra += code[1];
+ break;
+
+ case OP_THEN:
+ fprintf(f, " %s", OP_names[*code]);
+ break;
+
+ case OP_CIRCM:
+ case OP_DOLLM:
+ flag = "/m";
+ /* Fall through */
+
+ /* Anything else is just an item with no data, but possibly a flag. */
+
+ default:
+ fprintf(f, " %s %s", flag, OP_names[*code]);
+ break;
+ }
+
+ code += OP_lengths[*code] + extra;
+ fprintf(f, "\n");
+ }
+}
+
+/* End of pcre2_printint.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_serialize.c b/src/3rdparty/pcre2/src/pcre2_serialize.c
new file mode 100644
index 0000000000..0af26d8fc3
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_serialize.c
@@ -0,0 +1,265 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+/* This module contains functions for serializing and deserializing
+a sequence of compiled codes. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#include "pcre2_internal.h"
+
+/* Magic number to provide a small check against being handed junk. */
+
+#define SERIALIZED_DATA_MAGIC 0x50523253u
+
+/* Deserialization is limited to the current PCRE version and
+character width. */
+
+#define SERIALIZED_DATA_VERSION \
+ ((PCRE2_MAJOR) | ((PCRE2_MINOR) << 16))
+
+#define SERIALIZED_DATA_CONFIG \
+ (sizeof(PCRE2_UCHAR) | ((sizeof(void*)) << 8) | ((sizeof(PCRE2_SIZE)) << 16))
+
+
+
+/*************************************************
+* Serialize compiled patterns *
+*************************************************/
+
+PCRE2_EXP_DEFN int32_t PCRE2_CALL_CONVENTION
+pcre2_serialize_encode(const pcre2_code **codes, int32_t number_of_codes,
+ uint8_t **serialized_bytes, PCRE2_SIZE *serialized_size,
+ pcre2_general_context *gcontext)
+{
+uint8_t *bytes;
+uint8_t *dst_bytes;
+int32_t i;
+PCRE2_SIZE total_size;
+const pcre2_real_code *re;
+const uint8_t *tables;
+pcre2_serialized_data *data;
+
+const pcre2_memctl *memctl = (gcontext != NULL) ?
+ &gcontext->memctl : &PRIV(default_compile_context).memctl;
+
+if (codes == NULL || serialized_bytes == NULL || serialized_size == NULL)
+ return PCRE2_ERROR_NULL;
+
+if (number_of_codes <= 0) return PCRE2_ERROR_BADDATA;
+
+/* Compute total size. */
+total_size = sizeof(pcre2_serialized_data) + tables_length;
+tables = NULL;
+
+for (i = 0; i < number_of_codes; i++)
+ {
+ if (codes[i] == NULL) return PCRE2_ERROR_NULL;
+ re = (const pcre2_real_code *)(codes[i]);
+ if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;
+ if (tables == NULL)
+ tables = re->tables;
+ else if (tables != re->tables)
+ return PCRE2_ERROR_MIXEDTABLES;
+ total_size += re->blocksize;
+ }
+
+/* Initialize the byte stream. */
+bytes = memctl->malloc(total_size + sizeof(pcre2_memctl), memctl->memory_data);
+if (bytes == NULL) return PCRE2_ERROR_NOMEMORY;
+
+/* The controller is stored as a hidden parameter. */
+memcpy(bytes, memctl, sizeof(pcre2_memctl));
+bytes += sizeof(pcre2_memctl);
+
+data = (pcre2_serialized_data *)bytes;
+data->magic = SERIALIZED_DATA_MAGIC;
+data->version = SERIALIZED_DATA_VERSION;
+data->config = SERIALIZED_DATA_CONFIG;
+data->number_of_codes = number_of_codes;
+
+/* Copy all compiled code data. */
+dst_bytes = bytes + sizeof(pcre2_serialized_data);
+memcpy(dst_bytes, tables, tables_length);
+dst_bytes += tables_length;
+
+for (i = 0; i < number_of_codes; i++)
+ {
+ re = (const pcre2_real_code *)(codes[i]);
+ memcpy(dst_bytes, (char *)re, re->blocksize);
+ dst_bytes += re->blocksize;
+ }
+
+*serialized_bytes = bytes;
+*serialized_size = total_size;
+return number_of_codes;
+}
+
+
+/*************************************************
+* Deserialize compiled patterns *
+*************************************************/
+
+PCRE2_EXP_DEFN int32_t PCRE2_CALL_CONVENTION
+pcre2_serialize_decode(pcre2_code **codes, int32_t number_of_codes,
+ const uint8_t *bytes, pcre2_general_context *gcontext)
+{
+const pcre2_serialized_data *data = (const pcre2_serialized_data *)bytes;
+const pcre2_memctl *memctl = (gcontext != NULL) ?
+ &gcontext->memctl : &PRIV(default_compile_context).memctl;
+
+const uint8_t *src_bytes;
+pcre2_real_code *dst_re;
+uint8_t *tables;
+int32_t i, j;
+
+/* Sanity checks. */
+
+if (data == NULL || codes == NULL) return PCRE2_ERROR_NULL;
+if (number_of_codes <= 0) return PCRE2_ERROR_BADDATA;
+if (data->number_of_codes <= 0) return PCRE2_ERROR_BADSERIALIZEDDATA;
+if (data->magic != SERIALIZED_DATA_MAGIC) return PCRE2_ERROR_BADMAGIC;
+if (data->version != SERIALIZED_DATA_VERSION) return PCRE2_ERROR_BADMODE;
+if (data->config != SERIALIZED_DATA_CONFIG) return PCRE2_ERROR_BADMODE;
+
+if (number_of_codes > data->number_of_codes)
+ number_of_codes = data->number_of_codes;
+
+src_bytes = bytes + sizeof(pcre2_serialized_data);
+
+/* Decode tables. The reference count for the tables is stored immediately
+following them. */
+
+tables = memctl->malloc(tables_length + sizeof(PCRE2_SIZE), memctl->memory_data);
+if (tables == NULL) return PCRE2_ERROR_NOMEMORY;
+
+memcpy(tables, src_bytes, tables_length);
+*(PCRE2_SIZE *)(tables + tables_length) = number_of_codes;
+src_bytes += tables_length;
+
+/* Decode the byte stream. We must not try to read the size from the compiled
+code block in the stream, because it might be unaligned, which causes errors on
+hardware such as Sparc-64 that doesn't like unaligned memory accesses. The type
+of the blocksize field is given its own name to ensure that it is the same here
+as in the block. */
+
+for (i = 0; i < number_of_codes; i++)
+ {
+ CODE_BLOCKSIZE_TYPE blocksize;
+ memcpy(&blocksize, src_bytes + offsetof(pcre2_real_code, blocksize),
+ sizeof(CODE_BLOCKSIZE_TYPE));
+ if (blocksize <= sizeof(pcre2_real_code))
+ return PCRE2_ERROR_BADSERIALIZEDDATA;
+
+ /* The allocator provided by gcontext replaces the original one. */
+
+ dst_re = (pcre2_real_code *)PRIV(memctl_malloc)(blocksize,
+ (pcre2_memctl *)gcontext);
+ if (dst_re == NULL)
+ {
+ memctl->free(tables, memctl->memory_data);
+ for (j = 0; j < i; j++)
+ {
+ memctl->free(codes[j], memctl->memory_data);
+ codes[j] = NULL;
+ }
+ return PCRE2_ERROR_NOMEMORY;
+ }
+
+ /* The new allocator must be preserved. */
+
+ memcpy(((uint8_t *)dst_re) + sizeof(pcre2_memctl),
+ src_bytes + sizeof(pcre2_memctl), blocksize - sizeof(pcre2_memctl));
+ if (dst_re->magic_number != MAGIC_NUMBER ||
+ dst_re->name_entry_size > MAX_NAME_SIZE + IMM2_SIZE + 1 ||
+ dst_re->name_count > MAX_NAME_COUNT)
+ return PCRE2_ERROR_BADSERIALIZEDDATA;
+
+ /* At the moment only one table is supported. */
+
+ dst_re->tables = tables;
+ dst_re->executable_jit = NULL;
+ dst_re->flags |= PCRE2_DEREF_TABLES;
+
+ codes[i] = dst_re;
+ src_bytes += blocksize;
+ }
+
+return number_of_codes;
+}
+
+
+/*************************************************
+* Get the number of serialized patterns *
+*************************************************/
+
+PCRE2_EXP_DEFN int32_t PCRE2_CALL_CONVENTION
+pcre2_serialize_get_number_of_codes(const uint8_t *bytes)
+{
+const pcre2_serialized_data *data = (const pcre2_serialized_data *)bytes;
+
+if (data == NULL) return PCRE2_ERROR_NULL;
+if (data->magic != SERIALIZED_DATA_MAGIC) return PCRE2_ERROR_BADMAGIC;
+if (data->version != SERIALIZED_DATA_VERSION) return PCRE2_ERROR_BADMODE;
+if (data->config != SERIALIZED_DATA_CONFIG) return PCRE2_ERROR_BADMODE;
+
+return data->number_of_codes;
+}
+
+
+/*************************************************
+* Free the allocated stream *
+*************************************************/
+
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_serialize_free(uint8_t *bytes)
+{
+if (bytes != NULL)
+ {
+ pcre2_memctl *memctl = (pcre2_memctl *)(bytes - sizeof(pcre2_memctl));
+ memctl->free(memctl, memctl->memory_data);
+ }
+}
+
+/* End of pcre2_serialize.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_string_utils.c b/src/3rdparty/pcre2/src/pcre2_string_utils.c
new file mode 100644
index 0000000000..2a1f282629
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_string_utils.c
@@ -0,0 +1,201 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+/* This module contains internal functions for comparing and finding the length
+of strings. These are used instead of strcmp() etc because the standard
+functions work only on 8-bit data. */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre2_internal.h"
+
+
+/*************************************************
+* Compare two zero-terminated PCRE2 strings *
+*************************************************/
+
+/*
+Arguments:
+ str1 first string
+ str2 second string
+
+Returns: 0, 1, or -1
+*/
+
+int
+PRIV(strcmp)(PCRE2_SPTR str1, PCRE2_SPTR str2)
+{
+PCRE2_UCHAR c1, c2;
+while (*str1 != '\0' || *str2 != '\0')
+ {
+ c1 = *str1++;
+ c2 = *str2++;
+ if (c1 != c2) return ((c1 > c2) << 1) - 1;
+ }
+return 0;
+}
+
+
+/*************************************************
+* Compare zero-terminated PCRE2 & 8-bit strings *
+*************************************************/
+
+/* As the 8-bit string is almost always a literal, its type is specified as
+const char *.
+
+Arguments:
+ str1 first string
+ str2 second string
+
+Returns: 0, 1, or -1
+*/
+
+int
+PRIV(strcmp_c8)(PCRE2_SPTR str1, const char *str2)
+{
+PCRE2_UCHAR c1, c2;
+while (*str1 != '\0' || *str2 != '\0')
+ {
+ c1 = *str1++;
+ c2 = *str2++;
+ if (c1 != c2) return ((c1 > c2) << 1) - 1;
+ }
+return 0;
+}
+
+
+/*************************************************
+* Compare two PCRE2 strings, given a length *
+*************************************************/
+
+/*
+Arguments:
+ str1 first string
+ str2 second string
+ len the length
+
+Returns: 0, 1, or -1
+*/
+
+int
+PRIV(strncmp)(PCRE2_SPTR str1, PCRE2_SPTR str2, size_t len)
+{
+PCRE2_UCHAR c1, c2;
+for (; len > 0; len--)
+ {
+ c1 = *str1++;
+ c2 = *str2++;
+ if (c1 != c2) return ((c1 > c2) << 1) - 1;
+ }
+return 0;
+}
+
+
+/*************************************************
+* Compare PCRE2 string to 8-bit string by length *
+*************************************************/
+
+/* As the 8-bit string is almost always a literal, its type is specified as
+const char *.
+
+Arguments:
+ str1 first string
+ str2 second string
+ len the length
+
+Returns: 0, 1, or -1
+*/
+
+int
+PRIV(strncmp_c8)(PCRE2_SPTR str1, const char *str2, size_t len)
+{
+PCRE2_UCHAR c1, c2;
+for (; len > 0; len--)
+ {
+ c1 = *str1++;
+ c2 = *str2++;
+ if (c1 != c2) return ((c1 > c2) << 1) - 1;
+ }
+return 0;
+}
+
+
+/*************************************************
+* Find the length of a PCRE2 string *
+*************************************************/
+
+/*
+Argument: the string
+Returns: the length
+*/
+
+PCRE2_SIZE
+PRIV(strlen)(PCRE2_SPTR str)
+{
+PCRE2_SIZE c = 0;
+while (*str++ != 0) c++;
+return c;
+}
+
+
+/*************************************************
+* Copy 8-bit 0-terminated string to PCRE2 string *
+*************************************************/
+
+/* Arguments:
+ str1 buffer to receive the string
+ str2 8-bit string to be copied
+
+Returns: the number of code units used (excluding trailing zero)
+*/
+
+PCRE2_SIZE
+PRIV(strcpy_c8)(PCRE2_UCHAR *str1, const char *str2)
+{
+PCRE2_UCHAR *t = str1;
+while (*str2 != 0) *t++ = *str2++;
+*t = 0;
+return t - str1;
+}
+
+/* End of pcre2_string_utils.c */
diff --git a/src/3rdparty/pcre/pcre_study.c b/src/3rdparty/pcre2/src/pcre2_study.c
index d9d4960d84..db08266745 100644
--- a/src/3rdparty/pcre/pcre_study.c
+++ b/src/3rdparty/pcre2/src/pcre2_study.c
@@ -6,7 +6,8 @@
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
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -37,74 +38,95 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
-
-/* This module contains the external function pcre_study(), along with local
-supporting functions. */
+/* This module contains functions for scanning a compiled pattern and
+collecting data (e.g. minimum matching length). */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include "pcre_internal.h"
-#define SET_BIT(c) start_bits[c/8] |= (1 << (c&7))
+#include "pcre2_internal.h"
+
+
+/* Set a bit in the starting code unit bit map. */
+
+#define SET_BIT(c) re->start_bitmap[(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.
+string of that length that matches. In UTF mode, the result is in characters
+rather than code units. The field in a compiled pattern for storing the minimum
+length is 16-bits long (on the grounds that anything longer than that is
+pathological), so we give up when we reach that amount. This also means that
+integer overflow for really crazy patterns cannot happen.
Arguments:
re compiled pattern block
code pointer to start of group (the bracket)
startcode pointer to start of the whole pattern's code
- options the compiling options
+ utf UTF flag
recurses chain of recurse_check to catch mutual recursion
countptr pointer to call count (to catch over complexity)
Returns: the minimum length
- -1 if \C in UTF-8 mode or (*ACCEPT) was encountered
+ -1 \C in UTF-8 mode
+ or (*ACCEPT)
+ or pattern too complicated
+ or back reference to duplicate name/number
-2 internal error (missing capturing bracket)
-3 internal error (opcode not listed)
*/
static int
-find_minlength(const REAL_PCRE *re, const pcre_uchar *code,
- const pcre_uchar *startcode, int options, recurse_check *recurses,
- int *countptr)
+find_minlength(const pcre2_real_code *re, PCRE2_SPTR code,
+ PCRE2_SPTR startcode, BOOL utf, recurse_check *recurses, int *countptr)
{
int length = -1;
-/* PCRE_UTF16 has the same value as PCRE_UTF8. */
-BOOL utf = (options & PCRE_UTF8) != 0;
+int prev_cap_recno = -1;
+int prev_cap_d = 0;
+int prev_recurse_recno = -1;
+int prev_recurse_d = 0;
+uint32_t once_fudge = 0;
BOOL had_recurse = FALSE;
+BOOL dupcapused = (re->flags & PCRE2_DUPCAPUSED) != 0;
recurse_check this_recurse;
register int branchlength = 0;
-register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE;
+register PCRE2_UCHAR *cc = (PCRE2_UCHAR *)code + 1 + LINK_SIZE;
+
+/* If this is a "could be empty" group, its minimum length is 0. */
+
+if (*code >= OP_SBRA && *code <= OP_SCOND) return 0;
-if ((*countptr)++ > 1000) return -1; /* too complex */
+/* Skip over capturing bracket number */
-if (*code == OP_CBRA || *code == OP_SCBRA ||
- *code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE;
+if (*code == OP_CBRA || *code == OP_CBRAPOS) 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. */
+/* A large and/or complex regex can take too long to process. */
+
+if ((*countptr)++ > 1000) return -1;
+
+/* Scan along the opcodes for this branch. If we get to the end of the branch,
+check the length against that of the other branches. If the accumulated length
+passes 16-bits, stop. */
for (;;)
{
- int d, min;
- pcre_uchar *cs, *ce;
- register pcre_uchar op = *cc;
+ int d, min, recno;
+ PCRE2_UCHAR *cs, *ce;
+ register PCRE2_UCHAR op = *cc;
+
+ if (branchlength >= UINT16_MAX) return UINT16_MAX;
switch (op)
{
@@ -113,7 +135,8 @@ for (;;)
/* 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. */
+ automatically. If there are two branches we can treat it the same as any
+ other non-capturing subpattern. */
cs = cc + GET(cc, 1);
if (*cs != OP_ALT)
@@ -121,27 +144,56 @@ for (;;)
cc = cs + 1 + LINK_SIZE;
break;
}
+ goto PROCESS_NON_CAPTURE;
- /* Otherwise we can fall through and treat it the same as any other
- subpattern. */
+ /* There's a special case of OP_ONCE, when it is wrapped round an
+ OP_RECURSE. We'd like to process the latter at this level so that
+ remembering the value works for repeated cases. So we do nothing, but
+ set a fudge value to skip over the OP_KET after the recurse. */
- case OP_CBRA:
- case OP_SCBRA:
+ case OP_ONCE:
+ if (cc[1+LINK_SIZE] == OP_RECURSE && cc[2*(1+LINK_SIZE)] == OP_KET)
+ {
+ once_fudge = 1 + LINK_SIZE;
+ cc += 1 + LINK_SIZE;
+ break;
+ }
+ /* Fall through */
+
+ case OP_ONCE_NC:
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(re, cc, startcode, options, recurses, countptr);
+ PROCESS_NON_CAPTURE:
+ d = find_minlength(re, cc, startcode, utf, recurses, countptr);
if (d < 0) return d;
branchlength += d;
do cc += GET(cc, 1); while (*cc == OP_ALT);
cc += 1 + LINK_SIZE;
break;
+ /* To save time for repeated capturing subpatterns, we remember the
+ length of the previous one. Unfortunately we can't do the same for
+ the unnumbered ones above. Nor can we do this if (?| is present in the
+ pattern because captures with the same number are not then identical. */
+
+ case OP_CBRA:
+ case OP_SCBRA:
+ case OP_CBRAPOS:
+ case OP_SCBRAPOS:
+ recno = dupcapused? prev_cap_recno - 1 : (int)GET2(cc, 1+LINK_SIZE);
+ if (recno != prev_cap_recno)
+ {
+ prev_cap_recno = recno;
+ prev_cap_d = find_minlength(re, cc, startcode, utf, recurses, countptr);
+ if (prev_cap_d < 0) return prev_cap_d;
+ }
+ branchlength += prev_cap_d;
+ do cc += GET(cc, 1); while (*cc == OP_ALT);
+ cc += 1 + LINK_SIZE;
+ break;
+
/* ACCEPT makes things far too complicated; we have to give up. */
case OP_ACCEPT:
@@ -184,7 +236,8 @@ for (;;)
case OP_DNCREF:
case OP_RREF:
case OP_DNRREF:
- case OP_DEF:
+ case OP_FALSE:
+ case OP_TRUE:
case OP_CALLOUT:
case OP_SOD:
case OP_SOM:
@@ -199,6 +252,10 @@ for (;;)
cc += PRIV(OP_lengths)[*cc];
break;
+ case OP_CALLOUT_STR:
+ cc += GET(cc, 1 + 2*LINK_SIZE);
+ break;
+
/* Skip over a subpattern that has a {0} or {0,x} quantifier */
case OP_BRAZERO:
@@ -230,7 +287,7 @@ for (;;)
case OP_NOTPOSPLUSI:
branchlength++;
cc += 2;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
break;
@@ -243,7 +300,7 @@ for (;;)
break;
/* Handle exact repetitions. The count is already in characters, but we
- need to skip over a multibyte character in UTF8 mode. */
+ may need to skip over a multibyte character in UTF mode. */
case OP_EXACT:
case OP_EXACTI:
@@ -251,7 +308,7 @@ for (;;)
case OP_NOTEXACTI:
branchlength += GET2(cc,1);
cc += 2 + IMM2_SIZE;
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
break;
@@ -294,12 +351,12 @@ for (;;)
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
+ /* The single-byte matcher means we can't proceed in UTF mode. (In
+ non-UTF mode \C will actually be turned into OP_ALLANY, so won't ever
appear, but leave the code, just in case.) */
case OP_ANYBYTE:
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf) return -1;
#endif
branchlength++;
@@ -331,7 +388,7 @@ for (;;)
case OP_CLASS:
case OP_NCLASS:
-#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
+#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
/* The original code caused an unsigned overflow in 64 bit systems,
so now we use a conditional statement. */
@@ -373,32 +430,40 @@ for (;;)
}
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.
+ /* Backreferences and subroutine calls (OP_RECURSE) are treated in the same
+ way: we find the minimum length for the subpattern. A recursion
+ (backreference or subroutine) causes an a flag to be set that causes the
+ length of this branch to be ignored. The logic is that a recursion can only
+ make sense if there is another alternative that stops the recursing. That
+ will provide the minimum length (when no recursion happens).
- If PCRE_JAVASCRIPT_COMPAT is set, a backreference to an unset bracket
+ If PCRE2_MATCH_UNSET_BACKREF is set, a backreference to an unset bracket
matches an empty string (by default it causes a matching failure), so in
that case we must set the minimum length to zero. */
- case OP_DNREF: /* Duplicate named pattern back reference */
+ /* Duplicate named pattern back reference. We cannot reliably find a length
+ for this if duplicate numbers are present in the pattern. */
+
+ case OP_DNREF:
case OP_DNREFI:
- if ((options & PCRE_JAVASCRIPT_COMPAT) == 0)
+ if (dupcapused) return -1;
+ if ((re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)
{
int count = GET2(cc, 1+IMM2_SIZE);
- pcre_uchar *slot = (pcre_uchar *)re +
- re->name_table_offset + GET2(cc, 1) * re->name_entry_size;
+ PCRE2_UCHAR *slot =
+ (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) +
+ GET2(cc, 1) * re->name_entry_size;
+
d = INT_MAX;
+
+ /* Scan all groups with the same name */
+
while (count-- > 0)
{
- ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(slot, 0));
+ ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, GET2(slot, 0));
if (cs == NULL) return -2;
do ce += GET(ce, 1); while (*ce == OP_ALT);
- if (cc > cs && cc < ce) /* Simple recursion */
+ if (cc > cs && cc < ce) /* Simple recursion */
{
d = 0;
had_recurse = TRUE;
@@ -419,8 +484,7 @@ for (;;)
int dd;
this_recurse.prev = recurses;
this_recurse.group = cs;
- dd = find_minlength(re, cs, startcode, options, &this_recurse,
- countptr);
+ dd = find_minlength(re, cs, startcode, utf, &this_recurse, countptr);
if (dd < d) d = dd;
}
}
@@ -431,11 +495,15 @@ for (;;)
cc += 1 + 2*IMM2_SIZE;
goto REPEAT_BACK_REFERENCE;
- case OP_REF: /* Single back reference */
+ /* Single back reference. We cannot find a length for this if duplicate
+ numbers are present in the pattern. */
+
+ case OP_REF:
case OP_REFI:
- if ((options & PCRE_JAVASCRIPT_COMPAT) == 0)
+ if (dupcapused) return -1;
+ if ((re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)
{
- ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(cc, 1));
+ ce = cs = (PCRE2_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) /* Simple recursion */
@@ -456,8 +524,7 @@ for (;;)
{
this_recurse.prev = recurses;
this_recurse.group = cs;
- d = find_minlength(re, cs, startcode, options, &this_recurse,
- countptr);
+ d = find_minlength(re, cs, startcode, utf, &this_recurse, countptr);
}
}
}
@@ -498,32 +565,51 @@ for (;;)
break;
}
- branchlength += min * d;
+ /* Take care not to overflow: (1) min and d are ints, so check that their
+ product is not greater than INT_MAX. (2) branchlength is limited to
+ UINT16_MAX (checked at the top of the loop). */
+
+ if ((d > 0 && (INT_MAX/d) < min) || UINT16_MAX - branchlength < min*d)
+ branchlength = UINT16_MAX;
+ else branchlength += min * d;
break;
- /* We can easily detect direct recursion, but not mutual recursion. This is
- caught by a recursion depth count. */
+ /* Recursion always refers to the first occurrence of a subpattern with a
+ given number. Therefore, we can always make use of caching, even when the
+ pattern contains multiple subpatterns with the same number. */
case OP_RECURSE:
- cs = ce = (pcre_uchar *)startcode + GET(cc, 1);
- do ce += GET(ce, 1); while (*ce == OP_ALT);
- if (cc > cs && cc < ce) /* Simple recursion */
- had_recurse = TRUE;
+ cs = ce = (PCRE2_UCHAR *)startcode + GET(cc, 1);
+ recno = GET2(cs, 1+LINK_SIZE);
+ if (recno == prev_recurse_recno)
+ {
+ branchlength += prev_recurse_d;
+ }
else
{
- recurse_check *r = recurses;
- for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
- if (r != NULL) /* Mutual recursion */
+ do ce += GET(ce, 1); while (*ce == OP_ALT);
+ if (cc > cs && cc < ce) /* Simple recursion */
had_recurse = TRUE;
else
{
- this_recurse.prev = recurses;
- this_recurse.group = cs;
- branchlength += find_minlength(re, cs, startcode, options,
- &this_recurse, countptr);
+ recurse_check *r = recurses;
+ for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
+ if (r != NULL) /* Mutual recursion */
+ had_recurse = TRUE;
+ else
+ {
+ this_recurse.prev = recurses;
+ this_recurse.group = cs;
+ prev_recurse_d = find_minlength(re, cs, startcode, utf, &this_recurse,
+ countptr);
+ if (prev_recurse_d < 0) return prev_recurse_d;
+ prev_recurse_recno = recno;
+ branchlength += prev_recurse_d;
+ }
}
}
- cc += 1 + LINK_SIZE;
+ cc += 1 + LINK_SIZE + once_fudge;
+ once_fudge = 0;
break;
/* Anything else does not or need not match a character. We can get the
@@ -574,7 +660,7 @@ for (;;)
case OP_NOTPOSQUERYI:
cc += PRIV(OP_lengths)[op];
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
#endif
break;
@@ -616,85 +702,70 @@ for (;;)
* 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.
+/* Given a character, set its first code unit's bit in the table, and also the
+corresponding bit for the other version of a letter if we are caseless.
Arguments:
- 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 / UTF-32 mode
+ re points to the regex block
+ p points to the first code unit of the character
+ caseless TRUE if caseless
+ utf TRUE for UTF mode
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)
+static PCRE2_SPTR
+set_table_bit(pcre2_real_code *re, PCRE2_SPTR p, BOOL caseless, BOOL utf)
{
-pcre_uint32 c = *p;
+uint32_t c = *p++; /* First code unit */
+(void)utf; /* Stop compiler warning when UTF not supported */
-#ifdef COMPILE_PCRE8
-SET_BIT(c);
+/* In 16-bit and 32-bit modes, code units greater than 0xff set the bit for
+0xff. */
-#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 /* Not SUPPORT_UCP */
- return p;
- }
-#else /* Not SUPPORT_UTF */
-(void)(utf); /* Stops warning for unused parameter */
-#endif /* SUPPORT_UTF */
+#if PCRE2_CODE_UNIT_WIDTH != 8
+if (c > 0xff) SET_BIT(0xff); else
+#endif
-/* Not UTF-8 mode, or character is less than 127. */
+SET_BIT(c);
-if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
-return p + 1;
-#endif /* COMPILE_PCRE8 */
+/* In UTF-8 or UTF-16 mode, pick up the remaining code units in order to find
+the end of the character, even when caseless. */
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
-if (c > 0xff)
+#ifdef SUPPORT_UNICODE
+if (utf)
{
- c = 0xff;
- caseless = FALSE;
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (c >= 0xc0) GETUTF8INC(c, p);
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+ if ((c & 0xfc00) == 0xd800) GETUTF16INC(c, p);
+#endif
}
-SET_BIT(c);
+#endif /* SUPPORT_UNICODE */
-#ifdef SUPPORT_UTF
-if (utf && c > 127)
+/* If caseless, handle the other case of the character. */
+
+if (caseless)
{
- GETCHARINC(c, p);
-#ifdef SUPPORT_UCP
- if (caseless)
+ if (utf)
{
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ PCRE2_UCHAR buff[6];
c = UCD_OTHERCASE(c);
- if (c > 0xff)
- c = 0xff;
- SET_BIT(c);
+ (void)PRIV(ord2utf)(c, buff);
+ SET_BIT(buff[0]);
+#else /* 16-bit or 32-bit mode */
+ c = UCD_OTHERCASE(c);
+ if (c > 0xff) SET_BIT(0xff); else SET_BIT(c);
+#endif
}
-#endif /* SUPPORT_UCP */
- return p;
+
+ /* Not UTF */
+
+ else if (MAX_255(c)) SET_BIT(re->tables[fcc_offset + c]);
}
-#else /* Not SUPPORT_UTF */
-(void)(utf); /* Stops warning for unused parameter */
-#endif /* SUPPORT_UTF */
-if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
-return p + 1;
-#endif
+return p;
}
@@ -711,32 +782,31 @@ 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
+ re the regex block
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, unsigned int table_limit,
- compile_data *cd)
+set_type_bits(pcre2_real_code *re, int cbit_type, unsigned int table_limit)
{
-register pcre_uint32 c;
-for (c = 0; c < table_limit; c++) start_bits[c] |= cd->cbits[c+cbit_type];
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+register uint32_t c;
+for (c = 0; c < table_limit; c++)
+ re->start_bitmap[c] |= re->tables[c+cbits_offset+cbit_type];
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (table_limit == 32) return;
for (c = 128; c < 256; c++)
{
- if ((cd->cbits[c/8] & (1 << (c&7))) != 0)
+ if ((re->tables[cbits_offset + c/8] & (1 << (c&7))) != 0)
{
- pcre_uchar buff[6];
+ PCRE2_UCHAR buff[6];
(void)PRIV(ord2utf)(c, buff);
SET_BIT(buff[0]);
}
}
-#endif
+#endif /* UTF-8 */
}
@@ -753,22 +823,21 @@ all high-valued characters. The lowest is 0xc2, but we overkill by starting at
0xc0 (192) for simplicity.
Arguments:
- start_bits the starting bitmap
+ re the regex block
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, unsigned int table_limit,
- compile_data *cd)
+set_nottype_bits(pcre2_real_code *re, int cbit_type, unsigned int table_limit)
{
-register pcre_uint32 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;
+register uint32_t c;
+for (c = 0; c < table_limit; c++)
+ re->start_bitmap[c] |= ~(re->tables[c+cbits_offset+cbit_type]);
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
+if (table_limit != 32) for (c = 24; c < 32; c++) re->start_bitmap[c] = 0xff;
#endif
}
@@ -779,58 +848,44 @@ if (table_limit != 32) for (c = 24; c < 32; c++) start_bits[c] = 0xff;
*************************************************/
/* 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.
+attempts to build a bitmap of the set of possible starting code units whose
+values are less than 256. In 16-bit and 32-bit mode, values above 255 all cause
+the 255 bit to be set. When calling set[_not]_type_bits() in UTF-8 (sic) mode
+we pass a value of 16 rather than 32 as the final argument. (See comments in
+those functions for the reason.)
+
+The SSB_CONTINUE return is useful for parenthesized groups in patterns such as
+(a*)b where the group provides some optional starting code units but scanning
+must continue at the outer level to find at least one mandatory code unit. At
+the outermost level, this function fails unless the result is SSB_DONE.
Arguments:
+ re points to the compiled regex block
code points to an expression
- start_bits points to a 32-byte table, initialized to 0
- utf TRUE if in UTF-8 / UTF-16 / UTF-32 mode
- cd the block with char table pointers
+ utf TRUE if in UTF mode
-Returns: SSB_FAIL => Failed to find any starting bytes
- SSB_DONE => Found mandatory starting bytes
- SSB_CONTINUE => Found optional starting bytes
+Returns: SSB_FAIL => Failed to find any starting code units
+ SSB_DONE => Found mandatory starting code units
+ SSB_CONTINUE => Found optional starting code units
SSB_UNKNOWN => Hit an unrecognized opcode
*/
static int
-set_start_bits(const pcre_uchar *code, pcre_uint8 *start_bits, BOOL utf,
- compile_data *cd)
+set_start_bits(pcre2_real_code *re, PCRE2_SPTR code, BOOL utf)
{
-register pcre_uint32 c;
+register uint32_t c;
int yield = SSB_DONE;
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
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;
+ PCRE2_SPTR tcode = code + 1 + LINK_SIZE;
if (*code == OP_CBRA || *code == OP_SCBRA ||
*code == OP_CBRAPOS || *code == OP_SCBRAPOS) tcode += IMM2_SIZE;
@@ -838,12 +893,13 @@ do
while (try_next) /* Loop for items in this branch */
{
int rc;
+ uint8_t *classmap = NULL;
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. */
+ been created that hasn't been added to this function. Hopefully this
+ problem will be discovered during testing. */
default:
return SSB_UNKNOWN;
@@ -861,7 +917,8 @@ do
case OP_COMMIT:
case OP_COND:
case OP_CREF:
- case OP_DEF:
+ case OP_FALSE:
+ case OP_TRUE:
case OP_DNCREF:
case OP_DNREF:
case OP_DNREFI:
@@ -930,13 +987,13 @@ do
case OP_PROP:
if (tcode[1] != PT_CLIST) return SSB_FAIL;
{
- const pcre_uint32 *p = PRIV(ucd_caseless_sets) + tcode[2];
+ const uint32_t *p = PRIV(ucd_caseless_sets) + tcode[2];
while ((c = *p++) < NOTACHAR)
{
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (utf)
{
- pcre_uchar buff[6];
+ PCRE2_UCHAR buff[6];
(void)PRIV(ord2utf)(c, buff);
c = buff[0];
}
@@ -970,7 +1027,7 @@ do
case OP_ONCE:
case OP_ONCE_NC:
case OP_ASSERT:
- rc = set_start_bits(tcode, start_bits, utf, cd);
+ rc = set_start_bits(re, tcode, utf);
if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc;
if (rc == SSB_DONE) try_next = FALSE; else
{
@@ -1000,7 +1057,11 @@ do
/* Skip over callout */
case OP_CALLOUT:
- tcode += 2 + 2*LINK_SIZE;
+ tcode += PRIV(OP_lengths)[OP_CALLOUT];
+ break;
+
+ case OP_CALLOUT_STR:
+ tcode += GET(tcode, 1 + 2*LINK_SIZE);
break;
/* Skip over lookbehind and negative lookahead assertions */
@@ -1017,13 +1078,8 @@ do
case OP_BRAZERO:
case OP_BRAMINZERO:
case OP_BRAPOSZERO:
- rc = set_start_bits(++tcode, start_bits, utf, cd);
+ rc = set_start_bits(re, ++tcode, utf);
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;
@@ -1044,7 +1100,7 @@ do
case OP_QUERY:
case OP_MINQUERY:
case OP_POSQUERY:
- tcode = set_table_bit(start_bits, tcode + 1, FALSE, cd, utf);
+ tcode = set_table_bit(re, tcode + 1, FALSE, utf);
break;
case OP_STARI:
@@ -1053,7 +1109,7 @@ do
case OP_QUERYI:
case OP_MINQUERYI:
case OP_POSQUERYI:
- tcode = set_table_bit(start_bits, tcode + 1, TRUE, cd, utf);
+ tcode = set_table_bit(re, tcode + 1, TRUE, utf);
break;
/* Single-char upto sets the bit and tries the next */
@@ -1061,13 +1117,13 @@ do
case OP_UPTO:
case OP_MINUPTO:
case OP_POSUPTO:
- tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, FALSE, cd, utf);
+ tcode = set_table_bit(re, tcode + 1 + IMM2_SIZE, FALSE, utf);
break;
case OP_UPTOI:
case OP_MINUPTOI:
case OP_POSUPTOI:
- tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, TRUE, cd, utf);
+ tcode = set_table_bit(re, tcode + 1 + IMM2_SIZE, TRUE, utf);
break;
/* At least one single char sets the bit and stops */
@@ -1079,7 +1135,7 @@ do
case OP_PLUS:
case OP_MINPLUS:
case OP_POSPLUS:
- (void)set_table_bit(start_bits, tcode + 1, FALSE, cd, utf);
+ (void)set_table_bit(re, tcode + 1, FALSE, utf);
try_next = FALSE;
break;
@@ -1090,7 +1146,7 @@ do
case OP_PLUSI:
case OP_MINPLUSI:
case OP_POSPLUSI:
- (void)set_table_bit(start_bits, tcode + 1, TRUE, cd, utf);
+ (void)set_table_bit(re, tcode + 1, TRUE, utf);
try_next = FALSE;
break;
@@ -1103,29 +1159,36 @@ do
case OP_HSPACE:
SET_BIT(CHAR_HT);
SET_BIT(CHAR_SPACE);
-#ifdef SUPPORT_UTF
+
+ /* For the 16-bit and 32-bit libraries (which can never be EBCDIC), set
+ the bits for 0xA0 and for code units >= 255, independently of UTF. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ SET_BIT(0xA0);
+ SET_BIT(0xFF);
+#else
+ /* For the 8-bit library in UTF-8 mode, set the bits for the first code
+ units of horizontal space characters. */
+
+#ifdef SUPPORT_UNICODE
if (utf)
{
-#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 */
-#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
- SET_BIT(0xA0);
- SET_BIT(0xFF); /* For characters > 255 */
-#endif /* COMPILE_PCRE[8|16|32] */
}
else
-#endif /* SUPPORT_UTF */
+#endif
+ /* For the 8-bit library not in UTF-8 mode, set the bit for 0xA0, unless
+ the code is EBCDIC. */
{
#ifndef EBCDIC
SET_BIT(0xA0);
#endif /* Not EBCDIC */
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
- SET_BIT(0xFF); /* For characters > 255 */
-#endif /* COMPILE_PCRE[16|32] */
}
+#endif /* 8-bit support */
+
try_next = FALSE;
break;
@@ -1135,64 +1198,66 @@ do
SET_BIT(CHAR_VT);
SET_BIT(CHAR_FF);
SET_BIT(CHAR_CR);
-#ifdef SUPPORT_UTF
+
+ /* For the 16-bit and 32-bit libraries (which can never be EBCDIC), set
+ the bits for NEL and for code units >= 255, independently of UTF. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ SET_BIT(CHAR_NEL);
+ SET_BIT(0xFF);
+#else
+ /* For the 8-bit library in UTF-8 mode, set the bits for the first code
+ units of vertical space characters. */
+
+#ifdef SUPPORT_UNICODE
if (utf)
{
-#ifdef COMPILE_PCRE8
- SET_BIT(0xC2); /* For U+0085 */
+ SET_BIT(0xC2); /* For U+0085 (NEL) */
SET_BIT(0xE2); /* For U+2028, U+2029 */
-#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
- SET_BIT(CHAR_NEL);
- SET_BIT(0xFF); /* For characters > 255 */
-#endif /* COMPILE_PCRE[8|16|32] */
}
else
-#endif /* SUPPORT_UTF */
+#endif
+ /* For the 8-bit library not in UTF-8 mode, set the bit for NEL. */
{
SET_BIT(CHAR_NEL);
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
- SET_BIT(0xFF); /* For characters > 255 */
-#endif
}
+#endif /* 8-bit support */
+
try_next = FALSE;
break;
- /* Single character types set the bits and stop. Note that if PCRE_UCP
+ /* Single character types set the bits and stop. Note that if PCRE2_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);
+ set_nottype_bits(re, cbit_digit, table_limit);
try_next = FALSE;
break;
case OP_DIGIT:
- set_type_bits(start_bits, cbit_digit, table_limit, cd);
+ set_type_bits(re, cbit_digit, table_limit);
try_next = FALSE;
break;
- /* The cbit_space table has vertical tab as whitespace; we no longer
- have to play fancy tricks because Perl added VT to its whitespace at
- release 5.18. PCRE added it at release 8.34. */
-
case OP_NOT_WHITESPACE:
- set_nottype_bits(start_bits, cbit_space, table_limit, cd);
+ set_nottype_bits(re, cbit_space, table_limit);
try_next = FALSE;
break;
case OP_WHITESPACE:
- set_type_bits(start_bits, cbit_space, table_limit, cd);
+ set_type_bits(re, cbit_space, table_limit);
try_next = FALSE;
break;
case OP_NOT_WORDCHAR:
- set_nottype_bits(start_bits, cbit_word, table_limit, cd);
+ set_nottype_bits(re, cbit_word, table_limit);
try_next = FALSE;
break;
case OP_WORDCHAR:
- set_type_bits(start_bits, cbit_word, table_limit, cd);
+ set_type_bits(re, cbit_word, table_limit);
try_next = FALSE;
break;
@@ -1233,24 +1298,35 @@ do
case OP_HSPACE:
SET_BIT(CHAR_HT);
SET_BIT(CHAR_SPACE);
-#ifdef SUPPORT_UTF
+
+ /* For the 16-bit and 32-bit libraries (which can never be EBCDIC), set
+ the bits for 0xA0 and for code units >= 255, independently of UTF. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ SET_BIT(0xA0);
+ SET_BIT(0xFF);
+#else
+ /* For the 8-bit library in UTF-8 mode, set the bits for the first code
+ units of horizontal space characters. */
+
+#ifdef SUPPORT_UNICODE
if (utf)
{
-#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 */
-#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
- SET_BIT(0xA0);
- SET_BIT(0xFF); /* For characters > 255 */
-#endif /* COMPILE_PCRE[8|16|32] */
}
else
-#endif /* SUPPORT_UTF */
+#endif
+ /* For the 8-bit library not in UTF-8 mode, set the bit for 0xA0, unless
+ the code is EBCDIC. */
+ {
#ifndef EBCDIC
SET_BIT(0xA0);
#endif /* Not EBCDIC */
+ }
+#endif /* 8-bit support */
break;
case OP_ANYNL:
@@ -1259,428 +1335,241 @@ do
SET_BIT(CHAR_VT);
SET_BIT(CHAR_FF);
SET_BIT(CHAR_CR);
-#ifdef SUPPORT_UTF
+
+ /* For the 16-bit and 32-bit libraries (which can never be EBCDIC), set
+ the bits for NEL and for code units >= 255, independently of UTF. */
+
+#if PCRE2_CODE_UNIT_WIDTH != 8
+ SET_BIT(CHAR_NEL);
+ SET_BIT(0xFF);
+#else
+ /* For the 8-bit library in UTF-8 mode, set the bits for the first code
+ units of vertical space characters. */
+
+#ifdef SUPPORT_UNICODE
if (utf)
{
-#ifdef COMPILE_PCRE8
- SET_BIT(0xC2); /* For U+0085 */
+ SET_BIT(0xC2); /* For U+0085 (NEL) */
SET_BIT(0xE2); /* For U+2028, U+2029 */
-#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
- SET_BIT(CHAR_NEL);
- SET_BIT(0xFF); /* For characters > 255 */
-#endif /* COMPILE_PCRE16 */
}
else
-#endif /* SUPPORT_UTF */
+#endif
+ /* For the 8-bit library not in UTF-8 mode, set the bit for NEL. */
+ {
SET_BIT(CHAR_NEL);
+ }
+#endif /* 8-bit support */
break;
case OP_NOT_DIGIT:
- set_nottype_bits(start_bits, cbit_digit, table_limit, cd);
+ set_nottype_bits(re, cbit_digit, table_limit);
break;
case OP_DIGIT:
- set_type_bits(start_bits, cbit_digit, table_limit, cd);
+ set_type_bits(re, cbit_digit, table_limit);
break;
- /* The cbit_space table has vertical tab as whitespace; we no longer
- have to play fancy tricks because Perl added VT to its whitespace at
- release 5.18. PCRE added it at release 8.34. */
-
case OP_NOT_WHITESPACE:
- set_nottype_bits(start_bits, cbit_space, table_limit, cd);
+ set_nottype_bits(re, cbit_space, table_limit);
break;
case OP_WHITESPACE:
- set_type_bits(start_bits, cbit_space, table_limit, cd);
+ set_type_bits(re, cbit_space, table_limit);
break;
case OP_NOT_WORDCHAR:
- set_nottype_bits(start_bits, cbit_word, table_limit, cd);
+ set_nottype_bits(re, cbit_word, table_limit);
break;
case OP_WORDCHAR:
- set_type_bits(start_bits, cbit_word, table_limit, cd);
+ set_type_bits(re, cbit_word, table_limit);
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. */
+ /* Extended class: if there are any property checks, or if this is a
+ negative XCLASS without a map, give up. If there are no property checks,
+ there must be wide characters on the XCLASS list, because otherwise an
+ XCLASS would not have been created. This means that code points >= 255
+ are always potential starters. */
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
+#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
- if ((tcode[1 + LINK_SIZE] & XCL_HASPROP) != 0)
- return SSB_FAIL;
- /* All bits are set. */
- if ((tcode[1 + LINK_SIZE] & XCL_MAP) == 0 && (tcode[1 + LINK_SIZE] & XCL_NOT) != 0)
+ if ((tcode[1 + LINK_SIZE] & XCL_HASPROP) != 0 ||
+ (tcode[1 + LINK_SIZE] & (XCL_MAP|XCL_NOT)) == XCL_NOT)
return SSB_FAIL;
+
+ /* We have a positive XCLASS or a negative one without a map. Set up the
+ map pointer if there is one, and fall through. */
+
+ classmap = ((tcode[1 + LINK_SIZE] & XCL_MAP) == 0)? NULL :
+ (uint8_t *)(tcode + 1 + LINK_SIZE + 1);
#endif
- /* Fall through */
+
+ /* Enter here for a negative non-XCLASS. In the 8-bit library, if we are
+ in UTF mode, any byte with a value >= 0xc4 is a potentially valid starter
+ because it starts a character with a value > 255. In 8-bit non-UTF mode,
+ there is no difference between CLASS and NCLASS. In all other wide
+ character modes, set the 0xFF bit to indicate code units >= 255. */
case OP_NCLASS:
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (utf)
{
- start_bits[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */
- memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */
+ re->start_bitmap[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */
+ memset(re->start_bitmap+25, 0xff, 7); /* Bits for 0xc9 - 0xff */
}
-#endif
-#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
- SET_BIT(0xFF); /* For characters > 255 */
+#elif PCRE2_CODE_UNIT_WIDTH != 8
+ SET_BIT(0xFF); /* For characters >= 255 */
#endif
/* Fall through */
+ /* Enter here for a positive non-XCLASS. If we have fallen through from
+ an XCLASS, classmap will already be set; just advance the code pointer.
+ Otherwise, set up classmap for a a non-XCLASS and advance past it. */
+
case OP_CLASS:
+ if (*tcode == OP_XCLASS) tcode += GET(tcode, 1); else
{
- pcre_uint8 *map;
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
- map = NULL;
- if (*tcode == OP_XCLASS)
- {
- if ((tcode[1 + LINK_SIZE] & XCL_MAP) != 0)
- map = (pcre_uint8 *)(tcode + 1 + LINK_SIZE + 1);
- tcode += GET(tcode, 1);
- }
- else
-#endif
- {
- tcode++;
- map = (pcre_uint8 *)tcode;
- tcode += 32 / sizeof(pcre_uchar);
- }
+ classmap = (uint8_t *)(++tcode);
+ tcode += 32 / sizeof(PCRE2_UCHAR);
+ }
- /* 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. */
+ /* When wide characters are supported, classmap may be NULL. In UTF-8
+ (sic) mode, the bits in a class bit map correspond to character values,
+ not to byte values. However, the bit map we are constructing is for byte
+ values. So we have to do a conversion for characters whose code point is
+ greater than 127. In fact, there are only two possible starting bytes for
+ characters in the range 128 - 255. */
-#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
- if (map != NULL)
-#endif
+ if (classmap != NULL)
+ {
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
+ if (utf)
{
-#if defined SUPPORT_UTF && defined COMPILE_PCRE8
- if (utf)
+ for (c = 0; c < 16; c++) re->start_bitmap[c] |= classmap[c];
+ for (c = 128; c < 256; c++)
{
- for (c = 0; c < 16; c++) start_bits[c] |= map[c];
- for (c = 128; c < 256; c++)
+ if ((classmap[c/8] & (1 << (c&7))) != 0)
{
- 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. */
- }
+ int d = (c >> 6) | 0xc0; /* Set bit for this starter */
+ re->start_bitmap[d/8] |= (1 << (d&7)); /* and then skip on to the */
+ c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */
}
}
- else
+ }
+ 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];
- }
+ /* In all modes except UTF-8, the two bit maps are compatible. */
+
+ {
+ for (c = 0; c < 32; c++) re->start_bitmap[c] |= classmap[c];
}
+ }
- /* Advance past the bit map, and act on what follows. For a zero
- minimum repeat, continue; otherwise stop processing. */
+ /* Act on what follows the class. For a zero minimum repeat, continue;
+ otherwise stop processing. */
- switch (*tcode)
- {
- case OP_CRSTAR:
- case OP_CRMINSTAR:
- case OP_CRQUERY:
- case OP_CRMINQUERY:
- case OP_CRPOSSTAR:
- case OP_CRPOSQUERY:
- tcode++;
- break;
+ switch (*tcode)
+ {
+ case OP_CRSTAR:
+ case OP_CRMINSTAR:
+ case OP_CRQUERY:
+ case OP_CRMINQUERY:
+ case OP_CRPOSSTAR:
+ case OP_CRPOSQUERY:
+ tcode++;
+ break;
- case OP_CRRANGE:
- case OP_CRMINRANGE:
- case OP_CRPOSRANGE:
- if (GET2(tcode, 1) == 0) tcode += 1 + 2 * IMM2_SIZE;
- else try_next = FALSE;
- break;
+ case OP_CRRANGE:
+ case OP_CRMINRANGE:
+ case OP_CRPOSRANGE:
+ if (GET2(tcode, 1) == 0) tcode += 1 + 2 * IMM2_SIZE;
+ else try_next = FALSE;
+ break;
- default:
- try_next = FALSE;
- break;
- }
+ default:
+ try_next = FALSE;
+ break;
}
- break; /* End of bitmap class handling */
-
- } /* End of switch */
+ break; /* End of class handling case */
+ } /* End of switch for opcodes */
} /* End of try_next loop */
code += GET(code, 1); /* Advance to next branch */
}
while (*code == OP_ALT);
+
return yield;
}
-
-
/*************************************************
* Study a compiled expression *
*************************************************/
/* This function is handed a compiled expression that it must study to produce
-information that will speed up the matching. It returns a pcre[16]_extra block
-which then gets handed back to pcre_exec().
+information that will speed up the matching.
-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
+Argument: points to the compiled expression
+Returns: 0 normally; non-zero should never normally occur
+ 1 unknown opcode in set_start_bits
+ 2 missing capturing bracket
+ 3 unknown opcode in find_minlength
*/
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN pcre_extra * PCRE_CALL_CONVENTION
-pcre_study(const pcre *external_re, int options, const char **errorptr)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN pcre16_extra * PCRE_CALL_CONVENTION
-pcre16_study(const pcre16 *external_re, int options, const char **errorptr)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN pcre32_extra * PCRE_CALL_CONVENTION
-pcre32_study(const pcre32 *external_re, int options, const char **errorptr)
-#endif
+int
+PRIV(study)(pcre2_real_code *re)
{
int min;
int count = 0;
-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;
+PCRE2_UCHAR *code;
+BOOL utf = (re->overall_options & PCRE2_UTF) != 0;
+/* Find start of compiled code */
-*errorptr = NULL;
+code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) +
+ re->name_entry_size * re->name_count;
-if (re == NULL || re->magic_number != MAGIC_NUMBER)
- {
- *errorptr = "argument is not a compiled regular expression";
- return NULL;
- }
-
-if ((re->flags & PCRE_MODE) == 0)
- {
-#if defined COMPILE_PCRE8
- *errorptr = "argument not compiled in 8 bit mode";
-#elif defined COMPILE_PCRE16
- *errorptr = "argument not compiled in 16 bit mode";
-#elif defined COMPILE_PCRE32
- *errorptr = "argument not compiled in 32 bit mode";
-#endif
- return NULL;
- }
+/* For an anchored pattern, or an unanchored pattern that has a first code
+unit, or a multiline pattern that matches only at "line start", there is no
+point in seeking a list of starting code units. */
-if ((options & ~PUBLIC_STUDY_OPTIONS) != 0)
+if ((re->overall_options & PCRE2_ANCHORED) == 0 &&
+ (re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0)
{
- *errorptr = "unknown or incorrect option bit(s) set";
- return NULL;
+ int rc = set_start_bits(re, code, utf);
+ if (rc == SSB_UNKNOWN) return 1;
+ if (rc == SSB_DONE) re->flags |= PCRE2_FIRSTMAPSET;
}
-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. */
+/* Find the minimum length of subject string. If it can match an empty string,
+the minimum length is already known. */
-if ((re->options & PCRE_ANCHORED) == 0 &&
- (re->flags & (PCRE_FIRSTSET|PCRE_STARTLINE)) == 0)
+if ((re->flags & PCRE2_MATCH_EMPTY) == 0)
{
- int rc;
-
- /* Set the character tables in the block that is passed around */
-
- tables = re->tables;
-
-#if defined COMPILE_PCRE8
- if (tables == NULL)
- (void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
- (void *)(&tables));
-#elif defined COMPILE_PCRE16
- if (tables == NULL)
- (void)pcre16_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
- (void *)(&tables));
-#elif defined COMPILE_PCRE32
- if (tables == NULL)
- (void)pcre32_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)
+ switch(min = find_minlength(re, code, code, utf, NULL, &count))
{
- *errorptr = "internal error: opcode not recognized";
- return NULL;
- }
- }
+ case -1: /* \C in UTF mode or (*ACCEPT) or over-complex regex */
+ break; /* Leave minlength unchanged (will be zero) */
-/* Find the minimum length of subject string. */
+ case -2:
+ return 2; /* missing capturing bracket */
-switch(min = find_minlength(re, code, code, re->options, NULL, &count))
- {
- case -2: *errorptr = "internal error: missing capturing bracket"; return NULL;
- case -3: *errorptr = "internal error: opcode not recognized"; return NULL;
- default: break;
- }
+ case -3:
+ return 3; /* unrecognized opcode */
-/* 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, or if
-PCRE_STUDY_EXTRA_NEEDED is set, 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 || (options & (
-#ifdef SUPPORT_JIT
- PCRE_STUDY_JIT_COMPILE | PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE |
- PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE |
-#endif
- PCRE_STUDY_EXTRA_NEEDED)) != 0)
- {
- 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, unless
- PCRE_STUDY_EXTRA_NEEDED is set. */
-
-#ifdef SUPPORT_JIT
- extra->executable_jit = NULL;
- if ((options & PCRE_STUDY_JIT_COMPILE) != 0)
- PRIV(jit_compile)(re, extra, JIT_COMPILE);
- if ((options & PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE) != 0)
- PRIV(jit_compile)(re, extra, JIT_PARTIAL_SOFT_COMPILE);
- if ((options & PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE) != 0)
- PRIV(jit_compile)(re, extra, JIT_PARTIAL_HARD_COMPILE);
-
- if (study->flags == 0 && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) == 0 &&
- (options & PCRE_STUDY_EXTRA_NEEDED) == 0)
- {
-#if defined COMPILE_PCRE8
- pcre_free_study(extra);
-#elif defined COMPILE_PCRE16
- pcre16_free_study(extra);
-#elif defined COMPILE_PCRE32
- pcre32_free_study(extra);
-#endif
- extra = NULL;
+ default:
+ if (min > UINT16_MAX) min = UINT16_MAX;
+ re->minlength = min;
+ break;
}
-#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
-*/
-
-#if defined COMPILE_PCRE8
-PCRE_EXP_DEFN void
-pcre_free_study(pcre_extra *extra)
-#elif defined COMPILE_PCRE16
-PCRE_EXP_DEFN void
-pcre16_free_study(pcre16_extra *extra)
-#elif defined COMPILE_PCRE32
-PCRE_EXP_DEFN void
-pcre32_free_study(pcre32_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);
+return 0;
}
-/* End of pcre_study.c */
+/* End of pcre2_study.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_substitute.c b/src/3rdparty/pcre2/src/pcre2_substitute.c
new file mode 100644
index 0000000000..0bf781efc1
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_substitute.c
@@ -0,0 +1,850 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre2_internal.h"
+
+#define PTR_STACK_SIZE 20
+
+#define SUBSTITUTE_OPTIONS \
+ (PCRE2_SUBSTITUTE_EXTENDED|PCRE2_SUBSTITUTE_GLOBAL| \
+ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH|PCRE2_SUBSTITUTE_UNKNOWN_UNSET| \
+ PCRE2_SUBSTITUTE_UNSET_EMPTY)
+
+
+
+/*************************************************
+* Find end of substitute text *
+*************************************************/
+
+/* In extended mode, we recognize ${name:+set text:unset text} and similar
+constructions. This requires the identification of unescaped : and }
+characters. This function scans for such. It must deal with nested ${
+constructions. The pointer to the text is updated, either to the required end
+character, or to where an error was detected.
+
+Arguments:
+ code points to the compiled expression (for options)
+ ptrptr points to the pointer to the start of the text (updated)
+ ptrend end of the whole string
+ last TRUE if the last expected string (only } recognized)
+
+Returns: 0 on success
+ negative error code on failure
+*/
+
+static int
+find_text_end(const pcre2_code *code, PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend,
+ BOOL last)
+{
+int rc = 0;
+uint32_t nestlevel = 0;
+BOOL literal = FALSE;
+PCRE2_SPTR ptr = *ptrptr;
+
+for (; ptr < ptrend; ptr++)
+ {
+ if (literal)
+ {
+ if (ptr[0] == CHAR_BACKSLASH && ptr < ptrend - 1 && ptr[1] == CHAR_E)
+ {
+ literal = FALSE;
+ ptr += 1;
+ }
+ }
+
+ else if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
+ {
+ if (nestlevel == 0) goto EXIT;
+ nestlevel--;
+ }
+
+ else if (*ptr == CHAR_COLON && !last && nestlevel == 0) goto EXIT;
+
+ else if (*ptr == CHAR_DOLLAR_SIGN)
+ {
+ if (ptr < ptrend - 1 && ptr[1] == CHAR_LEFT_CURLY_BRACKET)
+ {
+ nestlevel++;
+ ptr += 1;
+ }
+ }
+
+ else if (*ptr == CHAR_BACKSLASH)
+ {
+ int erc;
+ int errorcode = 0;
+ uint32_t ch;
+
+ if (ptr < ptrend - 1) switch (ptr[1])
+ {
+ case CHAR_L:
+ case CHAR_l:
+ case CHAR_U:
+ case CHAR_u:
+ ptr += 1;
+ continue;
+ }
+
+ erc = PRIV(check_escape)(&ptr, ptrend, &ch, &errorcode,
+ code->overall_options, FALSE, NULL);
+ if (errorcode != 0)
+ {
+ rc = errorcode;
+ goto EXIT;
+ }
+
+ switch(erc)
+ {
+ case 0: /* Data character */
+ case ESC_E: /* Isolated \E is ignored */
+ break;
+
+ case ESC_Q:
+ literal = TRUE;
+ break;
+
+ default:
+ rc = PCRE2_ERROR_BADREPESCAPE;
+ goto EXIT;
+ }
+ }
+ }
+
+rc = PCRE2_ERROR_REPMISSINGBRACE; /* Terminator not found */
+
+EXIT:
+*ptrptr = ptr;
+return rc;
+}
+
+
+
+/*************************************************
+* Match and substitute *
+*************************************************/
+
+/* This function applies a compiled re to a subject string and creates a new
+string with substitutions. The first 7 arguments are the same as for
+pcre2_match(). Either string length may be PCRE2_ZERO_TERMINATED.
+
+Arguments:
+ code points to the compiled expression
+ subject points to the subject string
+ length length of subject string (may contain binary zeros)
+ start_offset where to start in the subject string
+ options option bits
+ match_data points to a match_data block, or is NULL
+ context points a PCRE2 context
+ replacement points to the replacement string
+ rlength length of replacement string
+ buffer where to put the substituted string
+ blength points to length of buffer; updated to length of string
+
+Returns: >= 0 number of substitutions made
+ < 0 an error code
+ PCRE2_ERROR_BADREPLACEMENT means invalid use of $
+*/
+
+/* This macro checks for space in the buffer before copying into it. On
+overflow, either give an error immediately, or keep on, accumulating the
+length. */
+
+#define CHECKMEMCPY(from,length) \
+ if (!overflowed && lengthleft < length) \
+ { \
+ if ((suboptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) == 0) goto NOROOM; \
+ overflowed = TRUE; \
+ extra_needed = length - lengthleft; \
+ } \
+ else if (overflowed) \
+ { \
+ extra_needed += length; \
+ } \
+ else \
+ { \
+ memcpy(buffer + buff_offset, from, CU2BYTES(length)); \
+ buff_offset += length; \
+ lengthleft -= length; \
+ }
+
+/* Here's the function */
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
+ PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext, PCRE2_SPTR replacement, PCRE2_SIZE rlength,
+ PCRE2_UCHAR *buffer, PCRE2_SIZE *blength)
+{
+int rc;
+int subs;
+int forcecase = 0;
+int forcecasereset = 0;
+uint32_t ovector_count;
+uint32_t goptions = 0;
+uint32_t suboptions;
+BOOL match_data_created = FALSE;
+BOOL literal = FALSE;
+BOOL overflowed = FALSE;
+#ifdef SUPPORT_UNICODE
+BOOL utf = (code->overall_options & PCRE2_UTF) != 0;
+#endif
+PCRE2_UCHAR temp[6];
+PCRE2_SPTR ptr;
+PCRE2_SPTR repend;
+PCRE2_SIZE extra_needed = 0;
+PCRE2_SIZE buff_offset, buff_length, lengthleft, fraglength;
+PCRE2_SIZE *ovector;
+
+buff_offset = 0;
+lengthleft = buff_length = *blength;
+*blength = PCRE2_UNSET;
+
+/* Partial matching is not valid. */
+
+if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0)
+ return PCRE2_ERROR_BADOPTION;
+
+/* If no match data block is provided, create one. */
+
+if (match_data == NULL)
+ {
+ pcre2_general_context *gcontext = (mcontext == NULL)?
+ (pcre2_general_context *)code :
+ (pcre2_general_context *)mcontext;
+ match_data = pcre2_match_data_create_from_pattern(code, gcontext);
+ if (match_data == NULL) return PCRE2_ERROR_NOMEMORY;
+ match_data_created = TRUE;
+ }
+ovector = pcre2_get_ovector_pointer(match_data);
+ovector_count = pcre2_get_ovector_count(match_data);
+
+/* Find lengths of zero-terminated strings and the end of the replacement. */
+
+if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject);
+if (rlength == PCRE2_ZERO_TERMINATED) rlength = PRIV(strlen)(replacement);
+repend = replacement + rlength;
+
+/* Check UTF replacement string if necessary. */
+
+#ifdef SUPPORT_UNICODE
+if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)
+ {
+ rc = PRIV(valid_utf)(replacement, rlength, &(match_data->rightchar));
+ if (rc != 0)
+ {
+ match_data->leftchar = 0;
+ goto EXIT;
+ }
+ }
+#endif /* SUPPORT_UNICODE */
+
+/* Save the substitute options and remove them from the match options. */
+
+suboptions = options & SUBSTITUTE_OPTIONS;
+options &= ~SUBSTITUTE_OPTIONS;
+
+/* Copy up to the start offset */
+
+CHECKMEMCPY(subject, start_offset);
+
+/* Loop for global substituting. */
+
+subs = 0;
+do
+ {
+ PCRE2_SPTR ptrstack[PTR_STACK_SIZE];
+ uint32_t ptrstackptr = 0;
+
+ rc = pcre2_match(code, subject, length, start_offset, options|goptions,
+ match_data, mcontext);
+
+#ifdef SUPPORT_UNICODE
+ if (utf) options |= PCRE2_NO_UTF_CHECK; /* Only need to check once */
+#endif
+
+ /* Any error other than no match returns the error code. No match when not
+ doing the special after-empty-match global rematch, or when at the end of the
+ subject, breaks the global loop. Otherwise, advance the starting point by one
+ character, copying it to the output, and try again. */
+
+ if (rc < 0)
+ {
+ PCRE2_SIZE save_start;
+
+ if (rc != PCRE2_ERROR_NOMATCH) goto EXIT;
+ if (goptions == 0 || start_offset >= length) break;
+
+ /* Advance by one code point. Then, if CRLF is a valid newline sequence and
+ we have advanced into the middle of it, advance one more code point. In
+ other words, do not start in the middle of CRLF, even if CR and LF on their
+ own are valid newlines. */
+
+ save_start = start_offset++;
+ if (subject[start_offset-1] == CHAR_CR &&
+ code->newline_convention != PCRE2_NEWLINE_CR &&
+ code->newline_convention != PCRE2_NEWLINE_LF &&
+ start_offset < length &&
+ subject[start_offset] == CHAR_LF)
+ start_offset++;
+
+ /* Otherwise, in UTF mode, advance past any secondary code points. */
+
+ else if ((code->overall_options & PCRE2_UTF) != 0)
+ {
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ while (start_offset < length && (subject[start_offset] & 0xc0) == 0x80)
+ start_offset++;
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+ while (start_offset < length &&
+ (subject[start_offset] & 0xfc00) == 0xdc00)
+ start_offset++;
+#endif
+ }
+
+ /* Copy what we have advanced past, reset the special global options, and
+ continue to the next match. */
+
+ fraglength = start_offset - save_start;
+ CHECKMEMCPY(subject + save_start, fraglength);
+ goptions = 0;
+ continue;
+ }
+
+ /* Handle a successful match. Matches that use \K to end before they start
+ are not supported. */
+
+ if (ovector[1] < ovector[0])
+ {
+ rc = PCRE2_ERROR_BADSUBSPATTERN;
+ goto EXIT;
+ }
+
+ /* Count substitutions with a paranoid check for integer overflow; surely no
+ real call to this function would ever hit this! */
+
+ if (subs == INT_MAX)
+ {
+ rc = PCRE2_ERROR_TOOMANYREPLACE;
+ goto EXIT;
+ }
+ subs++;
+
+ /* Copy the text leading up to the match. */
+
+ if (rc == 0) rc = ovector_count;
+ fraglength = ovector[0] - start_offset;
+ CHECKMEMCPY(subject + start_offset, fraglength);
+
+ /* Process the replacement string. Literal mode is set by \Q, but only in
+ extended mode when backslashes are being interpreted. In extended mode we
+ must handle nested substrings that are to be reprocessed. */
+
+ ptr = replacement;
+ for (;;)
+ {
+ uint32_t ch;
+ unsigned int chlen;
+
+ /* If at the end of a nested substring, pop the stack. */
+
+ if (ptr >= repend)
+ {
+ if (ptrstackptr <= 0) break; /* End of replacement string */
+ repend = ptrstack[--ptrstackptr];
+ ptr = ptrstack[--ptrstackptr];
+ continue;
+ }
+
+ /* Handle the next character */
+
+ if (literal)
+ {
+ if (ptr[0] == CHAR_BACKSLASH && ptr < repend - 1 && ptr[1] == CHAR_E)
+ {
+ literal = FALSE;
+ ptr += 2;
+ continue;
+ }
+ goto LOADLITERAL;
+ }
+
+ /* Not in literal mode. */
+
+ if (*ptr == CHAR_DOLLAR_SIGN)
+ {
+ int group, n;
+ uint32_t special = 0;
+ BOOL inparens;
+ BOOL star;
+ PCRE2_SIZE sublength;
+ PCRE2_SPTR text1_start = NULL;
+ PCRE2_SPTR text1_end = NULL;
+ PCRE2_SPTR text2_start = NULL;
+ PCRE2_SPTR text2_end = NULL;
+ PCRE2_UCHAR next;
+ PCRE2_UCHAR name[33];
+
+ if (++ptr >= repend) goto BAD;
+ if ((next = *ptr) == CHAR_DOLLAR_SIGN) goto LOADLITERAL;
+
+ group = -1;
+ n = 0;
+ inparens = FALSE;
+ star = FALSE;
+
+ if (next == CHAR_LEFT_CURLY_BRACKET)
+ {
+ if (++ptr >= repend) goto BAD;
+ next = *ptr;
+ inparens = TRUE;
+ }
+
+ if (next == CHAR_ASTERISK)
+ {
+ if (++ptr >= repend) goto BAD;
+ next = *ptr;
+ star = TRUE;
+ }
+
+ if (!star && next >= CHAR_0 && next <= CHAR_9)
+ {
+ group = next - CHAR_0;
+ while (++ptr < repend)
+ {
+ next = *ptr;
+ if (next < CHAR_0 || next > CHAR_9) break;
+ group = group * 10 + next - CHAR_0;
+
+ /* A check for a number greater than the hightest captured group
+ is sufficient here; no need for a separate overflow check. If unknown
+ groups are to be treated as unset, just skip over any remaining
+ digits and carry on. */
+
+ if (group > code->top_bracket)
+ {
+ if ((suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0)
+ {
+ while (++ptr < repend && *ptr >= CHAR_0 && *ptr <= CHAR_9);
+ break;
+ }
+ else
+ {
+ rc = PCRE2_ERROR_NOSUBSTRING;
+ goto PTREXIT;
+ }
+ }
+ }
+ }
+ else
+ {
+ const uint8_t *ctypes = code->tables + ctypes_offset;
+ while (MAX_255(next) && (ctypes[next] & ctype_word) != 0)
+ {
+ name[n++] = next;
+ if (n > 32) goto BAD;
+ if (++ptr >= repend) break;
+ next = *ptr;
+ }
+ if (n == 0) goto BAD;
+ name[n] = 0;
+ }
+
+ /* In extended mode we recognize ${name:+set text:unset text} and
+ ${name:-default text}. */
+
+ if (inparens)
+ {
+ if ((suboptions & PCRE2_SUBSTITUTE_EXTENDED) != 0 &&
+ !star && ptr < repend - 2 && next == CHAR_COLON)
+ {
+ special = *(++ptr);
+ if (special != CHAR_PLUS && special != CHAR_MINUS)
+ {
+ rc = PCRE2_ERROR_BADSUBSTITUTION;
+ goto PTREXIT;
+ }
+
+ text1_start = ++ptr;
+ rc = find_text_end(code, &ptr, repend, special == CHAR_MINUS);
+ if (rc != 0) goto PTREXIT;
+ text1_end = ptr;
+
+ if (special == CHAR_PLUS && *ptr == CHAR_COLON)
+ {
+ text2_start = ++ptr;
+ rc = find_text_end(code, &ptr, repend, TRUE);
+ if (rc != 0) goto PTREXIT;
+ text2_end = ptr;
+ }
+ }
+
+ else
+ {
+ if (ptr >= repend || *ptr != CHAR_RIGHT_CURLY_BRACKET)
+ {
+ rc = PCRE2_ERROR_REPMISSINGBRACE;
+ goto PTREXIT;
+ }
+ }
+
+ ptr++;
+ }
+
+ /* Have found a syntactically correct group number or name, or *name.
+ Only *MARK is currently recognized. */
+
+ if (star)
+ {
+ if (PRIV(strcmp_c8)(name, STRING_MARK) == 0)
+ {
+ PCRE2_SPTR mark = pcre2_get_mark(match_data);
+ if (mark != NULL)
+ {
+ PCRE2_SPTR mark_start = mark;
+ while (*mark != 0) mark++;
+ fraglength = mark - mark_start;
+ CHECKMEMCPY(mark_start, fraglength);
+ }
+ }
+ else goto BAD;
+ }
+
+ /* Substitute the contents of a group. We don't use substring_copy
+ functions any more, in order to support case forcing. */
+
+ else
+ {
+ PCRE2_SPTR subptr, subptrend;
+
+ /* Find a number for a named group. In case there are duplicate names,
+ search for the first one that is set. If the name is not found when
+ PCRE2_SUBSTITUTE_UNKNOWN_EMPTY is set, set the group number to a
+ non-existent group. */
+
+ if (group < 0)
+ {
+ PCRE2_SPTR first, last, entry;
+ rc = pcre2_substring_nametable_scan(code, name, &first, &last);
+ if (rc == PCRE2_ERROR_NOSUBSTRING &&
+ (suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0)
+ {
+ group = code->top_bracket + 1;
+ }
+ else
+ {
+ if (rc < 0) goto PTREXIT;
+ for (entry = first; entry <= last; entry += rc)
+ {
+ uint32_t ng = GET2(entry, 0);
+ if (ng < ovector_count)
+ {
+ if (group < 0) group = ng; /* First in ovector */
+ if (ovector[ng*2] != PCRE2_UNSET)
+ {
+ group = ng; /* First that is set */
+ break;
+ }
+ }
+ }
+
+ /* If group is still negative, it means we did not find a group
+ that is in the ovector. Just set the first group. */
+
+ if (group < 0) group = GET2(first, 0);
+ }
+ }
+
+ /* We now have a group that is identified by number. Find the length of
+ the captured string. If a group in a non-special substitution is unset
+ when PCRE2_SUBSTITUTE_UNSET_EMPTY is set, substitute nothing. */
+
+ rc = pcre2_substring_length_bynumber(match_data, group, &sublength);
+ if (rc < 0)
+ {
+ if (rc == PCRE2_ERROR_NOSUBSTRING &&
+ (suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) != 0)
+ {
+ rc = PCRE2_ERROR_UNSET;
+ }
+ if (rc != PCRE2_ERROR_UNSET) goto PTREXIT; /* Non-unset errors */
+ if (special == 0) /* Plain substitution */
+ {
+ if ((suboptions & PCRE2_SUBSTITUTE_UNSET_EMPTY) != 0) continue;
+ goto PTREXIT; /* Else error */
+ }
+ }
+
+ /* If special is '+' we have a 'set' and possibly an 'unset' text,
+ both of which are reprocessed when used. If special is '-' we have a
+ default text for when the group is unset; it must be reprocessed. */
+
+ if (special != 0)
+ {
+ if (special == CHAR_MINUS)
+ {
+ if (rc == 0) goto LITERAL_SUBSTITUTE;
+ text2_start = text1_start;
+ text2_end = text1_end;
+ }
+
+ if (ptrstackptr >= PTR_STACK_SIZE) goto BAD;
+ ptrstack[ptrstackptr++] = ptr;
+ ptrstack[ptrstackptr++] = repend;
+
+ if (rc == 0)
+ {
+ ptr = text1_start;
+ repend = text1_end;
+ }
+ else
+ {
+ ptr = text2_start;
+ repend = text2_end;
+ }
+ continue;
+ }
+
+ /* Otherwise we have a literal substitution of a group's contents. */
+
+ LITERAL_SUBSTITUTE:
+ subptr = subject + ovector[group*2];
+ subptrend = subject + ovector[group*2 + 1];
+
+ /* Substitute a literal string, possibly forcing alphabetic case. */
+
+ while (subptr < subptrend)
+ {
+ GETCHARINCTEST(ch, subptr);
+ if (forcecase != 0)
+ {
+#ifdef SUPPORT_UNICODE
+ if (utf)
+ {
+ uint32_t type = UCD_CHARTYPE(ch);
+ if (PRIV(ucp_gentype)[type] == ucp_L &&
+ type != ((forcecase > 0)? ucp_Lu : ucp_Ll))
+ ch = UCD_OTHERCASE(ch);
+ }
+ else
+#endif
+ {
+ if (((code->tables + cbits_offset +
+ ((forcecase > 0)? cbit_upper:cbit_lower)
+ )[ch/8] & (1 << (ch%8))) == 0)
+ ch = (code->tables + fcc_offset)[ch];
+ }
+ forcecase = forcecasereset;
+ }
+
+#ifdef SUPPORT_UNICODE
+ if (utf) chlen = PRIV(ord2utf)(ch, temp); else
+#endif
+ {
+ temp[0] = ch;
+ chlen = 1;
+ }
+ CHECKMEMCPY(temp, chlen);
+ }
+ }
+ }
+
+ /* Handle an escape sequence in extended mode. We can use check_escape()
+ to process \Q, \E, \c, \o, \x and \ followed by non-alphanumerics, but
+ the case-forcing escapes are not supported in pcre2_compile() so must be
+ recognized here. */
+
+ else if ((suboptions & PCRE2_SUBSTITUTE_EXTENDED) != 0 &&
+ *ptr == CHAR_BACKSLASH)
+ {
+ int errorcode = 0;
+
+ if (ptr < repend - 1) switch (ptr[1])
+ {
+ case CHAR_L:
+ forcecase = forcecasereset = -1;
+ ptr += 2;
+ continue;
+
+ case CHAR_l:
+ forcecase = -1;
+ forcecasereset = 0;
+ ptr += 2;
+ continue;
+
+ case CHAR_U:
+ forcecase = forcecasereset = 1;
+ ptr += 2;
+ continue;
+
+ case CHAR_u:
+ forcecase = 1;
+ forcecasereset = 0;
+ ptr += 2;
+ continue;
+
+ default:
+ break;
+ }
+
+ rc = PRIV(check_escape)(&ptr, repend, &ch, &errorcode,
+ code->overall_options, FALSE, NULL);
+ if (errorcode != 0) goto BADESCAPE;
+ ptr++;
+
+ switch(rc)
+ {
+ case ESC_E:
+ forcecase = forcecasereset = 0;
+ continue;
+
+ case ESC_Q:
+ literal = TRUE;
+ continue;
+
+ case 0: /* Data character */
+ goto LITERAL;
+
+ default:
+ goto BADESCAPE;
+ }
+ }
+
+ /* Handle a literal code unit */
+
+ else
+ {
+ LOADLITERAL:
+ GETCHARINCTEST(ch, ptr); /* Get character value, increment pointer */
+
+ LITERAL:
+ if (forcecase != 0)
+ {
+#ifdef SUPPORT_UNICODE
+ if (utf)
+ {
+ uint32_t type = UCD_CHARTYPE(ch);
+ if (PRIV(ucp_gentype)[type] == ucp_L &&
+ type != ((forcecase > 0)? ucp_Lu : ucp_Ll))
+ ch = UCD_OTHERCASE(ch);
+ }
+ else
+#endif
+ {
+ if (((code->tables + cbits_offset +
+ ((forcecase > 0)? cbit_upper:cbit_lower)
+ )[ch/8] & (1 << (ch%8))) == 0)
+ ch = (code->tables + fcc_offset)[ch];
+ }
+ forcecase = forcecasereset;
+ }
+
+#ifdef SUPPORT_UNICODE
+ if (utf) chlen = PRIV(ord2utf)(ch, temp); else
+#endif
+ {
+ temp[0] = ch;
+ chlen = 1;
+ }
+ CHECKMEMCPY(temp, chlen);
+ } /* End handling a literal code unit */
+ } /* End of loop for scanning the replacement. */
+
+ /* The replacement has been copied to the output. Update the start offset to
+ point to the rest of the subject string. If we matched an empty string,
+ do the magic for global matches. */
+
+ start_offset = ovector[1];
+ goptions = (ovector[0] != ovector[1])? 0 :
+ PCRE2_ANCHORED|PCRE2_NOTEMPTY_ATSTART;
+ } while ((suboptions & PCRE2_SUBSTITUTE_GLOBAL) != 0); /* Repeat "do" loop */
+
+/* Copy the rest of the subject. */
+
+fraglength = length - start_offset;
+CHECKMEMCPY(subject + start_offset, fraglength);
+temp[0] = 0;
+CHECKMEMCPY(temp , 1);
+
+/* If overflowed is set it means the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set,
+and matching has carried on after a full buffer, in order to compute the length
+needed. Otherwise, an overflow generates an immediate error return. */
+
+if (overflowed)
+ {
+ rc = PCRE2_ERROR_NOMEMORY;
+ *blength = buff_length + extra_needed;
+ }
+
+/* After a successful execution, return the number of substitutions and set the
+length of buffer used, excluding the trailing zero. */
+
+else
+ {
+ rc = subs;
+ *blength = buff_offset - 1;
+ }
+
+EXIT:
+if (match_data_created) pcre2_match_data_free(match_data);
+ else match_data->rc = rc;
+return rc;
+
+NOROOM:
+rc = PCRE2_ERROR_NOMEMORY;
+goto EXIT;
+
+BAD:
+rc = PCRE2_ERROR_BADREPLACEMENT;
+goto PTREXIT;
+
+BADESCAPE:
+rc = PCRE2_ERROR_BADREPESCAPE;
+
+PTREXIT:
+*blength = (PCRE2_SIZE)(ptr - replacement);
+goto EXIT;
+}
+
+/* End of pcre2_substitute.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_substring.c b/src/3rdparty/pcre2/src/pcre2_substring.c
new file mode 100644
index 0000000000..f6d7c39722
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_substring.c
@@ -0,0 +1,542 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcre2_internal.h"
+
+
+
+/*************************************************
+* Copy named captured string to given buffer *
+*************************************************/
+
+/* This function copies a single captured substring into a given buffer,
+identifying it by name. If the regex permits duplicate names, the first
+substring that is set is chosen.
+
+Arguments:
+ match_data points to the match data
+ stringname the name of the required substring
+ buffer where to put the substring
+ sizeptr the size of the buffer, updated to the size of the substring
+
+Returns: if successful: zero
+ if not successful, a negative error code:
+ (1) an error from nametable_scan()
+ (2) an error from copy_bynumber()
+ (3) PCRE2_ERROR_UNAVAILABLE: no group is in ovector
+ (4) PCRE2_ERROR_UNSET: all named groups in ovector are unset
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_substring_copy_byname(pcre2_match_data *match_data, PCRE2_SPTR stringname,
+ PCRE2_UCHAR *buffer, PCRE2_SIZE *sizeptr)
+{
+PCRE2_SPTR first, last, entry;
+int failrc, entrysize;
+if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER)
+ return PCRE2_ERROR_DFA_UFUNC;
+entrysize = pcre2_substring_nametable_scan(match_data->code, stringname,
+ &first, &last);
+if (entrysize < 0) return entrysize;
+failrc = PCRE2_ERROR_UNAVAILABLE;
+for (entry = first; entry <= last; entry += entrysize)
+ {
+ uint32_t n = GET2(entry, 0);
+ if (n < match_data->oveccount)
+ {
+ if (match_data->ovector[n*2] != PCRE2_UNSET)
+ return pcre2_substring_copy_bynumber(match_data, n, buffer, sizeptr);
+ failrc = PCRE2_ERROR_UNSET;
+ }
+ }
+return failrc;
+}
+
+
+
+/*************************************************
+* Copy numbered captured string to given buffer *
+*************************************************/
+
+/* This function copies a single captured substring into a given buffer,
+identifying it by number.
+
+Arguments:
+ match_data points to the match data
+ stringnumber the number of the required substring
+ buffer where to put the substring
+ sizeptr the size of the buffer, updated to the size of the substring
+
+Returns: if successful: 0
+ if not successful, a negative error code:
+ PCRE2_ERROR_NOMEMORY: buffer too small
+ PCRE2_ERROR_NOSUBSTRING: no such substring
+ PCRE2_ERROR_UNAVAILABLE: ovector too small
+ PCRE2_ERROR_UNSET: substring is not set
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_substring_copy_bynumber(pcre2_match_data *match_data,
+ uint32_t stringnumber, PCRE2_UCHAR *buffer, PCRE2_SIZE *sizeptr)
+{
+int rc;
+PCRE2_SIZE size;
+rc = pcre2_substring_length_bynumber(match_data, stringnumber, &size);
+if (rc < 0) return rc;
+if (size + 1 > *sizeptr) return PCRE2_ERROR_NOMEMORY;
+memcpy(buffer, match_data->subject + match_data->ovector[stringnumber*2],
+ CU2BYTES(size));
+buffer[size] = 0;
+*sizeptr = size;
+return 0;
+}
+
+
+
+/*************************************************
+* Extract named captured string *
+*************************************************/
+
+/* This function copies a single captured substring, identified by name, into
+new memory. If the regex permits duplicate names, the first substring that is
+set is chosen.
+
+Arguments:
+ match_data pointer to match_data
+ stringname the name of the required substring
+ stringptr where to put the pointer to the new memory
+ sizeptr where to put the length of the substring
+
+Returns: if successful: zero
+ if not successful, a negative value:
+ (1) an error from nametable_scan()
+ (2) an error from get_bynumber()
+ (3) PCRE2_ERROR_UNAVAILABLE: no group is in ovector
+ (4) PCRE2_ERROR_UNSET: all named groups in ovector are unset
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_substring_get_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR stringname, PCRE2_UCHAR **stringptr, PCRE2_SIZE *sizeptr)
+{
+PCRE2_SPTR first, last, entry;
+int failrc, entrysize;
+if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER)
+ return PCRE2_ERROR_DFA_UFUNC;
+entrysize = pcre2_substring_nametable_scan(match_data->code, stringname,
+ &first, &last);
+if (entrysize < 0) return entrysize;
+failrc = PCRE2_ERROR_UNAVAILABLE;
+for (entry = first; entry <= last; entry += entrysize)
+ {
+ uint32_t n = GET2(entry, 0);
+ if (n < match_data->oveccount)
+ {
+ if (match_data->ovector[n*2] != PCRE2_UNSET)
+ return pcre2_substring_get_bynumber(match_data, n, stringptr, sizeptr);
+ failrc = PCRE2_ERROR_UNSET;
+ }
+ }
+return failrc;
+}
+
+
+
+/*************************************************
+* Extract captured string to new memory *
+*************************************************/
+
+/* This function copies a single captured substring into a piece of new
+memory.
+
+Arguments:
+ match_data points to match data
+ stringnumber the number of the required substring
+ stringptr where to put a pointer to the new memory
+ sizeptr where to put the size of the substring
+
+Returns: if successful: 0
+ if not successful, a negative error code:
+ PCRE2_ERROR_NOMEMORY: failed to get memory
+ PCRE2_ERROR_NOSUBSTRING: no such substring
+ PCRE2_ERROR_UNAVAILABLE: ovector too small
+ PCRE2_ERROR_UNSET: substring is not set
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_substring_get_bynumber(pcre2_match_data *match_data,
+ uint32_t stringnumber, PCRE2_UCHAR **stringptr, PCRE2_SIZE *sizeptr)
+{
+int rc;
+PCRE2_SIZE size;
+PCRE2_UCHAR *yield;
+rc = pcre2_substring_length_bynumber(match_data, stringnumber, &size);
+if (rc < 0) return rc;
+yield = PRIV(memctl_malloc)(sizeof(pcre2_memctl) +
+ (size + 1)*PCRE2_CODE_UNIT_WIDTH, (pcre2_memctl *)match_data);
+if (yield == NULL) return PCRE2_ERROR_NOMEMORY;
+yield = (PCRE2_UCHAR *)(((char *)yield) + sizeof(pcre2_memctl));
+memcpy(yield, match_data->subject + match_data->ovector[stringnumber*2],
+ CU2BYTES(size));
+yield[size] = 0;
+*stringptr = yield;
+*sizeptr = size;
+return 0;
+}
+
+
+
+/*************************************************
+* Free memory obtained by get_substring *
+*************************************************/
+
+/*
+Argument: the result of a previous pcre2_substring_get_byxxx()
+Returns: nothing
+*/
+
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_substring_free(PCRE2_UCHAR *string)
+{
+if (string != NULL)
+ {
+ pcre2_memctl *memctl = (pcre2_memctl *)((char *)string - sizeof(pcre2_memctl));
+ memctl->free(memctl, memctl->memory_data);
+ }
+}
+
+
+
+/*************************************************
+* Get length of a named substring *
+*************************************************/
+
+/* This function returns the length of a named captured substring. If the regex
+permits duplicate names, the first substring that is set is chosen.
+
+Arguments:
+ match_data pointer to match data
+ stringname the name of the required substring
+ sizeptr where to put the length
+
+Returns: 0 if successful, else a negative error number
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_substring_length_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR stringname, PCRE2_SIZE *sizeptr)
+{
+PCRE2_SPTR first, last, entry;
+int failrc, entrysize;
+if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER)
+ return PCRE2_ERROR_DFA_UFUNC;
+entrysize = pcre2_substring_nametable_scan(match_data->code, stringname,
+ &first, &last);
+if (entrysize < 0) return entrysize;
+failrc = PCRE2_ERROR_UNAVAILABLE;
+for (entry = first; entry <= last; entry += entrysize)
+ {
+ uint32_t n = GET2(entry, 0);
+ if (n < match_data->oveccount)
+ {
+ if (match_data->ovector[n*2] != PCRE2_UNSET)
+ return pcre2_substring_length_bynumber(match_data, n, sizeptr);
+ failrc = PCRE2_ERROR_UNSET;
+ }
+ }
+return failrc;
+}
+
+
+
+/*************************************************
+* Get length of a numbered substring *
+*************************************************/
+
+/* This function returns the length of a captured substring. If the start is
+beyond the end (which can happen when \K is used in an assertion), it sets the
+length to zero.
+
+Arguments:
+ match_data pointer to match data
+ stringnumber the number of the required substring
+ sizeptr where to put the length, if not NULL
+
+Returns: if successful: 0
+ if not successful, a negative error code:
+ PCRE2_ERROR_NOSUBSTRING: no such substring
+ PCRE2_ERROR_UNAVAILABLE: ovector is too small
+ PCRE2_ERROR_UNSET: substring is not set
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_substring_length_bynumber(pcre2_match_data *match_data,
+ uint32_t stringnumber, PCRE2_SIZE *sizeptr)
+{
+PCRE2_SIZE left, right;
+int count = match_data->rc;
+if (count == PCRE2_ERROR_PARTIAL)
+ {
+ if (stringnumber > 0) return PCRE2_ERROR_PARTIAL;
+ count = 0;
+ }
+else if (count < 0) return count; /* Match failed */
+
+if (match_data->matchedby != PCRE2_MATCHEDBY_DFA_INTERPRETER)
+ {
+ if (stringnumber > match_data->code->top_bracket)
+ return PCRE2_ERROR_NOSUBSTRING;
+ if (stringnumber >= match_data->oveccount)
+ return PCRE2_ERROR_UNAVAILABLE;
+ if (match_data->ovector[stringnumber*2] == PCRE2_UNSET)
+ return PCRE2_ERROR_UNSET;
+ }
+else /* Matched using pcre2_dfa_match() */
+ {
+ if (stringnumber >= match_data->oveccount) return PCRE2_ERROR_UNAVAILABLE;
+ if (count != 0 && stringnumber >= (uint32_t)count) return PCRE2_ERROR_UNSET;
+ }
+
+left = match_data->ovector[stringnumber*2];
+right = match_data->ovector[stringnumber*2+1];
+if (sizeptr != NULL) *sizeptr = (left > right)? 0 : right - left;
+return 0;
+}
+
+
+
+/*************************************************
+* Extract all captured strings to new memory *
+*************************************************/
+
+/* This function gets one chunk of memory and builds a list of pointers and all
+the captured substrings in it. A NULL pointer is put on the end of the list.
+The substrings are zero-terminated, but also, if the final argument is
+non-NULL, a list of lengths is also returned. This allows binary data to be
+handled.
+
+Arguments:
+ match_data points to the match data
+ listptr set to point to the list of pointers
+ lengthsptr set to point to the list of lengths (may be NULL)
+
+Returns: if successful: 0
+ if not successful, a negative error code:
+ PCRE2_ERROR_NOMEMORY: failed to get memory,
+ or a match failure code
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_substring_list_get(pcre2_match_data *match_data, PCRE2_UCHAR ***listptr,
+ PCRE2_SIZE **lengthsptr)
+{
+int i, count, count2;
+PCRE2_SIZE size;
+PCRE2_SIZE *lensp;
+pcre2_memctl *memp;
+PCRE2_UCHAR **listp;
+PCRE2_UCHAR *sp;
+PCRE2_SIZE *ovector;
+
+if ((count = match_data->rc) < 0) return count; /* Match failed */
+if (count == 0) count = match_data->oveccount; /* Ovector too small */
+
+count2 = 2*count;
+ovector = match_data->ovector;
+size = sizeof(pcre2_memctl) + sizeof(PCRE2_UCHAR *); /* For final NULL */
+if (lengthsptr != NULL) size += sizeof(PCRE2_SIZE) * count; /* For lengths */
+
+for (i = 0; i < count2; i += 2)
+ {
+ size += sizeof(PCRE2_UCHAR *) + CU2BYTES(1);
+ if (ovector[i+1] > ovector[i]) size += CU2BYTES(ovector[i+1] - ovector[i]);
+ }
+
+memp = PRIV(memctl_malloc)(size, (pcre2_memctl *)match_data);
+if (memp == NULL) return PCRE2_ERROR_NOMEMORY;
+
+*listptr = listp = (PCRE2_UCHAR **)((char *)memp + sizeof(pcre2_memctl));
+lensp = (PCRE2_SIZE *)((char *)listp + sizeof(PCRE2_UCHAR *) * (count + 1));
+
+if (lengthsptr == NULL)
+ {
+ sp = (PCRE2_UCHAR *)lensp;
+ lensp = NULL;
+ }
+else
+ {
+ *lengthsptr = lensp;
+ sp = (PCRE2_UCHAR *)((char *)lensp + sizeof(PCRE2_SIZE) * count);
+ }
+
+for (i = 0; i < count2; i += 2)
+ {
+ size = (ovector[i+1] > ovector[i])? (ovector[i+1] - ovector[i]) : 0;
+ memcpy(sp, match_data->subject + ovector[i], CU2BYTES(size));
+ *listp++ = sp;
+ if (lensp != NULL) *lensp++ = size;
+ sp += size;
+ *sp++ = 0;
+ }
+
+*listp = NULL;
+return 0;
+}
+
+
+
+/*************************************************
+* Free memory obtained by substring_list_get *
+*************************************************/
+
+/*
+Argument: the result of a previous pcre2_substring_list_get()
+Returns: nothing
+*/
+
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_substring_list_free(PCRE2_SPTR *list)
+{
+if (list != NULL)
+ {
+ pcre2_memctl *memctl = (pcre2_memctl *)((char *)list - sizeof(pcre2_memctl));
+ memctl->free(memctl, memctl->memory_data);
+ }
+}
+
+
+
+/*************************************************
+* Find (multiple) entries for named string *
+*************************************************/
+
+/* This function scans the nametable for a given name, using binary chop. It
+returns either two pointers to the entries in the table, or, if no pointers are
+given, the number of a unique group with the given name. If duplicate names are
+permitted, and the name is not unique, an error is generated.
+
+Arguments:
+ code the compiled regex
+ stringname the name whose entries required
+ firstptr where to put the pointer to the first entry
+ lastptr where to put the pointer to the last entry
+
+Returns: PCRE2_ERROR_NOSUBSTRING if the name is not found
+ otherwise, if firstptr and lastptr are NULL:
+ a group number for a unique substring
+ else PCRE2_ERROR_NOUNIQUESUBSTRING
+ otherwise:
+ the length of each entry, having set firstptr and lastptr
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_substring_nametable_scan(const pcre2_code *code, PCRE2_SPTR stringname,
+ PCRE2_SPTR *firstptr, PCRE2_SPTR *lastptr)
+{
+uint16_t bot = 0;
+uint16_t top = code->name_count;
+uint16_t entrysize = code->name_entry_size;
+PCRE2_SPTR nametable = (PCRE2_SPTR)((char *)code + sizeof(pcre2_real_code));
+
+while (top > bot)
+ {
+ uint16_t mid = (top + bot) / 2;
+ PCRE2_SPTR entry = nametable + entrysize*mid;
+ int c = PRIV(strcmp)(stringname, entry + IMM2_SIZE);
+ if (c == 0)
+ {
+ PCRE2_SPTR first;
+ PCRE2_SPTR last;
+ PCRE2_SPTR lastentry;
+ lastentry = nametable + entrysize * (code->name_count - 1);
+ first = last = entry;
+ while (first > nametable)
+ {
+ if (PRIV(strcmp)(stringname, (first - entrysize + IMM2_SIZE)) != 0) break;
+ first -= entrysize;
+ }
+ while (last < lastentry)
+ {
+ if (PRIV(strcmp)(stringname, (last + entrysize + IMM2_SIZE)) != 0) break;
+ last += entrysize;
+ }
+ if (firstptr == NULL) return (first == last)?
+ (int)GET2(entry, 0) : PCRE2_ERROR_NOUNIQUESUBSTRING;
+ *firstptr = first;
+ *lastptr = last;
+ return entrysize;
+ }
+ if (c > 0) bot = mid + 1; else top = mid;
+ }
+
+return PCRE2_ERROR_NOSUBSTRING;
+}
+
+
+/*************************************************
+* Find number for named string *
+*************************************************/
+
+/* This function is a convenience wrapper for pcre2_substring_nametable_scan()
+when it is known that names are unique. If there are duplicate names, it is not
+defined which number is returned.
+
+Arguments:
+ code the compiled regex
+ stringname the name whose number is required
+
+Returns: the number of the named parenthesis, or a negative number
+ PCRE2_ERROR_NOSUBSTRING if not found
+ PCRE2_ERROR_NOUNIQUESUBSTRING if not unique
+*/
+
+PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
+pcre2_substring_number_from_name(const pcre2_code *code,
+ PCRE2_SPTR stringname)
+{
+return pcre2_substring_nametable_scan(code, stringname, NULL, NULL);
+}
+
+/* End of pcre2_substring.c */
diff --git a/src/3rdparty/pcre/pcre_tables.c b/src/3rdparty/pcre2/src/pcre2_tables.c
index 4960af57c4..b945ed7a7f 100644
--- a/src/3rdparty/pcre/pcre_tables.c
+++ b/src/3rdparty/pcre2/src/pcre2_tables.c
@@ -6,7 +6,8 @@
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
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -37,46 +38,64 @@ 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. */
-
+PCRE code modules. The tables are also #included by the pcre2test program,
+which uses macros to change their names from _pcre2_xxx to xxxx, thereby
+avoiding name clashes with the library. In this case, PCRE2_PCRE2TEST is
+defined. */
+#ifndef PCRE2_PCRE2TEST /* We're compiling the library */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include "pcre2_internal.h"
+#endif /* PCRE2_PCRE2TEST */
-#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. */
+the definition is next to the definition of the opcodes in pcre2_internal.h.
+This is mode-dependent, so is skipped when this file is included by pcre2test. */
-const pcre_uint8 PRIV(OP_lengths)[] = { OP_LENGTHS };
+#ifndef PCRE2_PCRE2TEST
+const uint8_t PRIV(OP_lengths)[] = { OP_LENGTHS };
+#endif
/* Tables of horizontal and vertical whitespace characters, suitable for
adding to classes. */
-const pcre_uint32 PRIV(hspace_list)[] = { HSPACE_LIST };
-const pcre_uint32 PRIV(vspace_list)[] = { VSPACE_LIST };
+const uint32_t PRIV(hspace_list)[] = { HSPACE_LIST };
+const uint32_t PRIV(vspace_list)[] = { VSPACE_LIST };
+
+/* These tables are the pairs of delimiters that are valid for callout string
+arguments. For each starting delimiter there must be a matching ending
+delimiter, which in fact is different only for bracket-like delimiters. */
+
+const uint32_t PRIV(callout_start_delims)[] = {
+ CHAR_GRAVE_ACCENT, CHAR_APOSTROPHE, CHAR_QUOTATION_MARK,
+ CHAR_CIRCUMFLEX_ACCENT, CHAR_PERCENT_SIGN, CHAR_NUMBER_SIGN,
+ CHAR_DOLLAR_SIGN, CHAR_LEFT_CURLY_BRACKET, 0 };
+const uint32_t PRIV(callout_end_delims[]) = {
+ CHAR_GRAVE_ACCENT, CHAR_APOSTROPHE, CHAR_QUOTATION_MARK,
+ CHAR_CIRCUMFLEX_ACCENT, CHAR_PERCENT_SIGN, CHAR_NUMBER_SIGN,
+ CHAR_DOLLAR_SIGN, CHAR_RIGHT_CURLY_BRACKET, 0 };
/*************************************************
* Tables for UTF-8 support *
*************************************************/
-/* These are the breakpoints for different numbers of bytes in a UTF-8
-character. */
+/* These tables are required by pcre2test in 16- or 32-bit mode, as well
+as for the library in 8-bit mode, because pcre2test uses UTF-8 internally for
+handling wide characters. */
-#if (defined SUPPORT_UTF && defined COMPILE_PCRE8) \
- || (defined PCRE_INCLUDED && (defined SUPPORT_PCRE16 || defined SUPPORT_PCRE32))
+#if defined PCRE2_PCRE2TEST || \
+ (defined SUPPORT_UNICODE && \
+ defined PCRE2_CODE_UNIT_WIDTH && \
+ PCRE2_CODE_UNIT_WIDTH == 8)
-/* These tables are also required by pcretest in 16- or 32-bit mode. */
+/* These are the breakpoints for different numbers of bytes in a UTF-8
+character. */
const int PRIV(utf8_table1)[] =
{ 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
@@ -92,19 +111,20 @@ 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)[] = {
+const uint8_t PRIV(utf8_table4)[] = {
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
-#endif /* (SUPPORT_UTF && COMPILE_PCRE8) || (PCRE_INCLUDED && SUPPORT_PCRE[16|32])*/
+#endif /* UTF-8 support needed */
+
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
/* Table to translate from particular type value to the general value. */
-const pcre_uint32 PRIV(ucp_gentype)[] = {
+const uint32_t PRIV(ucp_gentype)[] = {
ucp_C, ucp_C, ucp_C, ucp_C, ucp_C, /* Cc, Cf, Cn, Co, Cs */
ucp_L, ucp_L, ucp_L, ucp_L, ucp_L, /* Ll, Lu, Lm, Lo, Lt */
ucp_M, ucp_M, ucp_M, /* Mc, Me, Mn */
@@ -117,11 +137,11 @@ const pcre_uint32 PRIV(ucp_gentype)[] = {
/* This table encodes the rules for finding the end of an extended grapheme
cluster. Every code point has a grapheme break property which is one of the
-ucp_gbXX values defined in ucp.h. The 2-dimensional table is indexed by the
-properties of two adjacent code points. The left property selects a word from
-the table, and the right property selects a bit from that word like this:
+ucp_gbXX values defined in pcre2_ucp.h. The 2-dimensional table is indexed by
+the properties of two adjacent code points. The left property selects a word
+from the table, and the right property selects a bit from that word like this:
- ucp_gbtable[left-property] & (1 << right-property)
+ PRIV(ucp_gbtable)[left-property] & (1 << right-property)
The value is non-zero if a grapheme break is NOT permitted between the relevant
two code points. The breaking rules are as follows:
@@ -149,7 +169,7 @@ are implementing).
7. Otherwise, break everywhere.
*/
-const pcre_uint32 PRIV(ucp_gbtable[]) = {
+const uint32_t PRIV(ucp_gbtable)[] = {
(1<<ucp_gbLF), /* 0 CR */
0, /* 1 LF */
0, /* 2 Control */
@@ -190,7 +210,7 @@ const int PRIV(ucp_typerange)[] = {
};
#endif /* SUPPORT_JIT */
-/* The pcre_utt[] table below translates Unicode property names into type and
+/* The PRIV(utt)[] table below translates Unicode property names into type and
code values. It is searched by binary chop, so must be in collating sequence of
name. Originally, the table contained pointers to the name strings in the first
field of each entry. However, that leads to a large number of relocations when
@@ -207,6 +227,8 @@ 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_Ahom0 STR_A STR_h STR_o STR_m "\0"
+#define STRING_Anatolian_Hieroglyphs0 STR_A STR_n STR_a STR_t STR_o STR_l STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
#define STRING_Any0 STR_A STR_n STR_y "\0"
#define STRING_Arabic0 STR_A STR_r STR_a STR_b STR_i STR_c "\0"
#define STRING_Armenian0 STR_A STR_r STR_m STR_e STR_n STR_i STR_a STR_n "\0"
@@ -254,6 +276,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#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_Hatran0 STR_H STR_a STR_t STR_r STR_a STR_n "\0"
#define STRING_Hebrew0 STR_H STR_e STR_b STR_r STR_e STR_w "\0"
#define STRING_Hiragana0 STR_H STR_i STR_r STR_a STR_g STR_a STR_n STR_a "\0"
#define STRING_Imperial_Aramaic0 STR_I STR_m STR_p STR_e STR_r STR_i STR_a STR_l STR_UNDERSCORE STR_A STR_r STR_a STR_m STR_a STR_i STR_c "\0"
@@ -301,6 +324,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Modi0 STR_M STR_o STR_d STR_i "\0"
#define STRING_Mongolian0 STR_M STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0"
#define STRING_Mro0 STR_M STR_r STR_o "\0"
+#define STRING_Multani0 STR_M STR_u STR_l STR_t STR_a STR_n STR_i "\0"
#define STRING_Myanmar0 STR_M STR_y STR_a STR_n STR_m STR_a STR_r "\0"
#define STRING_N0 STR_N "\0"
#define STRING_Nabataean0 STR_N STR_a STR_b STR_a STR_t STR_a STR_e STR_a STR_n "\0"
@@ -311,6 +335,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#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_Hungarian0 STR_O STR_l STR_d STR_UNDERSCORE STR_H STR_u STR_n STR_g STR_a STR_r STR_i STR_a STR_n "\0"
#define STRING_Old_Italic0 STR_O STR_l STR_d STR_UNDERSCORE STR_I STR_t STR_a STR_l STR_i STR_c "\0"
#define STRING_Old_North_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_N STR_o STR_r STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0"
#define STRING_Old_Permic0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_m STR_i STR_c "\0"
@@ -342,6 +367,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Sharada0 STR_S STR_h STR_a STR_r STR_a STR_d STR_a "\0"
#define STRING_Shavian0 STR_S STR_h STR_a STR_v STR_i STR_a STR_n "\0"
#define STRING_Siddham0 STR_S STR_i STR_d STR_d STR_h STR_a STR_m "\0"
+#define STRING_SignWriting0 STR_S STR_i STR_g STR_n STR_W STR_r STR_i STR_t STR_i STR_n STR_g "\0"
#define STRING_Sinhala0 STR_S STR_i STR_n STR_h STR_a STR_l STR_a "\0"
#define STRING_Sk0 STR_S STR_k "\0"
#define STRING_Sm0 STR_S STR_m "\0"
@@ -378,6 +404,8 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Zs0 STR_Z STR_s "\0"
const char PRIV(utt_names)[] =
+ STRING_Ahom0
+ STRING_Anatolian_Hieroglyphs0
STRING_Any0
STRING_Arabic0
STRING_Armenian0
@@ -425,6 +453,7 @@ const char PRIV(utt_names)[] =
STRING_Han0
STRING_Hangul0
STRING_Hanunoo0
+ STRING_Hatran0
STRING_Hebrew0
STRING_Hiragana0
STRING_Imperial_Aramaic0
@@ -472,6 +501,7 @@ const char PRIV(utt_names)[] =
STRING_Modi0
STRING_Mongolian0
STRING_Mro0
+ STRING_Multani0
STRING_Myanmar0
STRING_N0
STRING_Nabataean0
@@ -482,6 +512,7 @@ const char PRIV(utt_names)[] =
STRING_No0
STRING_Ogham0
STRING_Ol_Chiki0
+ STRING_Old_Hungarian0
STRING_Old_Italic0
STRING_Old_North_Arabian0
STRING_Old_Permic0
@@ -513,6 +544,7 @@ const char PRIV(utt_names)[] =
STRING_Sharada0
STRING_Shavian0
STRING_Siddham0
+ STRING_SignWriting0
STRING_Sinhala0
STRING_Sk0
STRING_Sm0
@@ -549,179 +581,185 @@ const char PRIV(utt_names)[] =
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_Bassa_Vah },
- { 53, PT_SC, ucp_Batak },
- { 59, PT_SC, ucp_Bengali },
- { 67, PT_SC, ucp_Bopomofo },
- { 76, PT_SC, ucp_Brahmi },
- { 83, PT_SC, ucp_Braille },
- { 91, PT_SC, ucp_Buginese },
- { 100, PT_SC, ucp_Buhid },
- { 106, PT_GC, ucp_C },
- { 108, PT_SC, ucp_Canadian_Aboriginal },
- { 128, PT_SC, ucp_Carian },
- { 135, PT_SC, ucp_Caucasian_Albanian },
- { 154, PT_PC, ucp_Cc },
- { 157, PT_PC, ucp_Cf },
- { 160, PT_SC, ucp_Chakma },
- { 167, PT_SC, ucp_Cham },
- { 172, PT_SC, ucp_Cherokee },
- { 181, PT_PC, ucp_Cn },
- { 184, PT_PC, ucp_Co },
- { 187, PT_SC, ucp_Common },
- { 194, PT_SC, ucp_Coptic },
- { 201, PT_PC, ucp_Cs },
- { 204, PT_SC, ucp_Cuneiform },
- { 214, PT_SC, ucp_Cypriot },
- { 222, PT_SC, ucp_Cyrillic },
- { 231, PT_SC, ucp_Deseret },
- { 239, PT_SC, ucp_Devanagari },
- { 250, PT_SC, ucp_Duployan },
- { 259, PT_SC, ucp_Egyptian_Hieroglyphs },
- { 280, PT_SC, ucp_Elbasan },
- { 288, PT_SC, ucp_Ethiopic },
- { 297, PT_SC, ucp_Georgian },
- { 306, PT_SC, ucp_Glagolitic },
- { 317, PT_SC, ucp_Gothic },
- { 324, PT_SC, ucp_Grantha },
- { 332, PT_SC, ucp_Greek },
- { 338, PT_SC, ucp_Gujarati },
- { 347, PT_SC, ucp_Gurmukhi },
- { 356, PT_SC, ucp_Han },
- { 360, PT_SC, ucp_Hangul },
- { 367, PT_SC, ucp_Hanunoo },
- { 375, PT_SC, ucp_Hebrew },
- { 382, PT_SC, ucp_Hiragana },
- { 391, PT_SC, ucp_Imperial_Aramaic },
- { 408, PT_SC, ucp_Inherited },
- { 418, PT_SC, ucp_Inscriptional_Pahlavi },
- { 440, PT_SC, ucp_Inscriptional_Parthian },
- { 463, PT_SC, ucp_Javanese },
- { 472, PT_SC, ucp_Kaithi },
- { 479, PT_SC, ucp_Kannada },
- { 487, PT_SC, ucp_Katakana },
- { 496, PT_SC, ucp_Kayah_Li },
- { 505, PT_SC, ucp_Kharoshthi },
- { 516, PT_SC, ucp_Khmer },
- { 522, PT_SC, ucp_Khojki },
- { 529, PT_SC, ucp_Khudawadi },
- { 539, PT_GC, ucp_L },
- { 541, PT_LAMP, 0 },
- { 544, PT_SC, ucp_Lao },
- { 548, PT_SC, ucp_Latin },
- { 554, PT_SC, ucp_Lepcha },
- { 561, PT_SC, ucp_Limbu },
- { 567, PT_SC, ucp_Linear_A },
- { 576, PT_SC, ucp_Linear_B },
- { 585, PT_SC, ucp_Lisu },
- { 590, PT_PC, ucp_Ll },
- { 593, PT_PC, ucp_Lm },
- { 596, PT_PC, ucp_Lo },
- { 599, PT_PC, ucp_Lt },
- { 602, PT_PC, ucp_Lu },
- { 605, PT_SC, ucp_Lycian },
- { 612, PT_SC, ucp_Lydian },
- { 619, PT_GC, ucp_M },
- { 621, PT_SC, ucp_Mahajani },
- { 630, PT_SC, ucp_Malayalam },
- { 640, PT_SC, ucp_Mandaic },
- { 648, PT_SC, ucp_Manichaean },
- { 659, PT_PC, ucp_Mc },
- { 662, PT_PC, ucp_Me },
- { 665, PT_SC, ucp_Meetei_Mayek },
- { 678, PT_SC, ucp_Mende_Kikakui },
- { 692, PT_SC, ucp_Meroitic_Cursive },
- { 709, PT_SC, ucp_Meroitic_Hieroglyphs },
- { 730, PT_SC, ucp_Miao },
- { 735, PT_PC, ucp_Mn },
- { 738, PT_SC, ucp_Modi },
- { 743, PT_SC, ucp_Mongolian },
- { 753, PT_SC, ucp_Mro },
- { 757, PT_SC, ucp_Myanmar },
- { 765, PT_GC, ucp_N },
- { 767, PT_SC, ucp_Nabataean },
- { 777, PT_PC, ucp_Nd },
- { 780, PT_SC, ucp_New_Tai_Lue },
- { 792, PT_SC, ucp_Nko },
- { 796, PT_PC, ucp_Nl },
- { 799, PT_PC, ucp_No },
- { 802, PT_SC, ucp_Ogham },
- { 808, PT_SC, ucp_Ol_Chiki },
- { 817, PT_SC, ucp_Old_Italic },
- { 828, PT_SC, ucp_Old_North_Arabian },
- { 846, PT_SC, ucp_Old_Permic },
- { 857, PT_SC, ucp_Old_Persian },
- { 869, PT_SC, ucp_Old_South_Arabian },
- { 887, PT_SC, ucp_Old_Turkic },
- { 898, PT_SC, ucp_Oriya },
- { 904, PT_SC, ucp_Osmanya },
- { 912, PT_GC, ucp_P },
- { 914, PT_SC, ucp_Pahawh_Hmong },
- { 927, PT_SC, ucp_Palmyrene },
- { 937, PT_SC, ucp_Pau_Cin_Hau },
- { 949, PT_PC, ucp_Pc },
- { 952, PT_PC, ucp_Pd },
- { 955, PT_PC, ucp_Pe },
- { 958, PT_PC, ucp_Pf },
- { 961, PT_SC, ucp_Phags_Pa },
- { 970, PT_SC, ucp_Phoenician },
- { 981, PT_PC, ucp_Pi },
- { 984, PT_PC, ucp_Po },
- { 987, PT_PC, ucp_Ps },
- { 990, PT_SC, ucp_Psalter_Pahlavi },
- { 1006, PT_SC, ucp_Rejang },
- { 1013, PT_SC, ucp_Runic },
- { 1019, PT_GC, ucp_S },
- { 1021, PT_SC, ucp_Samaritan },
- { 1031, PT_SC, ucp_Saurashtra },
- { 1042, PT_PC, ucp_Sc },
- { 1045, PT_SC, ucp_Sharada },
- { 1053, PT_SC, ucp_Shavian },
- { 1061, PT_SC, ucp_Siddham },
- { 1069, PT_SC, ucp_Sinhala },
- { 1077, PT_PC, ucp_Sk },
- { 1080, PT_PC, ucp_Sm },
- { 1083, PT_PC, ucp_So },
- { 1086, PT_SC, ucp_Sora_Sompeng },
- { 1099, PT_SC, ucp_Sundanese },
- { 1109, PT_SC, ucp_Syloti_Nagri },
- { 1122, PT_SC, ucp_Syriac },
- { 1129, PT_SC, ucp_Tagalog },
- { 1137, PT_SC, ucp_Tagbanwa },
- { 1146, PT_SC, ucp_Tai_Le },
- { 1153, PT_SC, ucp_Tai_Tham },
- { 1162, PT_SC, ucp_Tai_Viet },
- { 1171, PT_SC, ucp_Takri },
- { 1177, PT_SC, ucp_Tamil },
- { 1183, PT_SC, ucp_Telugu },
- { 1190, PT_SC, ucp_Thaana },
- { 1197, PT_SC, ucp_Thai },
- { 1202, PT_SC, ucp_Tibetan },
- { 1210, PT_SC, ucp_Tifinagh },
- { 1219, PT_SC, ucp_Tirhuta },
- { 1227, PT_SC, ucp_Ugaritic },
- { 1236, PT_SC, ucp_Vai },
- { 1240, PT_SC, ucp_Warang_Citi },
- { 1252, PT_ALNUM, 0 },
- { 1256, PT_PXSPACE, 0 },
- { 1260, PT_SPACE, 0 },
- { 1264, PT_UCNC, 0 },
- { 1268, PT_WORD, 0 },
- { 1272, PT_SC, ucp_Yi },
- { 1275, PT_GC, ucp_Z },
- { 1277, PT_PC, ucp_Zl },
- { 1280, PT_PC, ucp_Zp },
- { 1283, PT_PC, ucp_Zs }
+ { 0, PT_SC, ucp_Ahom },
+ { 5, PT_SC, ucp_Anatolian_Hieroglyphs },
+ { 27, PT_ANY, 0 },
+ { 31, PT_SC, ucp_Arabic },
+ { 38, PT_SC, ucp_Armenian },
+ { 47, PT_SC, ucp_Avestan },
+ { 55, PT_SC, ucp_Balinese },
+ { 64, PT_SC, ucp_Bamum },
+ { 70, PT_SC, ucp_Bassa_Vah },
+ { 80, PT_SC, ucp_Batak },
+ { 86, PT_SC, ucp_Bengali },
+ { 94, PT_SC, ucp_Bopomofo },
+ { 103, PT_SC, ucp_Brahmi },
+ { 110, PT_SC, ucp_Braille },
+ { 118, PT_SC, ucp_Buginese },
+ { 127, PT_SC, ucp_Buhid },
+ { 133, PT_GC, ucp_C },
+ { 135, PT_SC, ucp_Canadian_Aboriginal },
+ { 155, PT_SC, ucp_Carian },
+ { 162, PT_SC, ucp_Caucasian_Albanian },
+ { 181, PT_PC, ucp_Cc },
+ { 184, PT_PC, ucp_Cf },
+ { 187, PT_SC, ucp_Chakma },
+ { 194, PT_SC, ucp_Cham },
+ { 199, PT_SC, ucp_Cherokee },
+ { 208, PT_PC, ucp_Cn },
+ { 211, PT_PC, ucp_Co },
+ { 214, PT_SC, ucp_Common },
+ { 221, PT_SC, ucp_Coptic },
+ { 228, PT_PC, ucp_Cs },
+ { 231, PT_SC, ucp_Cuneiform },
+ { 241, PT_SC, ucp_Cypriot },
+ { 249, PT_SC, ucp_Cyrillic },
+ { 258, PT_SC, ucp_Deseret },
+ { 266, PT_SC, ucp_Devanagari },
+ { 277, PT_SC, ucp_Duployan },
+ { 286, PT_SC, ucp_Egyptian_Hieroglyphs },
+ { 307, PT_SC, ucp_Elbasan },
+ { 315, PT_SC, ucp_Ethiopic },
+ { 324, PT_SC, ucp_Georgian },
+ { 333, PT_SC, ucp_Glagolitic },
+ { 344, PT_SC, ucp_Gothic },
+ { 351, PT_SC, ucp_Grantha },
+ { 359, PT_SC, ucp_Greek },
+ { 365, PT_SC, ucp_Gujarati },
+ { 374, PT_SC, ucp_Gurmukhi },
+ { 383, PT_SC, ucp_Han },
+ { 387, PT_SC, ucp_Hangul },
+ { 394, PT_SC, ucp_Hanunoo },
+ { 402, PT_SC, ucp_Hatran },
+ { 409, PT_SC, ucp_Hebrew },
+ { 416, PT_SC, ucp_Hiragana },
+ { 425, PT_SC, ucp_Imperial_Aramaic },
+ { 442, PT_SC, ucp_Inherited },
+ { 452, PT_SC, ucp_Inscriptional_Pahlavi },
+ { 474, PT_SC, ucp_Inscriptional_Parthian },
+ { 497, PT_SC, ucp_Javanese },
+ { 506, PT_SC, ucp_Kaithi },
+ { 513, PT_SC, ucp_Kannada },
+ { 521, PT_SC, ucp_Katakana },
+ { 530, PT_SC, ucp_Kayah_Li },
+ { 539, PT_SC, ucp_Kharoshthi },
+ { 550, PT_SC, ucp_Khmer },
+ { 556, PT_SC, ucp_Khojki },
+ { 563, PT_SC, ucp_Khudawadi },
+ { 573, PT_GC, ucp_L },
+ { 575, PT_LAMP, 0 },
+ { 578, PT_SC, ucp_Lao },
+ { 582, PT_SC, ucp_Latin },
+ { 588, PT_SC, ucp_Lepcha },
+ { 595, PT_SC, ucp_Limbu },
+ { 601, PT_SC, ucp_Linear_A },
+ { 610, PT_SC, ucp_Linear_B },
+ { 619, PT_SC, ucp_Lisu },
+ { 624, PT_PC, ucp_Ll },
+ { 627, PT_PC, ucp_Lm },
+ { 630, PT_PC, ucp_Lo },
+ { 633, PT_PC, ucp_Lt },
+ { 636, PT_PC, ucp_Lu },
+ { 639, PT_SC, ucp_Lycian },
+ { 646, PT_SC, ucp_Lydian },
+ { 653, PT_GC, ucp_M },
+ { 655, PT_SC, ucp_Mahajani },
+ { 664, PT_SC, ucp_Malayalam },
+ { 674, PT_SC, ucp_Mandaic },
+ { 682, PT_SC, ucp_Manichaean },
+ { 693, PT_PC, ucp_Mc },
+ { 696, PT_PC, ucp_Me },
+ { 699, PT_SC, ucp_Meetei_Mayek },
+ { 712, PT_SC, ucp_Mende_Kikakui },
+ { 726, PT_SC, ucp_Meroitic_Cursive },
+ { 743, PT_SC, ucp_Meroitic_Hieroglyphs },
+ { 764, PT_SC, ucp_Miao },
+ { 769, PT_PC, ucp_Mn },
+ { 772, PT_SC, ucp_Modi },
+ { 777, PT_SC, ucp_Mongolian },
+ { 787, PT_SC, ucp_Mro },
+ { 791, PT_SC, ucp_Multani },
+ { 799, PT_SC, ucp_Myanmar },
+ { 807, PT_GC, ucp_N },
+ { 809, PT_SC, ucp_Nabataean },
+ { 819, PT_PC, ucp_Nd },
+ { 822, PT_SC, ucp_New_Tai_Lue },
+ { 834, PT_SC, ucp_Nko },
+ { 838, PT_PC, ucp_Nl },
+ { 841, PT_PC, ucp_No },
+ { 844, PT_SC, ucp_Ogham },
+ { 850, PT_SC, ucp_Ol_Chiki },
+ { 859, PT_SC, ucp_Old_Hungarian },
+ { 873, PT_SC, ucp_Old_Italic },
+ { 884, PT_SC, ucp_Old_North_Arabian },
+ { 902, PT_SC, ucp_Old_Permic },
+ { 913, PT_SC, ucp_Old_Persian },
+ { 925, PT_SC, ucp_Old_South_Arabian },
+ { 943, PT_SC, ucp_Old_Turkic },
+ { 954, PT_SC, ucp_Oriya },
+ { 960, PT_SC, ucp_Osmanya },
+ { 968, PT_GC, ucp_P },
+ { 970, PT_SC, ucp_Pahawh_Hmong },
+ { 983, PT_SC, ucp_Palmyrene },
+ { 993, PT_SC, ucp_Pau_Cin_Hau },
+ { 1005, PT_PC, ucp_Pc },
+ { 1008, PT_PC, ucp_Pd },
+ { 1011, PT_PC, ucp_Pe },
+ { 1014, PT_PC, ucp_Pf },
+ { 1017, PT_SC, ucp_Phags_Pa },
+ { 1026, PT_SC, ucp_Phoenician },
+ { 1037, PT_PC, ucp_Pi },
+ { 1040, PT_PC, ucp_Po },
+ { 1043, PT_PC, ucp_Ps },
+ { 1046, PT_SC, ucp_Psalter_Pahlavi },
+ { 1062, PT_SC, ucp_Rejang },
+ { 1069, PT_SC, ucp_Runic },
+ { 1075, PT_GC, ucp_S },
+ { 1077, PT_SC, ucp_Samaritan },
+ { 1087, PT_SC, ucp_Saurashtra },
+ { 1098, PT_PC, ucp_Sc },
+ { 1101, PT_SC, ucp_Sharada },
+ { 1109, PT_SC, ucp_Shavian },
+ { 1117, PT_SC, ucp_Siddham },
+ { 1125, PT_SC, ucp_SignWriting },
+ { 1137, PT_SC, ucp_Sinhala },
+ { 1145, PT_PC, ucp_Sk },
+ { 1148, PT_PC, ucp_Sm },
+ { 1151, PT_PC, ucp_So },
+ { 1154, PT_SC, ucp_Sora_Sompeng },
+ { 1167, PT_SC, ucp_Sundanese },
+ { 1177, PT_SC, ucp_Syloti_Nagri },
+ { 1190, PT_SC, ucp_Syriac },
+ { 1197, PT_SC, ucp_Tagalog },
+ { 1205, PT_SC, ucp_Tagbanwa },
+ { 1214, PT_SC, ucp_Tai_Le },
+ { 1221, PT_SC, ucp_Tai_Tham },
+ { 1230, PT_SC, ucp_Tai_Viet },
+ { 1239, PT_SC, ucp_Takri },
+ { 1245, PT_SC, ucp_Tamil },
+ { 1251, PT_SC, ucp_Telugu },
+ { 1258, PT_SC, ucp_Thaana },
+ { 1265, PT_SC, ucp_Thai },
+ { 1270, PT_SC, ucp_Tibetan },
+ { 1278, PT_SC, ucp_Tifinagh },
+ { 1287, PT_SC, ucp_Tirhuta },
+ { 1295, PT_SC, ucp_Ugaritic },
+ { 1304, PT_SC, ucp_Vai },
+ { 1308, PT_SC, ucp_Warang_Citi },
+ { 1320, PT_ALNUM, 0 },
+ { 1324, PT_PXSPACE, 0 },
+ { 1328, PT_SPACE, 0 },
+ { 1332, PT_UCNC, 0 },
+ { 1336, PT_WORD, 0 },
+ { 1340, PT_SC, ucp_Yi },
+ { 1343, PT_GC, ucp_Z },
+ { 1345, PT_PC, ucp_Zl },
+ { 1348, PT_PC, ucp_Zp },
+ { 1351, PT_PC, ucp_Zs }
};
-const int PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
+const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
-#endif /* SUPPORT_UTF */
+#endif /* SUPPORT_UNICODE */
-/* End of pcre_tables.c */
+/* End of pcre2_tables.c */
diff --git a/src/3rdparty/pcre/pcre_ucd.c b/src/3rdparty/pcre2/src/pcre2_ucd.c
index 69c4fd42c3..116f537b38 100644
--- a/src/3rdparty/pcre/pcre_ucd.c
+++ b/src/3rdparty/pcre2/src/pcre2_ucd.c
@@ -2,28 +2,29 @@
Do not modify it by hand. Instead modify the script and run it
to regenerate this code.
-As well as being part of the PCRE library, this module is #included
-by the pcretest program, which redefines the PRIV macro to change
-table names from _pcre_xxx to xxxx, thereby avoiding name clashes
+As well as being part of the PCRE2 library, this module is #included
+by the pcre2test program, which redefines the PRIV macro to change
+table names from _pcre2_xxx to xxxx, thereby avoiding name clashes
with the library. At present, just one of these tables is actually
needed. */
-#ifndef PCRE_INCLUDED
+#ifndef PCRE2_PCRE2TEST
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include "pcre_internal.h"
+#include "pcre2_internal.h"
-#endif /* PCRE_INCLUDED */
+#endif /* PCRE2_PCRE2TEST */
/* Unicode character database. */
/* This file was autogenerated by the MultiStage2.py script. */
-/* Total size: 72576 bytes, block size: 128. */
+/* Total size: 75072 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
+/* The tables herein are needed only when UCP support is built,
+and in PCRE2 that happens automatically with UTF support.
+This module should not be referenced otherwise, so
it should not matter whether it is compiled or not. However
a comment was received about space saving - maybe the guy linked
all the modules rather than using a library - so we include a
@@ -31,28 +32,30 @@ 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
+#ifndef SUPPORT_UNICODE
const ucd_record PRIV(ucd_records)[] = {{0,0,0,0,0 }};
-const pcre_uint8 PRIV(ucd_stage1)[] = {0};
-const pcre_uint16 PRIV(ucd_stage2)[] = {0};
-const pcre_uint32 PRIV(ucd_caseless_sets)[] = {0};
+const uint8_t PRIV(ucd_stage1)[] = {0};
+const uint16_t PRIV(ucd_stage2)[] = {0};
+const uint32_t PRIV(ucd_caseless_sets)[] = {0};
#else
+const char *PRIV(unicode_version) = "8.0.0";
+
/* When recompiling tables with a new Unicode version, please check the
-types in this structure definition from pcre_internal.h (the actual
+types in this structure definition from pcre2_internal.h (the actual
field names will be different):
typedef struct {
-pcre_uint8 property_0;
-pcre_uint8 property_1;
-pcre_uint8 property_2;
-pcre_uint8 property_3;
+uint8_t property_0;
+uint8_t property_1;
+uint8_t property_2;
+uint8_t property_3;
pcre_int32 property_4;
} ucd_record;
*/
-const pcre_uint32 PRIV(ucd_caseless_sets)[] = {
+const uint32_t PRIV(ucd_caseless_sets)[] = {
NOTACHAR,
0x0053, 0x0073, 0x017f, NOTACHAR,
0x01c4, 0x01c5, 0x01c6, NOTACHAR,
@@ -75,11 +78,11 @@ const pcre_uint32 PRIV(ucd_caseless_sets)[] = {
0x00c5, 0x00e5, 0x212b, NOTACHAR,
};
-/* When #included in pcretest, we don't need this large table. */
+/* When #included in pcre2test, we don't need this large table. */
-#ifndef PCRE_INCLUDED
+#ifndef PCRE2_PCRE2TEST
-const ucd_record PRIV(ucd_records)[] = { /* 5760 bytes, record size 8 */
+const ucd_record PRIV(ucd_records)[] = { /* 5952 bytes, record size 8 */
{ 9, 0, 2, 0, 0, }, /* 0 */
{ 9, 0, 1, 0, 0, }, /* 1 */
{ 9, 0, 0, 0, 0, }, /* 2 */
@@ -185,624 +188,648 @@ const ucd_record PRIV(ucd_records)[] = { /* 5760 bytes, record size 8 */
{ 33, 5, 12, 0, -217, }, /* 102 */
{ 33, 5, 12, 0, -71, }, /* 103 */
{ 33, 5, 12, 0, -219, }, /* 104 */
- { 33, 5, 12, 0, 42258, }, /* 105 */
- { 33, 6, 12, 0, 0, }, /* 106 */
- { 9, 6, 12, 0, 0, }, /* 107 */
- { 3, 24, 12, 0, 0, }, /* 108 */
- { 27, 12, 3, 0, 0, }, /* 109 */
- { 27, 12, 3, 21, 116, }, /* 110 */
- { 19, 9, 12, 0, 1, }, /* 111 */
- { 19, 5, 12, 0, -1, }, /* 112 */
- { 19, 24, 12, 0, 0, }, /* 113 */
- { 9, 2, 12, 0, 0, }, /* 114 */
- { 19, 6, 12, 0, 0, }, /* 115 */
- { 19, 5, 12, 0, 130, }, /* 116 */
- { 19, 9, 12, 0, 116, }, /* 117 */
- { 19, 9, 12, 0, 38, }, /* 118 */
- { 19, 9, 12, 0, 37, }, /* 119 */
- { 19, 9, 12, 0, 64, }, /* 120 */
- { 19, 9, 12, 0, 63, }, /* 121 */
- { 19, 5, 12, 0, 0, }, /* 122 */
- { 19, 9, 12, 0, 32, }, /* 123 */
- { 19, 9, 12, 34, 32, }, /* 124 */
- { 19, 9, 12, 59, 32, }, /* 125 */
- { 19, 9, 12, 38, 32, }, /* 126 */
- { 19, 9, 12, 21, 32, }, /* 127 */
- { 19, 9, 12, 51, 32, }, /* 128 */
- { 19, 9, 12, 26, 32, }, /* 129 */
- { 19, 9, 12, 47, 32, }, /* 130 */
- { 19, 9, 12, 55, 32, }, /* 131 */
- { 19, 9, 12, 30, 32, }, /* 132 */
- { 19, 9, 12, 43, 32, }, /* 133 */
- { 19, 9, 12, 67, 32, }, /* 134 */
- { 19, 5, 12, 0, -38, }, /* 135 */
- { 19, 5, 12, 0, -37, }, /* 136 */
- { 19, 5, 12, 0, -32, }, /* 137 */
- { 19, 5, 12, 34, -32, }, /* 138 */
- { 19, 5, 12, 59, -32, }, /* 139 */
- { 19, 5, 12, 38, -32, }, /* 140 */
- { 19, 5, 12, 21, -116, }, /* 141 */
- { 19, 5, 12, 51, -32, }, /* 142 */
- { 19, 5, 12, 26, -775, }, /* 143 */
- { 19, 5, 12, 47, -32, }, /* 144 */
- { 19, 5, 12, 55, -32, }, /* 145 */
- { 19, 5, 12, 30, 1, }, /* 146 */
- { 19, 5, 12, 30, -32, }, /* 147 */
- { 19, 5, 12, 43, -32, }, /* 148 */
- { 19, 5, 12, 67, -32, }, /* 149 */
- { 19, 5, 12, 0, -64, }, /* 150 */
- { 19, 5, 12, 0, -63, }, /* 151 */
- { 19, 9, 12, 0, 8, }, /* 152 */
- { 19, 5, 12, 34, -30, }, /* 153 */
- { 19, 5, 12, 38, -25, }, /* 154 */
- { 19, 9, 12, 0, 0, }, /* 155 */
- { 19, 5, 12, 43, -15, }, /* 156 */
- { 19, 5, 12, 47, -22, }, /* 157 */
- { 19, 5, 12, 0, -8, }, /* 158 */
- { 10, 9, 12, 0, 1, }, /* 159 */
- { 10, 5, 12, 0, -1, }, /* 160 */
- { 19, 5, 12, 51, -54, }, /* 161 */
- { 19, 5, 12, 55, -48, }, /* 162 */
- { 19, 5, 12, 0, 7, }, /* 163 */
- { 19, 5, 12, 0, -116, }, /* 164 */
- { 19, 9, 12, 38, -60, }, /* 165 */
- { 19, 5, 12, 59, -64, }, /* 166 */
- { 19, 25, 12, 0, 0, }, /* 167 */
- { 19, 9, 12, 0, -7, }, /* 168 */
- { 19, 9, 12, 0, -130, }, /* 169 */
- { 12, 9, 12, 0, 80, }, /* 170 */
- { 12, 9, 12, 0, 32, }, /* 171 */
- { 12, 5, 12, 0, -32, }, /* 172 */
- { 12, 5, 12, 0, -80, }, /* 173 */
- { 12, 9, 12, 0, 1, }, /* 174 */
- { 12, 5, 12, 0, -1, }, /* 175 */
- { 12, 26, 12, 0, 0, }, /* 176 */
- { 12, 12, 3, 0, 0, }, /* 177 */
- { 12, 11, 3, 0, 0, }, /* 178 */
- { 12, 9, 12, 0, 15, }, /* 179 */
- { 12, 5, 12, 0, -15, }, /* 180 */
- { 1, 9, 12, 0, 48, }, /* 181 */
- { 1, 6, 12, 0, 0, }, /* 182 */
- { 1, 21, 12, 0, 0, }, /* 183 */
- { 1, 5, 12, 0, -48, }, /* 184 */
- { 1, 5, 12, 0, 0, }, /* 185 */
- { 1, 17, 12, 0, 0, }, /* 186 */
- { 1, 26, 12, 0, 0, }, /* 187 */
- { 1, 23, 12, 0, 0, }, /* 188 */
- { 25, 12, 3, 0, 0, }, /* 189 */
- { 25, 17, 12, 0, 0, }, /* 190 */
- { 25, 21, 12, 0, 0, }, /* 191 */
- { 25, 7, 12, 0, 0, }, /* 192 */
- { 0, 1, 2, 0, 0, }, /* 193 */
- { 0, 25, 12, 0, 0, }, /* 194 */
- { 0, 21, 12, 0, 0, }, /* 195 */
- { 0, 23, 12, 0, 0, }, /* 196 */
- { 0, 26, 12, 0, 0, }, /* 197 */
- { 0, 12, 3, 0, 0, }, /* 198 */
- { 0, 7, 12, 0, 0, }, /* 199 */
- { 0, 6, 12, 0, 0, }, /* 200 */
+ { 33, 5, 12, 0, 42261, }, /* 105 */
+ { 33, 5, 12, 0, 42258, }, /* 106 */
+ { 33, 6, 12, 0, 0, }, /* 107 */
+ { 9, 6, 12, 0, 0, }, /* 108 */
+ { 3, 24, 12, 0, 0, }, /* 109 */
+ { 27, 12, 3, 0, 0, }, /* 110 */
+ { 27, 12, 3, 21, 116, }, /* 111 */
+ { 19, 9, 12, 0, 1, }, /* 112 */
+ { 19, 5, 12, 0, -1, }, /* 113 */
+ { 19, 24, 12, 0, 0, }, /* 114 */
+ { 9, 2, 12, 0, 0, }, /* 115 */
+ { 19, 6, 12, 0, 0, }, /* 116 */
+ { 19, 5, 12, 0, 130, }, /* 117 */
+ { 19, 9, 12, 0, 116, }, /* 118 */
+ { 19, 9, 12, 0, 38, }, /* 119 */
+ { 19, 9, 12, 0, 37, }, /* 120 */
+ { 19, 9, 12, 0, 64, }, /* 121 */
+ { 19, 9, 12, 0, 63, }, /* 122 */
+ { 19, 5, 12, 0, 0, }, /* 123 */
+ { 19, 9, 12, 0, 32, }, /* 124 */
+ { 19, 9, 12, 34, 32, }, /* 125 */
+ { 19, 9, 12, 59, 32, }, /* 126 */
+ { 19, 9, 12, 38, 32, }, /* 127 */
+ { 19, 9, 12, 21, 32, }, /* 128 */
+ { 19, 9, 12, 51, 32, }, /* 129 */
+ { 19, 9, 12, 26, 32, }, /* 130 */
+ { 19, 9, 12, 47, 32, }, /* 131 */
+ { 19, 9, 12, 55, 32, }, /* 132 */
+ { 19, 9, 12, 30, 32, }, /* 133 */
+ { 19, 9, 12, 43, 32, }, /* 134 */
+ { 19, 9, 12, 67, 32, }, /* 135 */
+ { 19, 5, 12, 0, -38, }, /* 136 */
+ { 19, 5, 12, 0, -37, }, /* 137 */
+ { 19, 5, 12, 0, -32, }, /* 138 */
+ { 19, 5, 12, 34, -32, }, /* 139 */
+ { 19, 5, 12, 59, -32, }, /* 140 */
+ { 19, 5, 12, 38, -32, }, /* 141 */
+ { 19, 5, 12, 21, -116, }, /* 142 */
+ { 19, 5, 12, 51, -32, }, /* 143 */
+ { 19, 5, 12, 26, -775, }, /* 144 */
+ { 19, 5, 12, 47, -32, }, /* 145 */
+ { 19, 5, 12, 55, -32, }, /* 146 */
+ { 19, 5, 12, 30, 1, }, /* 147 */
+ { 19, 5, 12, 30, -32, }, /* 148 */
+ { 19, 5, 12, 43, -32, }, /* 149 */
+ { 19, 5, 12, 67, -32, }, /* 150 */
+ { 19, 5, 12, 0, -64, }, /* 151 */
+ { 19, 5, 12, 0, -63, }, /* 152 */
+ { 19, 9, 12, 0, 8, }, /* 153 */
+ { 19, 5, 12, 34, -30, }, /* 154 */
+ { 19, 5, 12, 38, -25, }, /* 155 */
+ { 19, 9, 12, 0, 0, }, /* 156 */
+ { 19, 5, 12, 43, -15, }, /* 157 */
+ { 19, 5, 12, 47, -22, }, /* 158 */
+ { 19, 5, 12, 0, -8, }, /* 159 */
+ { 10, 9, 12, 0, 1, }, /* 160 */
+ { 10, 5, 12, 0, -1, }, /* 161 */
+ { 19, 5, 12, 51, -54, }, /* 162 */
+ { 19, 5, 12, 55, -48, }, /* 163 */
+ { 19, 5, 12, 0, 7, }, /* 164 */
+ { 19, 5, 12, 0, -116, }, /* 165 */
+ { 19, 9, 12, 38, -60, }, /* 166 */
+ { 19, 5, 12, 59, -64, }, /* 167 */
+ { 19, 25, 12, 0, 0, }, /* 168 */
+ { 19, 9, 12, 0, -7, }, /* 169 */
+ { 19, 9, 12, 0, -130, }, /* 170 */
+ { 12, 9, 12, 0, 80, }, /* 171 */
+ { 12, 9, 12, 0, 32, }, /* 172 */
+ { 12, 5, 12, 0, -32, }, /* 173 */
+ { 12, 5, 12, 0, -80, }, /* 174 */
+ { 12, 9, 12, 0, 1, }, /* 175 */
+ { 12, 5, 12, 0, -1, }, /* 176 */
+ { 12, 26, 12, 0, 0, }, /* 177 */
+ { 12, 12, 3, 0, 0, }, /* 178 */
+ { 12, 11, 3, 0, 0, }, /* 179 */
+ { 12, 9, 12, 0, 15, }, /* 180 */
+ { 12, 5, 12, 0, -15, }, /* 181 */
+ { 1, 9, 12, 0, 48, }, /* 182 */
+ { 1, 6, 12, 0, 0, }, /* 183 */
+ { 1, 21, 12, 0, 0, }, /* 184 */
+ { 1, 5, 12, 0, -48, }, /* 185 */
+ { 1, 5, 12, 0, 0, }, /* 186 */
+ { 1, 17, 12, 0, 0, }, /* 187 */
+ { 1, 26, 12, 0, 0, }, /* 188 */
+ { 1, 23, 12, 0, 0, }, /* 189 */
+ { 25, 12, 3, 0, 0, }, /* 190 */
+ { 25, 17, 12, 0, 0, }, /* 191 */
+ { 25, 21, 12, 0, 0, }, /* 192 */
+ { 25, 7, 12, 0, 0, }, /* 193 */
+ { 0, 1, 2, 0, 0, }, /* 194 */
+ { 0, 25, 12, 0, 0, }, /* 195 */
+ { 0, 21, 12, 0, 0, }, /* 196 */
+ { 0, 23, 12, 0, 0, }, /* 197 */
+ { 0, 26, 12, 0, 0, }, /* 198 */
+ { 0, 12, 3, 0, 0, }, /* 199 */
+ { 0, 7, 12, 0, 0, }, /* 200 */
{ 0, 13, 12, 0, 0, }, /* 201 */
- { 49, 21, 12, 0, 0, }, /* 202 */
- { 49, 1, 2, 0, 0, }, /* 203 */
- { 49, 7, 12, 0, 0, }, /* 204 */
- { 49, 12, 3, 0, 0, }, /* 205 */
- { 55, 7, 12, 0, 0, }, /* 206 */
- { 55, 12, 3, 0, 0, }, /* 207 */
- { 63, 13, 12, 0, 0, }, /* 208 */
- { 63, 7, 12, 0, 0, }, /* 209 */
- { 63, 12, 3, 0, 0, }, /* 210 */
- { 63, 6, 12, 0, 0, }, /* 211 */
- { 63, 26, 12, 0, 0, }, /* 212 */
- { 63, 21, 12, 0, 0, }, /* 213 */
- { 89, 7, 12, 0, 0, }, /* 214 */
- { 89, 12, 3, 0, 0, }, /* 215 */
- { 89, 6, 12, 0, 0, }, /* 216 */
- { 89, 21, 12, 0, 0, }, /* 217 */
- { 94, 7, 12, 0, 0, }, /* 218 */
- { 94, 12, 3, 0, 0, }, /* 219 */
- { 94, 21, 12, 0, 0, }, /* 220 */
- { 14, 12, 3, 0, 0, }, /* 221 */
- { 14, 10, 5, 0, 0, }, /* 222 */
- { 14, 7, 12, 0, 0, }, /* 223 */
- { 14, 13, 12, 0, 0, }, /* 224 */
- { 14, 21, 12, 0, 0, }, /* 225 */
- { 14, 6, 12, 0, 0, }, /* 226 */
- { 2, 7, 12, 0, 0, }, /* 227 */
- { 2, 12, 3, 0, 0, }, /* 228 */
- { 2, 10, 5, 0, 0, }, /* 229 */
- { 2, 10, 3, 0, 0, }, /* 230 */
- { 2, 13, 12, 0, 0, }, /* 231 */
- { 2, 23, 12, 0, 0, }, /* 232 */
- { 2, 15, 12, 0, 0, }, /* 233 */
- { 2, 26, 12, 0, 0, }, /* 234 */
- { 21, 12, 3, 0, 0, }, /* 235 */
- { 21, 10, 5, 0, 0, }, /* 236 */
- { 21, 7, 12, 0, 0, }, /* 237 */
- { 21, 13, 12, 0, 0, }, /* 238 */
- { 20, 12, 3, 0, 0, }, /* 239 */
- { 20, 10, 5, 0, 0, }, /* 240 */
- { 20, 7, 12, 0, 0, }, /* 241 */
- { 20, 13, 12, 0, 0, }, /* 242 */
- { 20, 21, 12, 0, 0, }, /* 243 */
- { 20, 23, 12, 0, 0, }, /* 244 */
- { 43, 12, 3, 0, 0, }, /* 245 */
- { 43, 10, 5, 0, 0, }, /* 246 */
- { 43, 7, 12, 0, 0, }, /* 247 */
- { 43, 10, 3, 0, 0, }, /* 248 */
- { 43, 13, 12, 0, 0, }, /* 249 */
- { 43, 26, 12, 0, 0, }, /* 250 */
- { 43, 15, 12, 0, 0, }, /* 251 */
- { 53, 12, 3, 0, 0, }, /* 252 */
- { 53, 7, 12, 0, 0, }, /* 253 */
- { 53, 10, 3, 0, 0, }, /* 254 */
- { 53, 10, 5, 0, 0, }, /* 255 */
- { 53, 13, 12, 0, 0, }, /* 256 */
- { 53, 15, 12, 0, 0, }, /* 257 */
- { 53, 26, 12, 0, 0, }, /* 258 */
- { 53, 23, 12, 0, 0, }, /* 259 */
- { 54, 12, 3, 0, 0, }, /* 260 */
- { 54, 10, 5, 0, 0, }, /* 261 */
- { 54, 7, 12, 0, 0, }, /* 262 */
- { 54, 13, 12, 0, 0, }, /* 263 */
- { 54, 15, 12, 0, 0, }, /* 264 */
- { 54, 26, 12, 0, 0, }, /* 265 */
- { 28, 12, 3, 0, 0, }, /* 266 */
- { 28, 10, 5, 0, 0, }, /* 267 */
- { 28, 7, 12, 0, 0, }, /* 268 */
- { 28, 10, 3, 0, 0, }, /* 269 */
- { 28, 13, 12, 0, 0, }, /* 270 */
- { 36, 12, 3, 0, 0, }, /* 271 */
- { 36, 10, 5, 0, 0, }, /* 272 */
- { 36, 7, 12, 0, 0, }, /* 273 */
- { 36, 10, 3, 0, 0, }, /* 274 */
- { 36, 13, 12, 0, 0, }, /* 275 */
- { 36, 15, 12, 0, 0, }, /* 276 */
- { 36, 26, 12, 0, 0, }, /* 277 */
- { 47, 10, 5, 0, 0, }, /* 278 */
- { 47, 7, 12, 0, 0, }, /* 279 */
- { 47, 12, 3, 0, 0, }, /* 280 */
- { 47, 10, 3, 0, 0, }, /* 281 */
- { 47, 13, 12, 0, 0, }, /* 282 */
- { 47, 21, 12, 0, 0, }, /* 283 */
- { 56, 7, 12, 0, 0, }, /* 284 */
- { 56, 12, 3, 0, 0, }, /* 285 */
- { 56, 7, 5, 0, 0, }, /* 286 */
- { 56, 6, 12, 0, 0, }, /* 287 */
- { 56, 21, 12, 0, 0, }, /* 288 */
- { 56, 13, 12, 0, 0, }, /* 289 */
- { 32, 7, 12, 0, 0, }, /* 290 */
- { 32, 12, 3, 0, 0, }, /* 291 */
- { 32, 7, 5, 0, 0, }, /* 292 */
- { 32, 6, 12, 0, 0, }, /* 293 */
- { 32, 13, 12, 0, 0, }, /* 294 */
- { 57, 7, 12, 0, 0, }, /* 295 */
- { 57, 26, 12, 0, 0, }, /* 296 */
- { 57, 21, 12, 0, 0, }, /* 297 */
- { 57, 12, 3, 0, 0, }, /* 298 */
- { 57, 13, 12, 0, 0, }, /* 299 */
- { 57, 15, 12, 0, 0, }, /* 300 */
- { 57, 22, 12, 0, 0, }, /* 301 */
- { 57, 18, 12, 0, 0, }, /* 302 */
- { 57, 10, 5, 0, 0, }, /* 303 */
- { 38, 7, 12, 0, 0, }, /* 304 */
- { 38, 10, 12, 0, 0, }, /* 305 */
- { 38, 12, 3, 0, 0, }, /* 306 */
- { 38, 10, 5, 0, 0, }, /* 307 */
- { 38, 13, 12, 0, 0, }, /* 308 */
- { 38, 21, 12, 0, 0, }, /* 309 */
- { 38, 26, 12, 0, 0, }, /* 310 */
- { 16, 9, 12, 0, 7264, }, /* 311 */
- { 16, 7, 12, 0, 0, }, /* 312 */
- { 16, 6, 12, 0, 0, }, /* 313 */
- { 23, 7, 6, 0, 0, }, /* 314 */
- { 23, 7, 7, 0, 0, }, /* 315 */
- { 23, 7, 8, 0, 0, }, /* 316 */
- { 15, 7, 12, 0, 0, }, /* 317 */
- { 15, 12, 3, 0, 0, }, /* 318 */
- { 15, 21, 12, 0, 0, }, /* 319 */
- { 15, 15, 12, 0, 0, }, /* 320 */
- { 15, 26, 12, 0, 0, }, /* 321 */
- { 8, 7, 12, 0, 0, }, /* 322 */
- { 7, 17, 12, 0, 0, }, /* 323 */
- { 7, 7, 12, 0, 0, }, /* 324 */
- { 7, 21, 12, 0, 0, }, /* 325 */
- { 40, 29, 12, 0, 0, }, /* 326 */
- { 40, 7, 12, 0, 0, }, /* 327 */
- { 40, 22, 12, 0, 0, }, /* 328 */
- { 40, 18, 12, 0, 0, }, /* 329 */
- { 45, 7, 12, 0, 0, }, /* 330 */
- { 45, 14, 12, 0, 0, }, /* 331 */
- { 50, 7, 12, 0, 0, }, /* 332 */
- { 50, 12, 3, 0, 0, }, /* 333 */
- { 24, 7, 12, 0, 0, }, /* 334 */
- { 24, 12, 3, 0, 0, }, /* 335 */
- { 6, 7, 12, 0, 0, }, /* 336 */
- { 6, 12, 3, 0, 0, }, /* 337 */
- { 51, 7, 12, 0, 0, }, /* 338 */
- { 51, 12, 3, 0, 0, }, /* 339 */
- { 31, 7, 12, 0, 0, }, /* 340 */
- { 31, 12, 3, 0, 0, }, /* 341 */
- { 31, 10, 5, 0, 0, }, /* 342 */
- { 31, 21, 12, 0, 0, }, /* 343 */
- { 31, 6, 12, 0, 0, }, /* 344 */
- { 31, 23, 12, 0, 0, }, /* 345 */
- { 31, 13, 12, 0, 0, }, /* 346 */
- { 31, 15, 12, 0, 0, }, /* 347 */
- { 37, 21, 12, 0, 0, }, /* 348 */
- { 37, 17, 12, 0, 0, }, /* 349 */
- { 37, 12, 3, 0, 0, }, /* 350 */
- { 37, 1, 2, 0, 0, }, /* 351 */
- { 37, 13, 12, 0, 0, }, /* 352 */
- { 37, 7, 12, 0, 0, }, /* 353 */
- { 37, 6, 12, 0, 0, }, /* 354 */
- { 34, 7, 12, 0, 0, }, /* 355 */
- { 34, 12, 3, 0, 0, }, /* 356 */
- { 34, 10, 5, 0, 0, }, /* 357 */
- { 34, 26, 12, 0, 0, }, /* 358 */
- { 34, 21, 12, 0, 0, }, /* 359 */
- { 34, 13, 12, 0, 0, }, /* 360 */
- { 52, 7, 12, 0, 0, }, /* 361 */
- { 39, 7, 12, 0, 0, }, /* 362 */
- { 39, 10, 12, 0, 0, }, /* 363 */
- { 39, 10, 5, 0, 0, }, /* 364 */
- { 39, 13, 12, 0, 0, }, /* 365 */
- { 39, 15, 12, 0, 0, }, /* 366 */
- { 39, 26, 12, 0, 0, }, /* 367 */
- { 31, 26, 12, 0, 0, }, /* 368 */
- { 5, 7, 12, 0, 0, }, /* 369 */
- { 5, 12, 3, 0, 0, }, /* 370 */
- { 5, 10, 5, 0, 0, }, /* 371 */
- { 5, 21, 12, 0, 0, }, /* 372 */
- { 90, 7, 12, 0, 0, }, /* 373 */
- { 90, 10, 5, 0, 0, }, /* 374 */
- { 90, 12, 3, 0, 0, }, /* 375 */
- { 90, 10, 12, 0, 0, }, /* 376 */
- { 90, 13, 12, 0, 0, }, /* 377 */
- { 90, 21, 12, 0, 0, }, /* 378 */
- { 90, 6, 12, 0, 0, }, /* 379 */
- { 27, 11, 3, 0, 0, }, /* 380 */
- { 61, 12, 3, 0, 0, }, /* 381 */
- { 61, 10, 5, 0, 0, }, /* 382 */
- { 61, 7, 12, 0, 0, }, /* 383 */
- { 61, 13, 12, 0, 0, }, /* 384 */
- { 61, 21, 12, 0, 0, }, /* 385 */
- { 61, 26, 12, 0, 0, }, /* 386 */
- { 75, 12, 3, 0, 0, }, /* 387 */
- { 75, 10, 5, 0, 0, }, /* 388 */
- { 75, 7, 12, 0, 0, }, /* 389 */
- { 75, 13, 12, 0, 0, }, /* 390 */
- { 92, 7, 12, 0, 0, }, /* 391 */
- { 92, 12, 3, 0, 0, }, /* 392 */
- { 92, 10, 5, 0, 0, }, /* 393 */
- { 92, 21, 12, 0, 0, }, /* 394 */
- { 69, 7, 12, 0, 0, }, /* 395 */
- { 69, 10, 5, 0, 0, }, /* 396 */
- { 69, 12, 3, 0, 0, }, /* 397 */
- { 69, 21, 12, 0, 0, }, /* 398 */
- { 69, 13, 12, 0, 0, }, /* 399 */
- { 72, 13, 12, 0, 0, }, /* 400 */
- { 72, 7, 12, 0, 0, }, /* 401 */
- { 72, 6, 12, 0, 0, }, /* 402 */
- { 72, 21, 12, 0, 0, }, /* 403 */
- { 75, 21, 12, 0, 0, }, /* 404 */
- { 9, 10, 5, 0, 0, }, /* 405 */
- { 9, 7, 12, 0, 0, }, /* 406 */
- { 12, 5, 12, 0, 0, }, /* 407 */
- { 12, 6, 12, 0, 0, }, /* 408 */
- { 33, 5, 12, 0, 35332, }, /* 409 */
- { 33, 5, 12, 0, 3814, }, /* 410 */
- { 33, 9, 12, 63, 1, }, /* 411 */
- { 33, 5, 12, 63, -1, }, /* 412 */
- { 33, 5, 12, 63, -58, }, /* 413 */
- { 33, 9, 12, 0, -7615, }, /* 414 */
- { 19, 5, 12, 0, 8, }, /* 415 */
- { 19, 9, 12, 0, -8, }, /* 416 */
- { 19, 5, 12, 0, 74, }, /* 417 */
- { 19, 5, 12, 0, 86, }, /* 418 */
- { 19, 5, 12, 0, 100, }, /* 419 */
- { 19, 5, 12, 0, 128, }, /* 420 */
- { 19, 5, 12, 0, 112, }, /* 421 */
- { 19, 5, 12, 0, 126, }, /* 422 */
- { 19, 8, 12, 0, -8, }, /* 423 */
- { 19, 5, 12, 0, 9, }, /* 424 */
- { 19, 9, 12, 0, -74, }, /* 425 */
- { 19, 8, 12, 0, -9, }, /* 426 */
- { 19, 5, 12, 21, -7173, }, /* 427 */
- { 19, 9, 12, 0, -86, }, /* 428 */
- { 19, 9, 12, 0, -100, }, /* 429 */
- { 19, 9, 12, 0, -112, }, /* 430 */
- { 19, 9, 12, 0, -128, }, /* 431 */
- { 19, 9, 12, 0, -126, }, /* 432 */
- { 27, 1, 3, 0, 0, }, /* 433 */
- { 9, 27, 2, 0, 0, }, /* 434 */
- { 9, 28, 2, 0, 0, }, /* 435 */
- { 9, 2, 2, 0, 0, }, /* 436 */
- { 9, 9, 12, 0, 0, }, /* 437 */
- { 9, 5, 12, 0, 0, }, /* 438 */
- { 19, 9, 12, 67, -7517, }, /* 439 */
- { 33, 9, 12, 71, -8383, }, /* 440 */
- { 33, 9, 12, 75, -8262, }, /* 441 */
- { 33, 9, 12, 0, 28, }, /* 442 */
- { 33, 5, 12, 0, -28, }, /* 443 */
- { 33, 14, 12, 0, 16, }, /* 444 */
- { 33, 14, 12, 0, -16, }, /* 445 */
- { 33, 14, 12, 0, 0, }, /* 446 */
- { 9, 26, 12, 0, 26, }, /* 447 */
- { 9, 26, 12, 0, -26, }, /* 448 */
- { 4, 26, 12, 0, 0, }, /* 449 */
- { 17, 9, 12, 0, 48, }, /* 450 */
- { 17, 5, 12, 0, -48, }, /* 451 */
- { 33, 9, 12, 0, -10743, }, /* 452 */
- { 33, 9, 12, 0, -3814, }, /* 453 */
- { 33, 9, 12, 0, -10727, }, /* 454 */
- { 33, 5, 12, 0, -10795, }, /* 455 */
- { 33, 5, 12, 0, -10792, }, /* 456 */
- { 33, 9, 12, 0, -10780, }, /* 457 */
- { 33, 9, 12, 0, -10749, }, /* 458 */
- { 33, 9, 12, 0, -10783, }, /* 459 */
- { 33, 9, 12, 0, -10782, }, /* 460 */
- { 33, 9, 12, 0, -10815, }, /* 461 */
- { 10, 5, 12, 0, 0, }, /* 462 */
- { 10, 26, 12, 0, 0, }, /* 463 */
- { 10, 12, 3, 0, 0, }, /* 464 */
- { 10, 21, 12, 0, 0, }, /* 465 */
- { 10, 15, 12, 0, 0, }, /* 466 */
- { 16, 5, 12, 0, -7264, }, /* 467 */
- { 58, 7, 12, 0, 0, }, /* 468 */
- { 58, 6, 12, 0, 0, }, /* 469 */
- { 58, 21, 12, 0, 0, }, /* 470 */
- { 58, 12, 3, 0, 0, }, /* 471 */
- { 22, 26, 12, 0, 0, }, /* 472 */
- { 22, 6, 12, 0, 0, }, /* 473 */
- { 22, 14, 12, 0, 0, }, /* 474 */
- { 23, 10, 3, 0, 0, }, /* 475 */
- { 26, 7, 12, 0, 0, }, /* 476 */
- { 26, 6, 12, 0, 0, }, /* 477 */
- { 29, 7, 12, 0, 0, }, /* 478 */
- { 29, 6, 12, 0, 0, }, /* 479 */
- { 3, 7, 12, 0, 0, }, /* 480 */
- { 23, 7, 12, 0, 0, }, /* 481 */
- { 23, 26, 12, 0, 0, }, /* 482 */
- { 29, 26, 12, 0, 0, }, /* 483 */
- { 22, 7, 12, 0, 0, }, /* 484 */
- { 60, 7, 12, 0, 0, }, /* 485 */
- { 60, 6, 12, 0, 0, }, /* 486 */
- { 60, 26, 12, 0, 0, }, /* 487 */
- { 85, 7, 12, 0, 0, }, /* 488 */
- { 85, 6, 12, 0, 0, }, /* 489 */
- { 85, 21, 12, 0, 0, }, /* 490 */
- { 76, 7, 12, 0, 0, }, /* 491 */
- { 76, 6, 12, 0, 0, }, /* 492 */
- { 76, 21, 12, 0, 0, }, /* 493 */
- { 76, 13, 12, 0, 0, }, /* 494 */
- { 12, 7, 12, 0, 0, }, /* 495 */
- { 12, 21, 12, 0, 0, }, /* 496 */
- { 78, 7, 12, 0, 0, }, /* 497 */
- { 78, 14, 12, 0, 0, }, /* 498 */
- { 78, 12, 3, 0, 0, }, /* 499 */
- { 78, 21, 12, 0, 0, }, /* 500 */
- { 33, 9, 12, 0, -35332, }, /* 501 */
- { 33, 9, 12, 0, -42280, }, /* 502 */
- { 33, 9, 12, 0, -42308, }, /* 503 */
- { 33, 9, 12, 0, -42319, }, /* 504 */
- { 33, 9, 12, 0, -42315, }, /* 505 */
- { 33, 9, 12, 0, -42305, }, /* 506 */
- { 33, 9, 12, 0, -42258, }, /* 507 */
- { 33, 9, 12, 0, -42282, }, /* 508 */
- { 48, 7, 12, 0, 0, }, /* 509 */
- { 48, 12, 3, 0, 0, }, /* 510 */
- { 48, 10, 5, 0, 0, }, /* 511 */
- { 48, 26, 12, 0, 0, }, /* 512 */
- { 64, 7, 12, 0, 0, }, /* 513 */
- { 64, 21, 12, 0, 0, }, /* 514 */
- { 74, 10, 5, 0, 0, }, /* 515 */
- { 74, 7, 12, 0, 0, }, /* 516 */
- { 74, 12, 3, 0, 0, }, /* 517 */
- { 74, 21, 12, 0, 0, }, /* 518 */
- { 74, 13, 12, 0, 0, }, /* 519 */
- { 68, 13, 12, 0, 0, }, /* 520 */
- { 68, 7, 12, 0, 0, }, /* 521 */
- { 68, 12, 3, 0, 0, }, /* 522 */
- { 68, 21, 12, 0, 0, }, /* 523 */
- { 73, 7, 12, 0, 0, }, /* 524 */
- { 73, 12, 3, 0, 0, }, /* 525 */
- { 73, 10, 5, 0, 0, }, /* 526 */
- { 73, 21, 12, 0, 0, }, /* 527 */
- { 83, 12, 3, 0, 0, }, /* 528 */
- { 83, 10, 5, 0, 0, }, /* 529 */
- { 83, 7, 12, 0, 0, }, /* 530 */
- { 83, 21, 12, 0, 0, }, /* 531 */
- { 83, 13, 12, 0, 0, }, /* 532 */
- { 38, 6, 12, 0, 0, }, /* 533 */
- { 67, 7, 12, 0, 0, }, /* 534 */
- { 67, 12, 3, 0, 0, }, /* 535 */
- { 67, 10, 5, 0, 0, }, /* 536 */
- { 67, 13, 12, 0, 0, }, /* 537 */
- { 67, 21, 12, 0, 0, }, /* 538 */
- { 91, 7, 12, 0, 0, }, /* 539 */
- { 91, 12, 3, 0, 0, }, /* 540 */
- { 91, 6, 12, 0, 0, }, /* 541 */
- { 91, 21, 12, 0, 0, }, /* 542 */
- { 86, 7, 12, 0, 0, }, /* 543 */
- { 86, 10, 5, 0, 0, }, /* 544 */
- { 86, 12, 3, 0, 0, }, /* 545 */
- { 86, 21, 12, 0, 0, }, /* 546 */
- { 86, 6, 12, 0, 0, }, /* 547 */
- { 86, 13, 12, 0, 0, }, /* 548 */
- { 23, 7, 9, 0, 0, }, /* 549 */
- { 23, 7, 10, 0, 0, }, /* 550 */
- { 9, 4, 2, 0, 0, }, /* 551 */
- { 9, 3, 12, 0, 0, }, /* 552 */
- { 25, 25, 12, 0, 0, }, /* 553 */
- { 0, 24, 12, 0, 0, }, /* 554 */
- { 9, 6, 3, 0, 0, }, /* 555 */
- { 35, 7, 12, 0, 0, }, /* 556 */
- { 19, 14, 12, 0, 0, }, /* 557 */
- { 19, 15, 12, 0, 0, }, /* 558 */
- { 19, 26, 12, 0, 0, }, /* 559 */
- { 70, 7, 12, 0, 0, }, /* 560 */
- { 66, 7, 12, 0, 0, }, /* 561 */
- { 41, 7, 12, 0, 0, }, /* 562 */
- { 41, 15, 12, 0, 0, }, /* 563 */
- { 18, 7, 12, 0, 0, }, /* 564 */
- { 18, 14, 12, 0, 0, }, /* 565 */
- { 117, 7, 12, 0, 0, }, /* 566 */
- { 117, 12, 3, 0, 0, }, /* 567 */
- { 59, 7, 12, 0, 0, }, /* 568 */
- { 59, 21, 12, 0, 0, }, /* 569 */
- { 42, 7, 12, 0, 0, }, /* 570 */
- { 42, 21, 12, 0, 0, }, /* 571 */
- { 42, 14, 12, 0, 0, }, /* 572 */
- { 13, 9, 12, 0, 40, }, /* 573 */
- { 13, 5, 12, 0, -40, }, /* 574 */
- { 46, 7, 12, 0, 0, }, /* 575 */
- { 44, 7, 12, 0, 0, }, /* 576 */
- { 44, 13, 12, 0, 0, }, /* 577 */
- { 105, 7, 12, 0, 0, }, /* 578 */
- { 103, 7, 12, 0, 0, }, /* 579 */
- { 103, 21, 12, 0, 0, }, /* 580 */
- { 109, 7, 12, 0, 0, }, /* 581 */
- { 11, 7, 12, 0, 0, }, /* 582 */
- { 80, 7, 12, 0, 0, }, /* 583 */
- { 80, 21, 12, 0, 0, }, /* 584 */
- { 80, 15, 12, 0, 0, }, /* 585 */
- { 119, 7, 12, 0, 0, }, /* 586 */
- { 119, 26, 12, 0, 0, }, /* 587 */
- { 119, 15, 12, 0, 0, }, /* 588 */
- { 115, 7, 12, 0, 0, }, /* 589 */
- { 115, 15, 12, 0, 0, }, /* 590 */
- { 65, 7, 12, 0, 0, }, /* 591 */
- { 65, 15, 12, 0, 0, }, /* 592 */
- { 65, 21, 12, 0, 0, }, /* 593 */
- { 71, 7, 12, 0, 0, }, /* 594 */
- { 71, 21, 12, 0, 0, }, /* 595 */
- { 97, 7, 12, 0, 0, }, /* 596 */
- { 96, 7, 12, 0, 0, }, /* 597 */
- { 30, 7, 12, 0, 0, }, /* 598 */
- { 30, 12, 3, 0, 0, }, /* 599 */
- { 30, 15, 12, 0, 0, }, /* 600 */
- { 30, 21, 12, 0, 0, }, /* 601 */
- { 87, 7, 12, 0, 0, }, /* 602 */
- { 87, 15, 12, 0, 0, }, /* 603 */
- { 87, 21, 12, 0, 0, }, /* 604 */
- { 116, 7, 12, 0, 0, }, /* 605 */
- { 116, 15, 12, 0, 0, }, /* 606 */
- { 111, 7, 12, 0, 0, }, /* 607 */
- { 111, 26, 12, 0, 0, }, /* 608 */
- { 111, 12, 3, 0, 0, }, /* 609 */
- { 111, 15, 12, 0, 0, }, /* 610 */
- { 111, 21, 12, 0, 0, }, /* 611 */
- { 77, 7, 12, 0, 0, }, /* 612 */
- { 77, 21, 12, 0, 0, }, /* 613 */
- { 82, 7, 12, 0, 0, }, /* 614 */
- { 82, 15, 12, 0, 0, }, /* 615 */
- { 81, 7, 12, 0, 0, }, /* 616 */
- { 81, 15, 12, 0, 0, }, /* 617 */
- { 120, 7, 12, 0, 0, }, /* 618 */
- { 120, 21, 12, 0, 0, }, /* 619 */
- { 120, 15, 12, 0, 0, }, /* 620 */
- { 88, 7, 12, 0, 0, }, /* 621 */
- { 0, 15, 12, 0, 0, }, /* 622 */
- { 93, 10, 5, 0, 0, }, /* 623 */
- { 93, 12, 3, 0, 0, }, /* 624 */
- { 93, 7, 12, 0, 0, }, /* 625 */
- { 93, 21, 12, 0, 0, }, /* 626 */
- { 93, 15, 12, 0, 0, }, /* 627 */
- { 93, 13, 12, 0, 0, }, /* 628 */
- { 84, 12, 3, 0, 0, }, /* 629 */
- { 84, 10, 5, 0, 0, }, /* 630 */
- { 84, 7, 12, 0, 0, }, /* 631 */
- { 84, 21, 12, 0, 0, }, /* 632 */
- { 84, 1, 2, 0, 0, }, /* 633 */
- { 100, 7, 12, 0, 0, }, /* 634 */
- { 100, 13, 12, 0, 0, }, /* 635 */
- { 95, 12, 3, 0, 0, }, /* 636 */
- { 95, 7, 12, 0, 0, }, /* 637 */
- { 95, 10, 5, 0, 0, }, /* 638 */
- { 95, 13, 12, 0, 0, }, /* 639 */
- { 95, 21, 12, 0, 0, }, /* 640 */
- { 110, 7, 12, 0, 0, }, /* 641 */
- { 110, 12, 3, 0, 0, }, /* 642 */
- { 110, 21, 12, 0, 0, }, /* 643 */
- { 99, 12, 3, 0, 0, }, /* 644 */
- { 99, 10, 5, 0, 0, }, /* 645 */
- { 99, 7, 12, 0, 0, }, /* 646 */
- { 99, 21, 12, 0, 0, }, /* 647 */
- { 99, 13, 12, 0, 0, }, /* 648 */
- { 47, 15, 12, 0, 0, }, /* 649 */
- { 107, 7, 12, 0, 0, }, /* 650 */
- { 107, 10, 5, 0, 0, }, /* 651 */
- { 107, 12, 3, 0, 0, }, /* 652 */
- { 107, 21, 12, 0, 0, }, /* 653 */
- { 108, 7, 12, 0, 0, }, /* 654 */
- { 108, 12, 3, 0, 0, }, /* 655 */
- { 108, 10, 5, 0, 0, }, /* 656 */
- { 108, 13, 12, 0, 0, }, /* 657 */
- { 106, 12, 3, 0, 0, }, /* 658 */
- { 106, 10, 5, 0, 0, }, /* 659 */
- { 106, 7, 12, 0, 0, }, /* 660 */
- { 106, 10, 3, 0, 0, }, /* 661 */
- { 123, 7, 12, 0, 0, }, /* 662 */
- { 123, 10, 3, 0, 0, }, /* 663 */
- { 123, 10, 5, 0, 0, }, /* 664 */
- { 123, 12, 3, 0, 0, }, /* 665 */
- { 123, 21, 12, 0, 0, }, /* 666 */
- { 123, 13, 12, 0, 0, }, /* 667 */
- { 122, 7, 12, 0, 0, }, /* 668 */
- { 122, 10, 3, 0, 0, }, /* 669 */
- { 122, 10, 5, 0, 0, }, /* 670 */
- { 122, 12, 3, 0, 0, }, /* 671 */
- { 122, 21, 12, 0, 0, }, /* 672 */
- { 113, 7, 12, 0, 0, }, /* 673 */
- { 113, 10, 5, 0, 0, }, /* 674 */
- { 113, 12, 3, 0, 0, }, /* 675 */
- { 113, 21, 12, 0, 0, }, /* 676 */
- { 113, 13, 12, 0, 0, }, /* 677 */
- { 101, 7, 12, 0, 0, }, /* 678 */
- { 101, 12, 3, 0, 0, }, /* 679 */
- { 101, 10, 5, 0, 0, }, /* 680 */
- { 101, 13, 12, 0, 0, }, /* 681 */
- { 124, 9, 12, 0, 32, }, /* 682 */
- { 124, 5, 12, 0, -32, }, /* 683 */
- { 124, 13, 12, 0, 0, }, /* 684 */
- { 124, 15, 12, 0, 0, }, /* 685 */
- { 124, 7, 12, 0, 0, }, /* 686 */
- { 121, 7, 12, 0, 0, }, /* 687 */
- { 62, 7, 12, 0, 0, }, /* 688 */
- { 62, 14, 12, 0, 0, }, /* 689 */
- { 62, 21, 12, 0, 0, }, /* 690 */
- { 79, 7, 12, 0, 0, }, /* 691 */
- { 114, 7, 12, 0, 0, }, /* 692 */
- { 114, 13, 12, 0, 0, }, /* 693 */
- { 114, 21, 12, 0, 0, }, /* 694 */
- { 102, 7, 12, 0, 0, }, /* 695 */
- { 102, 12, 3, 0, 0, }, /* 696 */
- { 102, 21, 12, 0, 0, }, /* 697 */
- { 118, 7, 12, 0, 0, }, /* 698 */
- { 118, 12, 3, 0, 0, }, /* 699 */
- { 118, 21, 12, 0, 0, }, /* 700 */
- { 118, 26, 12, 0, 0, }, /* 701 */
- { 118, 6, 12, 0, 0, }, /* 702 */
- { 118, 13, 12, 0, 0, }, /* 703 */
- { 118, 15, 12, 0, 0, }, /* 704 */
- { 98, 7, 12, 0, 0, }, /* 705 */
- { 98, 10, 5, 0, 0, }, /* 706 */
- { 98, 12, 3, 0, 0, }, /* 707 */
- { 98, 6, 12, 0, 0, }, /* 708 */
- { 104, 7, 12, 0, 0, }, /* 709 */
- { 104, 26, 12, 0, 0, }, /* 710 */
- { 104, 12, 3, 0, 0, }, /* 711 */
- { 104, 21, 12, 0, 0, }, /* 712 */
- { 9, 10, 3, 0, 0, }, /* 713 */
- { 19, 12, 3, 0, 0, }, /* 714 */
- { 112, 7, 12, 0, 0, }, /* 715 */
- { 112, 15, 12, 0, 0, }, /* 716 */
- { 112, 12, 3, 0, 0, }, /* 717 */
- { 9, 26, 11, 0, 0, }, /* 718 */
- { 26, 26, 12, 0, 0, }, /* 719 */
+ { 0, 6, 12, 0, 0, }, /* 202 */
+ { 49, 21, 12, 0, 0, }, /* 203 */
+ { 49, 1, 2, 0, 0, }, /* 204 */
+ { 49, 7, 12, 0, 0, }, /* 205 */
+ { 49, 12, 3, 0, 0, }, /* 206 */
+ { 55, 7, 12, 0, 0, }, /* 207 */
+ { 55, 12, 3, 0, 0, }, /* 208 */
+ { 63, 13, 12, 0, 0, }, /* 209 */
+ { 63, 7, 12, 0, 0, }, /* 210 */
+ { 63, 12, 3, 0, 0, }, /* 211 */
+ { 63, 6, 12, 0, 0, }, /* 212 */
+ { 63, 26, 12, 0, 0, }, /* 213 */
+ { 63, 21, 12, 0, 0, }, /* 214 */
+ { 89, 7, 12, 0, 0, }, /* 215 */
+ { 89, 12, 3, 0, 0, }, /* 216 */
+ { 89, 6, 12, 0, 0, }, /* 217 */
+ { 89, 21, 12, 0, 0, }, /* 218 */
+ { 94, 7, 12, 0, 0, }, /* 219 */
+ { 94, 12, 3, 0, 0, }, /* 220 */
+ { 94, 21, 12, 0, 0, }, /* 221 */
+ { 14, 12, 3, 0, 0, }, /* 222 */
+ { 14, 10, 5, 0, 0, }, /* 223 */
+ { 14, 7, 12, 0, 0, }, /* 224 */
+ { 14, 13, 12, 0, 0, }, /* 225 */
+ { 14, 21, 12, 0, 0, }, /* 226 */
+ { 14, 6, 12, 0, 0, }, /* 227 */
+ { 2, 7, 12, 0, 0, }, /* 228 */
+ { 2, 12, 3, 0, 0, }, /* 229 */
+ { 2, 10, 5, 0, 0, }, /* 230 */
+ { 2, 10, 3, 0, 0, }, /* 231 */
+ { 2, 13, 12, 0, 0, }, /* 232 */
+ { 2, 23, 12, 0, 0, }, /* 233 */
+ { 2, 15, 12, 0, 0, }, /* 234 */
+ { 2, 26, 12, 0, 0, }, /* 235 */
+ { 21, 12, 3, 0, 0, }, /* 236 */
+ { 21, 10, 5, 0, 0, }, /* 237 */
+ { 21, 7, 12, 0, 0, }, /* 238 */
+ { 21, 13, 12, 0, 0, }, /* 239 */
+ { 20, 12, 3, 0, 0, }, /* 240 */
+ { 20, 10, 5, 0, 0, }, /* 241 */
+ { 20, 7, 12, 0, 0, }, /* 242 */
+ { 20, 13, 12, 0, 0, }, /* 243 */
+ { 20, 21, 12, 0, 0, }, /* 244 */
+ { 20, 23, 12, 0, 0, }, /* 245 */
+ { 43, 12, 3, 0, 0, }, /* 246 */
+ { 43, 10, 5, 0, 0, }, /* 247 */
+ { 43, 7, 12, 0, 0, }, /* 248 */
+ { 43, 10, 3, 0, 0, }, /* 249 */
+ { 43, 13, 12, 0, 0, }, /* 250 */
+ { 43, 26, 12, 0, 0, }, /* 251 */
+ { 43, 15, 12, 0, 0, }, /* 252 */
+ { 53, 12, 3, 0, 0, }, /* 253 */
+ { 53, 7, 12, 0, 0, }, /* 254 */
+ { 53, 10, 3, 0, 0, }, /* 255 */
+ { 53, 10, 5, 0, 0, }, /* 256 */
+ { 53, 13, 12, 0, 0, }, /* 257 */
+ { 53, 15, 12, 0, 0, }, /* 258 */
+ { 53, 26, 12, 0, 0, }, /* 259 */
+ { 53, 23, 12, 0, 0, }, /* 260 */
+ { 54, 12, 3, 0, 0, }, /* 261 */
+ { 54, 10, 5, 0, 0, }, /* 262 */
+ { 54, 7, 12, 0, 0, }, /* 263 */
+ { 54, 13, 12, 0, 0, }, /* 264 */
+ { 54, 15, 12, 0, 0, }, /* 265 */
+ { 54, 26, 12, 0, 0, }, /* 266 */
+ { 28, 12, 3, 0, 0, }, /* 267 */
+ { 28, 10, 5, 0, 0, }, /* 268 */
+ { 28, 7, 12, 0, 0, }, /* 269 */
+ { 28, 10, 3, 0, 0, }, /* 270 */
+ { 28, 13, 12, 0, 0, }, /* 271 */
+ { 36, 12, 3, 0, 0, }, /* 272 */
+ { 36, 10, 5, 0, 0, }, /* 273 */
+ { 36, 7, 12, 0, 0, }, /* 274 */
+ { 36, 10, 3, 0, 0, }, /* 275 */
+ { 36, 13, 12, 0, 0, }, /* 276 */
+ { 36, 15, 12, 0, 0, }, /* 277 */
+ { 36, 26, 12, 0, 0, }, /* 278 */
+ { 47, 10, 5, 0, 0, }, /* 279 */
+ { 47, 7, 12, 0, 0, }, /* 280 */
+ { 47, 12, 3, 0, 0, }, /* 281 */
+ { 47, 10, 3, 0, 0, }, /* 282 */
+ { 47, 13, 12, 0, 0, }, /* 283 */
+ { 47, 21, 12, 0, 0, }, /* 284 */
+ { 56, 7, 12, 0, 0, }, /* 285 */
+ { 56, 12, 3, 0, 0, }, /* 286 */
+ { 56, 7, 5, 0, 0, }, /* 287 */
+ { 56, 6, 12, 0, 0, }, /* 288 */
+ { 56, 21, 12, 0, 0, }, /* 289 */
+ { 56, 13, 12, 0, 0, }, /* 290 */
+ { 32, 7, 12, 0, 0, }, /* 291 */
+ { 32, 12, 3, 0, 0, }, /* 292 */
+ { 32, 7, 5, 0, 0, }, /* 293 */
+ { 32, 6, 12, 0, 0, }, /* 294 */
+ { 32, 13, 12, 0, 0, }, /* 295 */
+ { 57, 7, 12, 0, 0, }, /* 296 */
+ { 57, 26, 12, 0, 0, }, /* 297 */
+ { 57, 21, 12, 0, 0, }, /* 298 */
+ { 57, 12, 3, 0, 0, }, /* 299 */
+ { 57, 13, 12, 0, 0, }, /* 300 */
+ { 57, 15, 12, 0, 0, }, /* 301 */
+ { 57, 22, 12, 0, 0, }, /* 302 */
+ { 57, 18, 12, 0, 0, }, /* 303 */
+ { 57, 10, 5, 0, 0, }, /* 304 */
+ { 38, 7, 12, 0, 0, }, /* 305 */
+ { 38, 10, 12, 0, 0, }, /* 306 */
+ { 38, 12, 3, 0, 0, }, /* 307 */
+ { 38, 10, 5, 0, 0, }, /* 308 */
+ { 38, 13, 12, 0, 0, }, /* 309 */
+ { 38, 21, 12, 0, 0, }, /* 310 */
+ { 38, 26, 12, 0, 0, }, /* 311 */
+ { 16, 9, 12, 0, 7264, }, /* 312 */
+ { 16, 7, 12, 0, 0, }, /* 313 */
+ { 16, 6, 12, 0, 0, }, /* 314 */
+ { 23, 7, 6, 0, 0, }, /* 315 */
+ { 23, 7, 7, 0, 0, }, /* 316 */
+ { 23, 7, 8, 0, 0, }, /* 317 */
+ { 15, 7, 12, 0, 0, }, /* 318 */
+ { 15, 12, 3, 0, 0, }, /* 319 */
+ { 15, 21, 12, 0, 0, }, /* 320 */
+ { 15, 15, 12, 0, 0, }, /* 321 */
+ { 15, 26, 12, 0, 0, }, /* 322 */
+ { 8, 9, 12, 0, 38864, }, /* 323 */
+ { 8, 9, 12, 0, 8, }, /* 324 */
+ { 8, 5, 12, 0, -8, }, /* 325 */
+ { 7, 17, 12, 0, 0, }, /* 326 */
+ { 7, 7, 12, 0, 0, }, /* 327 */
+ { 7, 21, 12, 0, 0, }, /* 328 */
+ { 40, 29, 12, 0, 0, }, /* 329 */
+ { 40, 7, 12, 0, 0, }, /* 330 */
+ { 40, 22, 12, 0, 0, }, /* 331 */
+ { 40, 18, 12, 0, 0, }, /* 332 */
+ { 45, 7, 12, 0, 0, }, /* 333 */
+ { 45, 14, 12, 0, 0, }, /* 334 */
+ { 50, 7, 12, 0, 0, }, /* 335 */
+ { 50, 12, 3, 0, 0, }, /* 336 */
+ { 24, 7, 12, 0, 0, }, /* 337 */
+ { 24, 12, 3, 0, 0, }, /* 338 */
+ { 6, 7, 12, 0, 0, }, /* 339 */
+ { 6, 12, 3, 0, 0, }, /* 340 */
+ { 51, 7, 12, 0, 0, }, /* 341 */
+ { 51, 12, 3, 0, 0, }, /* 342 */
+ { 31, 7, 12, 0, 0, }, /* 343 */
+ { 31, 12, 3, 0, 0, }, /* 344 */
+ { 31, 10, 5, 0, 0, }, /* 345 */
+ { 31, 21, 12, 0, 0, }, /* 346 */
+ { 31, 6, 12, 0, 0, }, /* 347 */
+ { 31, 23, 12, 0, 0, }, /* 348 */
+ { 31, 13, 12, 0, 0, }, /* 349 */
+ { 31, 15, 12, 0, 0, }, /* 350 */
+ { 37, 21, 12, 0, 0, }, /* 351 */
+ { 37, 17, 12, 0, 0, }, /* 352 */
+ { 37, 12, 3, 0, 0, }, /* 353 */
+ { 37, 1, 2, 0, 0, }, /* 354 */
+ { 37, 13, 12, 0, 0, }, /* 355 */
+ { 37, 7, 12, 0, 0, }, /* 356 */
+ { 37, 6, 12, 0, 0, }, /* 357 */
+ { 34, 7, 12, 0, 0, }, /* 358 */
+ { 34, 12, 3, 0, 0, }, /* 359 */
+ { 34, 10, 5, 0, 0, }, /* 360 */
+ { 34, 26, 12, 0, 0, }, /* 361 */
+ { 34, 21, 12, 0, 0, }, /* 362 */
+ { 34, 13, 12, 0, 0, }, /* 363 */
+ { 52, 7, 12, 0, 0, }, /* 364 */
+ { 39, 7, 12, 0, 0, }, /* 365 */
+ { 39, 13, 12, 0, 0, }, /* 366 */
+ { 39, 15, 12, 0, 0, }, /* 367 */
+ { 39, 26, 12, 0, 0, }, /* 368 */
+ { 31, 26, 12, 0, 0, }, /* 369 */
+ { 5, 7, 12, 0, 0, }, /* 370 */
+ { 5, 12, 3, 0, 0, }, /* 371 */
+ { 5, 10, 5, 0, 0, }, /* 372 */
+ { 5, 21, 12, 0, 0, }, /* 373 */
+ { 90, 7, 12, 0, 0, }, /* 374 */
+ { 90, 10, 5, 0, 0, }, /* 375 */
+ { 90, 12, 3, 0, 0, }, /* 376 */
+ { 90, 10, 12, 0, 0, }, /* 377 */
+ { 90, 13, 12, 0, 0, }, /* 378 */
+ { 90, 21, 12, 0, 0, }, /* 379 */
+ { 90, 6, 12, 0, 0, }, /* 380 */
+ { 27, 11, 3, 0, 0, }, /* 381 */
+ { 61, 12, 3, 0, 0, }, /* 382 */
+ { 61, 10, 5, 0, 0, }, /* 383 */
+ { 61, 7, 12, 0, 0, }, /* 384 */
+ { 61, 13, 12, 0, 0, }, /* 385 */
+ { 61, 21, 12, 0, 0, }, /* 386 */
+ { 61, 26, 12, 0, 0, }, /* 387 */
+ { 75, 12, 3, 0, 0, }, /* 388 */
+ { 75, 10, 5, 0, 0, }, /* 389 */
+ { 75, 7, 12, 0, 0, }, /* 390 */
+ { 75, 13, 12, 0, 0, }, /* 391 */
+ { 92, 7, 12, 0, 0, }, /* 392 */
+ { 92, 12, 3, 0, 0, }, /* 393 */
+ { 92, 10, 5, 0, 0, }, /* 394 */
+ { 92, 21, 12, 0, 0, }, /* 395 */
+ { 69, 7, 12, 0, 0, }, /* 396 */
+ { 69, 10, 5, 0, 0, }, /* 397 */
+ { 69, 12, 3, 0, 0, }, /* 398 */
+ { 69, 21, 12, 0, 0, }, /* 399 */
+ { 69, 13, 12, 0, 0, }, /* 400 */
+ { 72, 13, 12, 0, 0, }, /* 401 */
+ { 72, 7, 12, 0, 0, }, /* 402 */
+ { 72, 6, 12, 0, 0, }, /* 403 */
+ { 72, 21, 12, 0, 0, }, /* 404 */
+ { 75, 21, 12, 0, 0, }, /* 405 */
+ { 9, 10, 5, 0, 0, }, /* 406 */
+ { 9, 7, 12, 0, 0, }, /* 407 */
+ { 12, 5, 12, 0, 0, }, /* 408 */
+ { 12, 6, 12, 0, 0, }, /* 409 */
+ { 33, 5, 12, 0, 35332, }, /* 410 */
+ { 33, 5, 12, 0, 3814, }, /* 411 */
+ { 33, 9, 12, 63, 1, }, /* 412 */
+ { 33, 5, 12, 63, -1, }, /* 413 */
+ { 33, 5, 12, 63, -58, }, /* 414 */
+ { 33, 9, 12, 0, -7615, }, /* 415 */
+ { 19, 5, 12, 0, 8, }, /* 416 */
+ { 19, 9, 12, 0, -8, }, /* 417 */
+ { 19, 5, 12, 0, 74, }, /* 418 */
+ { 19, 5, 12, 0, 86, }, /* 419 */
+ { 19, 5, 12, 0, 100, }, /* 420 */
+ { 19, 5, 12, 0, 128, }, /* 421 */
+ { 19, 5, 12, 0, 112, }, /* 422 */
+ { 19, 5, 12, 0, 126, }, /* 423 */
+ { 19, 8, 12, 0, -8, }, /* 424 */
+ { 19, 5, 12, 0, 9, }, /* 425 */
+ { 19, 9, 12, 0, -74, }, /* 426 */
+ { 19, 8, 12, 0, -9, }, /* 427 */
+ { 19, 5, 12, 21, -7173, }, /* 428 */
+ { 19, 9, 12, 0, -86, }, /* 429 */
+ { 19, 9, 12, 0, -100, }, /* 430 */
+ { 19, 9, 12, 0, -112, }, /* 431 */
+ { 19, 9, 12, 0, -128, }, /* 432 */
+ { 19, 9, 12, 0, -126, }, /* 433 */
+ { 27, 1, 3, 0, 0, }, /* 434 */
+ { 9, 27, 2, 0, 0, }, /* 435 */
+ { 9, 28, 2, 0, 0, }, /* 436 */
+ { 9, 2, 2, 0, 0, }, /* 437 */
+ { 9, 9, 12, 0, 0, }, /* 438 */
+ { 9, 5, 12, 0, 0, }, /* 439 */
+ { 19, 9, 12, 67, -7517, }, /* 440 */
+ { 33, 9, 12, 71, -8383, }, /* 441 */
+ { 33, 9, 12, 75, -8262, }, /* 442 */
+ { 33, 9, 12, 0, 28, }, /* 443 */
+ { 33, 5, 12, 0, -28, }, /* 444 */
+ { 33, 14, 12, 0, 16, }, /* 445 */
+ { 33, 14, 12, 0, -16, }, /* 446 */
+ { 33, 14, 12, 0, 0, }, /* 447 */
+ { 9, 26, 12, 0, 26, }, /* 448 */
+ { 9, 26, 12, 0, -26, }, /* 449 */
+ { 4, 26, 12, 0, 0, }, /* 450 */
+ { 17, 9, 12, 0, 48, }, /* 451 */
+ { 17, 5, 12, 0, -48, }, /* 452 */
+ { 33, 9, 12, 0, -10743, }, /* 453 */
+ { 33, 9, 12, 0, -3814, }, /* 454 */
+ { 33, 9, 12, 0, -10727, }, /* 455 */
+ { 33, 5, 12, 0, -10795, }, /* 456 */
+ { 33, 5, 12, 0, -10792, }, /* 457 */
+ { 33, 9, 12, 0, -10780, }, /* 458 */
+ { 33, 9, 12, 0, -10749, }, /* 459 */
+ { 33, 9, 12, 0, -10783, }, /* 460 */
+ { 33, 9, 12, 0, -10782, }, /* 461 */
+ { 33, 9, 12, 0, -10815, }, /* 462 */
+ { 10, 5, 12, 0, 0, }, /* 463 */
+ { 10, 26, 12, 0, 0, }, /* 464 */
+ { 10, 12, 3, 0, 0, }, /* 465 */
+ { 10, 21, 12, 0, 0, }, /* 466 */
+ { 10, 15, 12, 0, 0, }, /* 467 */
+ { 16, 5, 12, 0, -7264, }, /* 468 */
+ { 58, 7, 12, 0, 0, }, /* 469 */
+ { 58, 6, 12, 0, 0, }, /* 470 */
+ { 58, 21, 12, 0, 0, }, /* 471 */
+ { 58, 12, 3, 0, 0, }, /* 472 */
+ { 22, 26, 12, 0, 0, }, /* 473 */
+ { 22, 6, 12, 0, 0, }, /* 474 */
+ { 22, 14, 12, 0, 0, }, /* 475 */
+ { 23, 10, 3, 0, 0, }, /* 476 */
+ { 26, 7, 12, 0, 0, }, /* 477 */
+ { 26, 6, 12, 0, 0, }, /* 478 */
+ { 29, 7, 12, 0, 0, }, /* 479 */
+ { 29, 6, 12, 0, 0, }, /* 480 */
+ { 3, 7, 12, 0, 0, }, /* 481 */
+ { 23, 7, 12, 0, 0, }, /* 482 */
+ { 23, 26, 12, 0, 0, }, /* 483 */
+ { 29, 26, 12, 0, 0, }, /* 484 */
+ { 22, 7, 12, 0, 0, }, /* 485 */
+ { 60, 7, 12, 0, 0, }, /* 486 */
+ { 60, 6, 12, 0, 0, }, /* 487 */
+ { 60, 26, 12, 0, 0, }, /* 488 */
+ { 85, 7, 12, 0, 0, }, /* 489 */
+ { 85, 6, 12, 0, 0, }, /* 490 */
+ { 85, 21, 12, 0, 0, }, /* 491 */
+ { 76, 7, 12, 0, 0, }, /* 492 */
+ { 76, 6, 12, 0, 0, }, /* 493 */
+ { 76, 21, 12, 0, 0, }, /* 494 */
+ { 76, 13, 12, 0, 0, }, /* 495 */
+ { 12, 7, 12, 0, 0, }, /* 496 */
+ { 12, 21, 12, 0, 0, }, /* 497 */
+ { 78, 7, 12, 0, 0, }, /* 498 */
+ { 78, 14, 12, 0, 0, }, /* 499 */
+ { 78, 12, 3, 0, 0, }, /* 500 */
+ { 78, 21, 12, 0, 0, }, /* 501 */
+ { 33, 9, 12, 0, -35332, }, /* 502 */
+ { 33, 9, 12, 0, -42280, }, /* 503 */
+ { 33, 9, 12, 0, -42308, }, /* 504 */
+ { 33, 9, 12, 0, -42319, }, /* 505 */
+ { 33, 9, 12, 0, -42315, }, /* 506 */
+ { 33, 9, 12, 0, -42305, }, /* 507 */
+ { 33, 9, 12, 0, -42258, }, /* 508 */
+ { 33, 9, 12, 0, -42282, }, /* 509 */
+ { 33, 9, 12, 0, -42261, }, /* 510 */
+ { 33, 9, 12, 0, 928, }, /* 511 */
+ { 48, 7, 12, 0, 0, }, /* 512 */
+ { 48, 12, 3, 0, 0, }, /* 513 */
+ { 48, 10, 5, 0, 0, }, /* 514 */
+ { 48, 26, 12, 0, 0, }, /* 515 */
+ { 64, 7, 12, 0, 0, }, /* 516 */
+ { 64, 21, 12, 0, 0, }, /* 517 */
+ { 74, 10, 5, 0, 0, }, /* 518 */
+ { 74, 7, 12, 0, 0, }, /* 519 */
+ { 74, 12, 3, 0, 0, }, /* 520 */
+ { 74, 21, 12, 0, 0, }, /* 521 */
+ { 74, 13, 12, 0, 0, }, /* 522 */
+ { 68, 13, 12, 0, 0, }, /* 523 */
+ { 68, 7, 12, 0, 0, }, /* 524 */
+ { 68, 12, 3, 0, 0, }, /* 525 */
+ { 68, 21, 12, 0, 0, }, /* 526 */
+ { 73, 7, 12, 0, 0, }, /* 527 */
+ { 73, 12, 3, 0, 0, }, /* 528 */
+ { 73, 10, 5, 0, 0, }, /* 529 */
+ { 73, 21, 12, 0, 0, }, /* 530 */
+ { 83, 12, 3, 0, 0, }, /* 531 */
+ { 83, 10, 5, 0, 0, }, /* 532 */
+ { 83, 7, 12, 0, 0, }, /* 533 */
+ { 83, 21, 12, 0, 0, }, /* 534 */
+ { 83, 13, 12, 0, 0, }, /* 535 */
+ { 38, 6, 12, 0, 0, }, /* 536 */
+ { 67, 7, 12, 0, 0, }, /* 537 */
+ { 67, 12, 3, 0, 0, }, /* 538 */
+ { 67, 10, 5, 0, 0, }, /* 539 */
+ { 67, 13, 12, 0, 0, }, /* 540 */
+ { 67, 21, 12, 0, 0, }, /* 541 */
+ { 91, 7, 12, 0, 0, }, /* 542 */
+ { 91, 12, 3, 0, 0, }, /* 543 */
+ { 91, 6, 12, 0, 0, }, /* 544 */
+ { 91, 21, 12, 0, 0, }, /* 545 */
+ { 86, 7, 12, 0, 0, }, /* 546 */
+ { 86, 10, 5, 0, 0, }, /* 547 */
+ { 86, 12, 3, 0, 0, }, /* 548 */
+ { 86, 21, 12, 0, 0, }, /* 549 */
+ { 86, 6, 12, 0, 0, }, /* 550 */
+ { 33, 5, 12, 0, -928, }, /* 551 */
+ { 8, 5, 12, 0, -38864, }, /* 552 */
+ { 86, 13, 12, 0, 0, }, /* 553 */
+ { 23, 7, 9, 0, 0, }, /* 554 */
+ { 23, 7, 10, 0, 0, }, /* 555 */
+ { 9, 4, 2, 0, 0, }, /* 556 */
+ { 9, 3, 12, 0, 0, }, /* 557 */
+ { 25, 25, 12, 0, 0, }, /* 558 */
+ { 0, 24, 12, 0, 0, }, /* 559 */
+ { 9, 6, 3, 0, 0, }, /* 560 */
+ { 35, 7, 12, 0, 0, }, /* 561 */
+ { 19, 14, 12, 0, 0, }, /* 562 */
+ { 19, 15, 12, 0, 0, }, /* 563 */
+ { 19, 26, 12, 0, 0, }, /* 564 */
+ { 70, 7, 12, 0, 0, }, /* 565 */
+ { 66, 7, 12, 0, 0, }, /* 566 */
+ { 41, 7, 12, 0, 0, }, /* 567 */
+ { 41, 15, 12, 0, 0, }, /* 568 */
+ { 18, 7, 12, 0, 0, }, /* 569 */
+ { 18, 14, 12, 0, 0, }, /* 570 */
+ { 117, 7, 12, 0, 0, }, /* 571 */
+ { 117, 12, 3, 0, 0, }, /* 572 */
+ { 59, 7, 12, 0, 0, }, /* 573 */
+ { 59, 21, 12, 0, 0, }, /* 574 */
+ { 42, 7, 12, 0, 0, }, /* 575 */
+ { 42, 21, 12, 0, 0, }, /* 576 */
+ { 42, 14, 12, 0, 0, }, /* 577 */
+ { 13, 9, 12, 0, 40, }, /* 578 */
+ { 13, 5, 12, 0, -40, }, /* 579 */
+ { 46, 7, 12, 0, 0, }, /* 580 */
+ { 44, 7, 12, 0, 0, }, /* 581 */
+ { 44, 13, 12, 0, 0, }, /* 582 */
+ { 105, 7, 12, 0, 0, }, /* 583 */
+ { 103, 7, 12, 0, 0, }, /* 584 */
+ { 103, 21, 12, 0, 0, }, /* 585 */
+ { 109, 7, 12, 0, 0, }, /* 586 */
+ { 11, 7, 12, 0, 0, }, /* 587 */
+ { 80, 7, 12, 0, 0, }, /* 588 */
+ { 80, 21, 12, 0, 0, }, /* 589 */
+ { 80, 15, 12, 0, 0, }, /* 590 */
+ { 119, 7, 12, 0, 0, }, /* 591 */
+ { 119, 26, 12, 0, 0, }, /* 592 */
+ { 119, 15, 12, 0, 0, }, /* 593 */
+ { 115, 7, 12, 0, 0, }, /* 594 */
+ { 115, 15, 12, 0, 0, }, /* 595 */
+ { 127, 7, 12, 0, 0, }, /* 596 */
+ { 127, 15, 12, 0, 0, }, /* 597 */
+ { 65, 7, 12, 0, 0, }, /* 598 */
+ { 65, 15, 12, 0, 0, }, /* 599 */
+ { 65, 21, 12, 0, 0, }, /* 600 */
+ { 71, 7, 12, 0, 0, }, /* 601 */
+ { 71, 21, 12, 0, 0, }, /* 602 */
+ { 97, 7, 12, 0, 0, }, /* 603 */
+ { 96, 7, 12, 0, 0, }, /* 604 */
+ { 96, 15, 12, 0, 0, }, /* 605 */
+ { 30, 7, 12, 0, 0, }, /* 606 */
+ { 30, 12, 3, 0, 0, }, /* 607 */
+ { 30, 15, 12, 0, 0, }, /* 608 */
+ { 30, 21, 12, 0, 0, }, /* 609 */
+ { 87, 7, 12, 0, 0, }, /* 610 */
+ { 87, 15, 12, 0, 0, }, /* 611 */
+ { 87, 21, 12, 0, 0, }, /* 612 */
+ { 116, 7, 12, 0, 0, }, /* 613 */
+ { 116, 15, 12, 0, 0, }, /* 614 */
+ { 111, 7, 12, 0, 0, }, /* 615 */
+ { 111, 26, 12, 0, 0, }, /* 616 */
+ { 111, 12, 3, 0, 0, }, /* 617 */
+ { 111, 15, 12, 0, 0, }, /* 618 */
+ { 111, 21, 12, 0, 0, }, /* 619 */
+ { 77, 7, 12, 0, 0, }, /* 620 */
+ { 77, 21, 12, 0, 0, }, /* 621 */
+ { 82, 7, 12, 0, 0, }, /* 622 */
+ { 82, 15, 12, 0, 0, }, /* 623 */
+ { 81, 7, 12, 0, 0, }, /* 624 */
+ { 81, 15, 12, 0, 0, }, /* 625 */
+ { 120, 7, 12, 0, 0, }, /* 626 */
+ { 120, 21, 12, 0, 0, }, /* 627 */
+ { 120, 15, 12, 0, 0, }, /* 628 */
+ { 88, 7, 12, 0, 0, }, /* 629 */
+ { 129, 9, 12, 0, 64, }, /* 630 */
+ { 129, 5, 12, 0, -64, }, /* 631 */
+ { 129, 15, 12, 0, 0, }, /* 632 */
+ { 0, 15, 12, 0, 0, }, /* 633 */
+ { 93, 10, 5, 0, 0, }, /* 634 */
+ { 93, 12, 3, 0, 0, }, /* 635 */
+ { 93, 7, 12, 0, 0, }, /* 636 */
+ { 93, 21, 12, 0, 0, }, /* 637 */
+ { 93, 15, 12, 0, 0, }, /* 638 */
+ { 93, 13, 12, 0, 0, }, /* 639 */
+ { 84, 12, 3, 0, 0, }, /* 640 */
+ { 84, 10, 5, 0, 0, }, /* 641 */
+ { 84, 7, 12, 0, 0, }, /* 642 */
+ { 84, 21, 12, 0, 0, }, /* 643 */
+ { 84, 1, 2, 0, 0, }, /* 644 */
+ { 100, 7, 12, 0, 0, }, /* 645 */
+ { 100, 13, 12, 0, 0, }, /* 646 */
+ { 95, 12, 3, 0, 0, }, /* 647 */
+ { 95, 7, 12, 0, 0, }, /* 648 */
+ { 95, 10, 5, 0, 0, }, /* 649 */
+ { 95, 13, 12, 0, 0, }, /* 650 */
+ { 95, 21, 12, 0, 0, }, /* 651 */
+ { 110, 7, 12, 0, 0, }, /* 652 */
+ { 110, 12, 3, 0, 0, }, /* 653 */
+ { 110, 21, 12, 0, 0, }, /* 654 */
+ { 99, 12, 3, 0, 0, }, /* 655 */
+ { 99, 10, 5, 0, 0, }, /* 656 */
+ { 99, 7, 12, 0, 0, }, /* 657 */
+ { 99, 21, 12, 0, 0, }, /* 658 */
+ { 99, 13, 12, 0, 0, }, /* 659 */
+ { 47, 15, 12, 0, 0, }, /* 660 */
+ { 107, 7, 12, 0, 0, }, /* 661 */
+ { 107, 10, 5, 0, 0, }, /* 662 */
+ { 107, 12, 3, 0, 0, }, /* 663 */
+ { 107, 21, 12, 0, 0, }, /* 664 */
+ { 128, 7, 12, 0, 0, }, /* 665 */
+ { 128, 21, 12, 0, 0, }, /* 666 */
+ { 108, 7, 12, 0, 0, }, /* 667 */
+ { 108, 12, 3, 0, 0, }, /* 668 */
+ { 108, 10, 5, 0, 0, }, /* 669 */
+ { 108, 13, 12, 0, 0, }, /* 670 */
+ { 106, 12, 3, 0, 0, }, /* 671 */
+ { 106, 10, 5, 0, 0, }, /* 672 */
+ { 106, 7, 12, 0, 0, }, /* 673 */
+ { 106, 10, 3, 0, 0, }, /* 674 */
+ { 123, 7, 12, 0, 0, }, /* 675 */
+ { 123, 10, 3, 0, 0, }, /* 676 */
+ { 123, 10, 5, 0, 0, }, /* 677 */
+ { 123, 12, 3, 0, 0, }, /* 678 */
+ { 123, 21, 12, 0, 0, }, /* 679 */
+ { 123, 13, 12, 0, 0, }, /* 680 */
+ { 122, 7, 12, 0, 0, }, /* 681 */
+ { 122, 10, 3, 0, 0, }, /* 682 */
+ { 122, 10, 5, 0, 0, }, /* 683 */
+ { 122, 12, 3, 0, 0, }, /* 684 */
+ { 122, 21, 12, 0, 0, }, /* 685 */
+ { 113, 7, 12, 0, 0, }, /* 686 */
+ { 113, 10, 5, 0, 0, }, /* 687 */
+ { 113, 12, 3, 0, 0, }, /* 688 */
+ { 113, 21, 12, 0, 0, }, /* 689 */
+ { 113, 13, 12, 0, 0, }, /* 690 */
+ { 101, 7, 12, 0, 0, }, /* 691 */
+ { 101, 12, 3, 0, 0, }, /* 692 */
+ { 101, 10, 5, 0, 0, }, /* 693 */
+ { 101, 13, 12, 0, 0, }, /* 694 */
+ { 125, 7, 12, 0, 0, }, /* 695 */
+ { 125, 12, 3, 0, 0, }, /* 696 */
+ { 125, 10, 5, 0, 0, }, /* 697 */
+ { 125, 13, 12, 0, 0, }, /* 698 */
+ { 125, 15, 12, 0, 0, }, /* 699 */
+ { 125, 21, 12, 0, 0, }, /* 700 */
+ { 125, 26, 12, 0, 0, }, /* 701 */
+ { 124, 9, 12, 0, 32, }, /* 702 */
+ { 124, 5, 12, 0, -32, }, /* 703 */
+ { 124, 13, 12, 0, 0, }, /* 704 */
+ { 124, 15, 12, 0, 0, }, /* 705 */
+ { 124, 7, 12, 0, 0, }, /* 706 */
+ { 121, 7, 12, 0, 0, }, /* 707 */
+ { 62, 7, 12, 0, 0, }, /* 708 */
+ { 62, 14, 12, 0, 0, }, /* 709 */
+ { 62, 21, 12, 0, 0, }, /* 710 */
+ { 79, 7, 12, 0, 0, }, /* 711 */
+ { 126, 7, 12, 0, 0, }, /* 712 */
+ { 114, 7, 12, 0, 0, }, /* 713 */
+ { 114, 13, 12, 0, 0, }, /* 714 */
+ { 114, 21, 12, 0, 0, }, /* 715 */
+ { 102, 7, 12, 0, 0, }, /* 716 */
+ { 102, 12, 3, 0, 0, }, /* 717 */
+ { 102, 21, 12, 0, 0, }, /* 718 */
+ { 118, 7, 12, 0, 0, }, /* 719 */
+ { 118, 12, 3, 0, 0, }, /* 720 */
+ { 118, 21, 12, 0, 0, }, /* 721 */
+ { 118, 26, 12, 0, 0, }, /* 722 */
+ { 118, 6, 12, 0, 0, }, /* 723 */
+ { 118, 13, 12, 0, 0, }, /* 724 */
+ { 118, 15, 12, 0, 0, }, /* 725 */
+ { 98, 7, 12, 0, 0, }, /* 726 */
+ { 98, 10, 5, 0, 0, }, /* 727 */
+ { 98, 12, 3, 0, 0, }, /* 728 */
+ { 98, 6, 12, 0, 0, }, /* 729 */
+ { 104, 7, 12, 0, 0, }, /* 730 */
+ { 104, 26, 12, 0, 0, }, /* 731 */
+ { 104, 12, 3, 0, 0, }, /* 732 */
+ { 104, 21, 12, 0, 0, }, /* 733 */
+ { 9, 10, 3, 0, 0, }, /* 734 */
+ { 19, 12, 3, 0, 0, }, /* 735 */
+ { 130, 26, 12, 0, 0, }, /* 736 */
+ { 130, 12, 3, 0, 0, }, /* 737 */
+ { 130, 21, 12, 0, 0, }, /* 738 */
+ { 112, 7, 12, 0, 0, }, /* 739 */
+ { 112, 15, 12, 0, 0, }, /* 740 */
+ { 112, 12, 3, 0, 0, }, /* 741 */
+ { 9, 26, 11, 0, 0, }, /* 742 */
+ { 26, 26, 12, 0, 0, }, /* 743 */
};
-const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */
+const uint8_t 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, 35, 36, 37, 38, 39, 40, 41, 41, 41, 42, 43, 44, 45, /* U+1000 */
@@ -836,19 +863,19 @@ const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */
123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+F000 */
123,123, 95, 95,124,125,126,127,128,128,129,130,131,132,133,134, /* U+F800 */
135,136,137,138,139,140,141,142,143,144,145,139,146,146,147,139, /* U+10000 */
-148,149,150,151,152,153,154,155,156,139,139,139,157,139,139,139, /* U+10800 */
-158,159,160,161,162,163,164,139,139,165,139,166,167,168,139,139, /* U+11000 */
-139,169,139,139,139,170,139,139,139,139,139,139,139,139,139,139, /* U+11800 */
-171,171,171,171,171,171,171,172,173,139,139,139,139,139,139,139, /* U+12000 */
+148,149,150,151,152,153,154,155,156,157,139,139,158,139,139,139, /* U+10800 */
+159,160,161,162,163,164,165,139,139,166,139,167,168,169,170,139, /* U+11000 */
+139,171,139,139,139,172,139,139,139,139,139,139,139,139,139,139, /* U+11800 */
+173,173,173,173,173,173,173,174,175,173,176,139,139,139,139,139, /* U+12000 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+12800 */
-174,174,174,174,174,174,174,174,175,139,139,139,139,139,139,139, /* U+13000 */
+177,177,177,177,177,177,177,177,178,139,139,139,139,139,139,139, /* U+13000 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+13800 */
-139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+14000 */
+139,139,139,139,139,139,139,139,179,179,179,179,180,139,139,139, /* U+14000 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+14800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+15000 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+15800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+16000 */
-176,176,176,176,177,178,179,180,139,139,139,139,139,139,181,182, /* U+16800 */
+181,181,181,181,182,183,184,185,139,139,139,139,139,139,186,187, /* U+16800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+17000 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+17800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+18000 */
@@ -857,16 +884,16 @@ const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+19800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1A000 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1A800 */
-183,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1B000 */
-139,139,139,139,139,139,139,139,184,185,139,139,139,139,139,139, /* U+1B800 */
+188,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1B000 */
+139,139,139,139,139,139,139,139,189,190,139,139,139,139,139,139, /* U+1B800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1C000 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1C800 */
- 71,186,187,188,189,139,190,139,191,192,193,194,195,196,197,198, /* U+1D000 */
-139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1D800 */
+ 71,191,192,193,194,139,195,139,196,197,198,199,200,201,202,203, /* U+1D000 */
+204,204,204,204,205,206,139,139,139,139,139,139,139,139,139,139, /* U+1D800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1E000 */
-199,200,139,139,139,139,139,139,139,139,139,139,201,202,139,139, /* U+1E800 */
-203,204,205,206,207,139,208,209, 71,210,211,212,213,214,215,216, /* U+1F000 */
-217,218,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1F800 */
+207,208,139,139,139,139,139,139,139,139,139,139,209,210,139,139, /* U+1E800 */
+211,212,213,214,215,139, 71,216, 71, 71,217,218, 71,219,220,221, /* U+1F000 */
+222,223,224,225,139,139,139,139,139,139,139,139,139,139,139,139, /* U+1F800 */
95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+20000 */
95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+20800 */
95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+21000 */
@@ -887,18 +914,18 @@ const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */
95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+28800 */
95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+29000 */
95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+29800 */
- 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,219, 95, 95, /* U+2A000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,226, 95, 95, /* U+2A000 */
95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+2A800 */
- 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,220, 95, /* U+2B000 */
-221,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2B800 */
-139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2C000 */
-139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2C800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,227, 95, /* U+2B000 */
+228, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+2B800 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, /* U+2C000 */
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,229,139,139, /* U+2C800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2D000 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2D800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2E000 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2E800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+2F000 */
- 95, 95, 95, 95,221,139,139,139,139,139,139,139,139,139,139,139, /* U+2F800 */
+ 95, 95, 95, 95,230,139,139,139,139,139,139,139,139,139,139,139, /* U+2F800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+30000 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+30800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+31000 */
@@ -1251,8 +1278,8 @@ const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DE800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DF000 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+DF800 */
-222,223,224,225,223,223,223,223,223,223,223,223,223,223,223,223, /* U+E0000 */
-223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, /* U+E0800 */
+231,232,233,234,232,232,232,232,232,232,232,232,232,232,232,232, /* U+E0000 */
+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232, /* U+E0800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E1000 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E1800 */
139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139, /* U+E2000 */
@@ -1314,7 +1341,7 @@ const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */
123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FE000 */
123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FE800 */
123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+FF000 */
-123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,226, /* U+FF800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,235, /* U+FF800 */
123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+100000 */
123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+100800 */
123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+101000 */
@@ -1346,10 +1373,10 @@ const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */
123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10E000 */
123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10E800 */
123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, /* U+10F000 */
-123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,226, /* U+10F800 */
+123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,235, /* U+10F800 */
};
-const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
+const uint16_t PRIV(ucd_stage2)[] = { /* 60416 bytes, block = 128 */
/* block 0 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -1402,533 +1429,533 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
/* block 5 */
99, 33, 33, 99, 33, 33, 33,100, 99,101,102,102,103, 33, 33, 33,
- 33, 33,104, 33, 20, 33, 33, 33, 33, 33, 33, 33, 33, 33,105, 33,
+ 33, 33,104, 33, 20, 33, 33, 33, 33, 33, 33, 33, 33,105,106, 33,
33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
-106,106,106,106,106,106,106,106,106,107,107,107,107,107,107,107,
-107,107, 14, 14, 14, 14,107,107,107,107,107,107,107,107,107,107,
-107,107, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-106,106,106,106,106, 14, 14, 14, 14, 14,108,108,107, 14,107, 14,
+107,107,107,107,107,107,107,107,107,108,108,108,108,108,108,108,
+108,108, 14, 14, 14, 14,108,108,108,108,108,108,108,108,108,108,
+108,108, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+107,107,107,107,107, 14, 14, 14, 14, 14,109,109,108, 14,108, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
/* block 6 */
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,110,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-111,112,111,112,107,113,111,112,114,114,115,116,116,116, 4,117,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,111,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+112,113,112,113,108,114,112,113,115,115,116,117,117,117, 4,118,
/* block 7 */
-114,114,114,114,113, 14,118, 4,119,119,119,114,120,114,121,121,
-122,123,124,123,123,125,123,123,126,127,128,123,129,123,123,123,
-130,131,114,132,123,123,133,123,123,134,123,123,135,136,136,136,
-122,137,138,137,137,139,137,137,140,141,142,137,143,137,137,137,
-144,145,146,147,137,137,148,137,137,149,137,137,150,151,151,152,
-153,154,155,155,155,156,157,158,111,112,111,112,111,112,111,112,
-111,112,159,160,159,160,159,160,159,160,159,160,159,160,159,160,
-161,162,163,164,165,166,167,111,112,168,111,112,122,169,169,169,
+115,115,115,115,114, 14,119, 4,120,120,120,115,121,115,122,122,
+123,124,125,124,124,126,124,124,127,128,129,124,130,124,124,124,
+131,132,115,133,124,124,134,124,124,135,124,124,136,137,137,137,
+123,138,139,138,138,140,138,138,141,142,143,138,144,138,138,138,
+145,146,147,148,138,138,149,138,138,150,138,138,151,152,152,153,
+154,155,156,156,156,157,158,159,112,113,112,113,112,113,112,113,
+112,113,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
+162,163,164,165,166,167,168,112,113,169,112,113,123,170,170,170,
/* block 8 */
-170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
-171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
+173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
+174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
/* block 9 */
-174,175,176,177,177,109,109,177,178,178,174,175,174,175,174,175,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
-179,174,175,174,175,174,175,174,175,174,175,174,175,174,175,180,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
+175,176,177,178,178,110,110,178,179,179,175,176,175,176,175,176,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
+180,175,176,175,176,175,176,175,176,175,176,175,176,175,176,181,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
/* block 10 */
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
-114,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
-181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,
-181,181,181,181,181,181,181,114,114,182,183,183,183,183,183,183,
-114,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
-184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
+115,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
+182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
+182,182,182,182,182,182,182,115,115,183,184,184,184,184,184,184,
+115,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
+185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
/* block 11 */
-184,184,184,184,184,184,184,185,114, 4,186,114,114,187,187,188,
-114,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
-189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
-189,189,189,189,189,189,189,189,189,189,189,189,189,189,190,189,
-191,189,189,191,189,189,191,189,114,114,114,114,114,114,114,114,
-192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
-192,192,192,192,192,192,192,192,192,192,192,114,114,114,114,114,
-192,192,192,191,191,114,114,114,114,114,114,114,114,114,114,114,
+185,185,185,185,185,185,185,186,115, 4,187,115,115,188,188,189,
+115,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,
+190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,
+190,190,190,190,190,190,190,190,190,190,190,190,190,190,191,190,
+192,190,190,192,190,190,192,190,115,115,115,115,115,115,115,115,
+193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,
+193,193,193,193,193,193,193,193,193,193,193,115,115,115,115,115,
+193,193,193,192,192,115,115,115,115,115,115,115,115,115,115,115,
/* block 12 */
-193,193,193,193,193, 22,194,194,194,195,195,196, 4,195,197,197,
-198,198,198,198,198,198,198,198,198,198,198, 4, 22,114,195, 4,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-107,199,199,199,199,199,199,199,199,199,199,109,109,109,109,109,
-109,109,109,109,109,109,198,198,198,198,198,198,198,198,198,198,
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,195,195,195,195,199,199,
-109,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
+194,194,194,194,194, 22,195,195,195,196,196,197, 4,196,198,198,
+199,199,199,199,199,199,199,199,199,199,199, 4, 22,115,196, 4,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+108,200,200,200,200,200,200,200,200,200,200,110,110,110,110,110,
+110,110,110,110,110,110,199,199,199,199,199,199,199,199,199,199,
+201,201,201,201,201,201,201,201,201,201,196,196,196,196,200,200,
+110,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
/* block 13 */
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,195,199,198,198,198,198,198,198,198, 22,197,198,
-198,198,198,198,198,200,200,198,198,197,198,198,198,198,199,199,
-201,201,201,201,201,201,201,201,201,201,199,199,199,197,197,199,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,196,200,199,199,199,199,199,199,199, 22,198,199,
+199,199,199,199,199,202,202,199,199,198,199,199,199,199,200,200,
+201,201,201,201,201,201,201,201,201,201,200,200,200,198,198,200,
/* block 14 */
-202,202,202,202,202,202,202,202,202,202,202,202,202,202,114,203,
-204,205,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
-204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,
+203,203,203,203,203,203,203,203,203,203,203,203,203,203,115,204,
+205,206,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,
-205,205,205,205,205,205,205,205,205,205,205,114,114,204,204,204,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
+206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,
+206,206,206,206,206,206,206,206,206,206,206,115,115,205,205,205,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
/* block 15 */
-206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,
-206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,
-206,206,206,206,206,206,207,207,207,207,207,207,207,207,207,207,
-207,206,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-208,208,208,208,208,208,208,208,208,208,209,209,209,209,209,209,
-209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,
-209,209,209,209,209,209,209,209,209,209,209,210,210,210,210,210,
-210,210,210,210,211,211,212,213,213,213,211,114,114,114,114,114,
+207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,
+207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,
+207,207,207,207,207,207,208,208,208,208,208,208,208,208,208,208,
+208,207,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+209,209,209,209,209,209,209,209,209,209,210,210,210,210,210,210,
+210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,
+210,210,210,210,210,210,210,210,210,210,210,211,211,211,211,211,
+211,211,211,211,212,212,213,214,214,214,212,115,115,115,115,115,
/* block 16 */
-214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,
-214,214,214,214,214,214,215,215,215,215,216,215,215,215,215,215,
-215,215,215,215,216,215,215,215,216,215,215,215,215,215,114,114,
-217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,114,
-218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,
-218,218,218,218,218,218,218,218,218,219,219,219,114,114,220,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,
+215,215,215,215,215,215,216,216,216,216,217,216,216,216,216,216,
+216,216,216,216,217,216,216,216,217,216,216,216,216,216,115,115,
+218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,115,
+219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,
+219,219,219,219,219,219,219,219,219,220,220,220,115,115,221,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 17 */
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,199,199,199,199,199,199,199,199,199,199,199,199,199,
199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,198,198,198,198,198,198,198,198,198,198,198,198,
-198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,
/* block 18 */
-221,221,221,222,223,223,223,223,223,223,223,223,223,223,223,223,
-223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
-223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
-223,223,223,223,223,223,223,223,223,223,221,222,221,223,222,222,
-222,221,221,221,221,221,221,221,221,222,222,222,222,221,222,222,
-223,109,109,221,221,221,221,221,223,223,223,223,223,223,223,223,
-223,223,221,221, 4, 4,224,224,224,224,224,224,224,224,224,224,
-225,226,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
+222,222,222,223,224,224,224,224,224,224,224,224,224,224,224,224,
+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
+224,224,224,224,224,224,224,224,224,224,222,223,222,224,223,223,
+223,222,222,222,222,222,222,222,222,223,223,223,223,222,223,223,
+224,110,110,222,222,222,222,222,224,224,224,224,224,224,224,224,
+224,224,222,222, 4, 4,225,225,225,225,225,225,225,225,225,225,
+226,227,224,224,224,224,224,224,224,224,224,224,224,224,224,224,
/* block 19 */
-227,228,229,229,114,227,227,227,227,227,227,227,227,114,114,227,
-227,114,114,227,227,227,227,227,227,227,227,227,227,227,227,227,
-227,227,227,227,227,227,227,227,227,114,227,227,227,227,227,227,
-227,114,227,114,114,114,227,227,227,227,114,114,228,227,230,229,
-229,228,228,228,228,114,114,229,229,114,114,229,229,228,227,114,
-114,114,114,114,114,114,114,230,114,114,114,114,227,227,114,227,
-227,227,228,228,114,114,231,231,231,231,231,231,231,231,231,231,
-227,227,232,232,233,233,233,233,233,233,234,232,114,114,114,114,
+228,229,230,230,115,228,228,228,228,228,228,228,228,115,115,228,
+228,115,115,228,228,228,228,228,228,228,228,228,228,228,228,228,
+228,228,228,228,228,228,228,228,228,115,228,228,228,228,228,228,
+228,115,228,115,115,115,228,228,228,228,115,115,229,228,231,230,
+230,229,229,229,229,115,115,230,230,115,115,230,230,229,228,115,
+115,115,115,115,115,115,115,231,115,115,115,115,228,228,115,228,
+228,228,229,229,115,115,232,232,232,232,232,232,232,232,232,232,
+228,228,233,233,234,234,234,234,234,234,235,233,115,115,115,115,
/* block 20 */
-114,235,235,236,114,237,237,237,237,237,237,114,114,114,114,237,
-237,114,114,237,237,237,237,237,237,237,237,237,237,237,237,237,
-237,237,237,237,237,237,237,237,237,114,237,237,237,237,237,237,
-237,114,237,237,114,237,237,114,237,237,114,114,235,114,236,236,
-236,235,235,114,114,114,114,235,235,114,114,235,235,235,114,114,
-114,235,114,114,114,114,114,114,114,237,237,237,237,114,237,114,
-114,114,114,114,114,114,238,238,238,238,238,238,238,238,238,238,
-235,235,237,237,237,235,114,114,114,114,114,114,114,114,114,114,
+115,236,236,237,115,238,238,238,238,238,238,115,115,115,115,238,
+238,115,115,238,238,238,238,238,238,238,238,238,238,238,238,238,
+238,238,238,238,238,238,238,238,238,115,238,238,238,238,238,238,
+238,115,238,238,115,238,238,115,238,238,115,115,236,115,237,237,
+237,236,236,115,115,115,115,236,236,115,115,236,236,236,115,115,
+115,236,115,115,115,115,115,115,115,238,238,238,238,115,238,115,
+115,115,115,115,115,115,239,239,239,239,239,239,239,239,239,239,
+236,236,238,238,238,236,115,115,115,115,115,115,115,115,115,115,
/* block 21 */
-114,239,239,240,114,241,241,241,241,241,241,241,241,241,114,241,
-241,241,114,241,241,241,241,241,241,241,241,241,241,241,241,241,
-241,241,241,241,241,241,241,241,241,114,241,241,241,241,241,241,
-241,114,241,241,114,241,241,241,241,241,114,114,239,241,240,240,
-240,239,239,239,239,239,114,239,239,240,114,240,240,239,114,114,
-241,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-241,241,239,239,114,114,242,242,242,242,242,242,242,242,242,242,
-243,244,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+115,240,240,241,115,242,242,242,242,242,242,242,242,242,115,242,
+242,242,115,242,242,242,242,242,242,242,242,242,242,242,242,242,
+242,242,242,242,242,242,242,242,242,115,242,242,242,242,242,242,
+242,115,242,242,115,242,242,242,242,242,115,115,240,242,241,241,
+241,240,240,240,240,240,115,240,240,241,115,241,241,240,115,115,
+242,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+242,242,240,240,115,115,243,243,243,243,243,243,243,243,243,243,
+244,245,115,115,115,115,115,115,115,242,115,115,115,115,115,115,
/* block 22 */
-114,245,246,246,114,247,247,247,247,247,247,247,247,114,114,247,
-247,114,114,247,247,247,247,247,247,247,247,247,247,247,247,247,
-247,247,247,247,247,247,247,247,247,114,247,247,247,247,247,247,
-247,114,247,247,114,247,247,247,247,247,114,114,245,247,248,245,
-246,245,245,245,245,114,114,246,246,114,114,246,246,245,114,114,
-114,114,114,114,114,114,245,248,114,114,114,114,247,247,114,247,
-247,247,245,245,114,114,249,249,249,249,249,249,249,249,249,249,
-250,247,251,251,251,251,251,251,114,114,114,114,114,114,114,114,
+115,246,247,247,115,248,248,248,248,248,248,248,248,115,115,248,
+248,115,115,248,248,248,248,248,248,248,248,248,248,248,248,248,
+248,248,248,248,248,248,248,248,248,115,248,248,248,248,248,248,
+248,115,248,248,115,248,248,248,248,248,115,115,246,248,249,246,
+247,246,246,246,246,115,115,247,247,115,115,247,247,246,115,115,
+115,115,115,115,115,115,246,249,115,115,115,115,248,248,115,248,
+248,248,246,246,115,115,250,250,250,250,250,250,250,250,250,250,
+251,248,252,252,252,252,252,252,115,115,115,115,115,115,115,115,
/* block 23 */
-114,114,252,253,114,253,253,253,253,253,253,114,114,114,253,253,
-253,114,253,253,253,253,114,114,114,253,253,114,253,114,253,253,
-114,114,114,253,253,114,114,114,253,253,253,114,114,114,253,253,
-253,253,253,253,253,253,253,253,253,253,114,114,114,114,254,255,
-252,255,255,114,114,114,255,255,255,114,255,255,255,252,114,114,
-253,114,114,114,114,114,114,254,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,256,256,256,256,256,256,256,256,256,256,
-257,257,257,258,258,258,258,258,258,259,258,114,114,114,114,114,
+115,115,253,254,115,254,254,254,254,254,254,115,115,115,254,254,
+254,115,254,254,254,254,115,115,115,254,254,115,254,115,254,254,
+115,115,115,254,254,115,115,115,254,254,254,115,115,115,254,254,
+254,254,254,254,254,254,254,254,254,254,115,115,115,115,255,256,
+253,256,256,115,115,115,256,256,256,115,256,256,256,253,115,115,
+254,115,115,115,115,115,115,255,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,257,257,257,257,257,257,257,257,257,257,
+258,258,258,259,259,259,259,259,259,260,259,115,115,115,115,115,
/* block 24 */
-260,261,261,261,114,262,262,262,262,262,262,262,262,114,262,262,
-262,114,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
-262,262,262,262,262,262,262,262,262,114,262,262,262,262,262,262,
-262,262,262,262,262,262,262,262,262,262,114,114,114,262,260,260,
-260,261,261,261,261,114,260,260,260,114,260,260,260,260,114,114,
-114,114,114,114,114,260,260,114,262,262,114,114,114,114,114,114,
-262,262,260,260,114,114,263,263,263,263,263,263,263,263,263,263,
-114,114,114,114,114,114,114,114,264,264,264,264,264,264,264,265,
+261,262,262,262,115,263,263,263,263,263,263,263,263,115,263,263,
+263,115,263,263,263,263,263,263,263,263,263,263,263,263,263,263,
+263,263,263,263,263,263,263,263,263,115,263,263,263,263,263,263,
+263,263,263,263,263,263,263,263,263,263,115,115,115,263,261,261,
+261,262,262,262,262,115,261,261,261,115,261,261,261,261,115,115,
+115,115,115,115,115,261,261,115,263,263,263,115,115,115,115,115,
+263,263,261,261,115,115,264,264,264,264,264,264,264,264,264,264,
+115,115,115,115,115,115,115,115,265,265,265,265,265,265,265,266,
/* block 25 */
-114,266,267,267,114,268,268,268,268,268,268,268,268,114,268,268,
-268,114,268,268,268,268,268,268,268,268,268,268,268,268,268,268,
-268,268,268,268,268,268,268,268,268,114,268,268,268,268,268,268,
-268,268,268,268,114,268,268,268,268,268,114,114,266,268,267,266,
-267,267,269,267,267,114,266,267,267,114,267,267,266,266,114,114,
-114,114,114,114,114,269,269,114,114,114,114,114,114,114,268,114,
-268,268,266,266,114,114,270,270,270,270,270,270,270,270,270,270,
-114,268,268,114,114,114,114,114,114,114,114,114,114,114,114,114,
+115,267,268,268,115,269,269,269,269,269,269,269,269,115,269,269,
+269,115,269,269,269,269,269,269,269,269,269,269,269,269,269,269,
+269,269,269,269,269,269,269,269,269,115,269,269,269,269,269,269,
+269,269,269,269,115,269,269,269,269,269,115,115,267,269,268,267,
+268,268,270,268,268,115,267,268,268,115,268,268,267,267,115,115,
+115,115,115,115,115,270,270,115,115,115,115,115,115,115,269,115,
+269,269,267,267,115,115,271,271,271,271,271,271,271,271,271,271,
+115,269,269,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 26 */
-114,271,272,272,114,273,273,273,273,273,273,273,273,114,273,273,
-273,114,273,273,273,273,273,273,273,273,273,273,273,273,273,273,
-273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,
-273,273,273,273,273,273,273,273,273,273,273,114,114,273,274,272,
-272,271,271,271,271,114,272,272,272,114,272,272,272,271,273,114,
-114,114,114,114,114,114,114,274,114,114,114,114,114,114,114,114,
-273,273,271,271,114,114,275,275,275,275,275,275,275,275,275,275,
-276,276,276,276,276,276,114,114,114,277,273,273,273,273,273,273,
+115,272,273,273,115,274,274,274,274,274,274,274,274,115,274,274,
+274,115,274,274,274,274,274,274,274,274,274,274,274,274,274,274,
+274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,
+274,274,274,274,274,274,274,274,274,274,274,115,115,274,275,273,
+273,272,272,272,272,115,273,273,273,115,273,273,273,272,274,115,
+115,115,115,115,115,115,115,275,115,115,115,115,115,115,115,274,
+274,274,272,272,115,115,276,276,276,276,276,276,276,276,276,276,
+277,277,277,277,277,277,115,115,115,278,274,274,274,274,274,274,
/* block 27 */
-114,114,278,278,114,279,279,279,279,279,279,279,279,279,279,279,
-279,279,279,279,279,279,279,114,114,114,279,279,279,279,279,279,
-279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,
-279,279,114,279,279,279,279,279,279,279,279,279,114,279,114,114,
-279,279,279,279,279,279,279,114,114,114,280,114,114,114,114,281,
-278,278,280,280,280,114,280,114,278,278,278,278,278,278,278,281,
-114,114,114,114,114,114,282,282,282,282,282,282,282,282,282,282,
-114,114,278,278,283,114,114,114,114,114,114,114,114,114,114,114,
+115,115,279,279,115,280,280,280,280,280,280,280,280,280,280,280,
+280,280,280,280,280,280,280,115,115,115,280,280,280,280,280,280,
+280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,
+280,280,115,280,280,280,280,280,280,280,280,280,115,280,115,115,
+280,280,280,280,280,280,280,115,115,115,281,115,115,115,115,282,
+279,279,281,281,281,115,281,115,279,279,279,279,279,279,279,282,
+115,115,115,115,115,115,283,283,283,283,283,283,283,283,283,283,
+115,115,279,279,284,115,115,115,115,115,115,115,115,115,115,115,
/* block 28 */
-114,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,
-284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,
-284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,
-284,285,284,286,285,285,285,285,285,285,285,114,114,114,114, 5,
-284,284,284,284,284,284,287,285,285,285,285,285,285,285,285,288,
-289,289,289,289,289,289,289,289,289,289,288,288,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+115,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,
+285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,
+285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,
+285,286,285,287,286,286,286,286,286,286,286,115,115,115,115, 5,
+285,285,285,285,285,285,288,286,286,286,286,286,286,286,286,289,
+290,290,290,290,290,290,290,290,290,290,289,289,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 29 */
-114,290,290,114,290,114,114,290,290,114,290,114,114,290,114,114,
-114,114,114,114,290,290,290,290,114,290,290,290,290,290,290,290,
-114,290,290,290,114,290,114,290,114,114,290,290,114,290,290,290,
-290,291,290,292,291,291,291,291,291,291,114,291,291,290,114,114,
-290,290,290,290,290,114,293,114,291,291,291,291,291,291,114,114,
-294,294,294,294,294,294,294,294,294,294,114,114,290,290,290,290,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+115,291,291,115,291,115,115,291,291,115,291,115,115,291,115,115,
+115,115,115,115,291,291,291,291,115,291,291,291,291,291,291,291,
+115,291,291,291,115,291,115,291,115,115,291,291,115,291,291,291,
+291,292,291,293,292,292,292,292,292,292,115,292,292,291,115,115,
+291,291,291,291,291,115,294,115,292,292,292,292,292,292,115,115,
+295,295,295,295,295,295,295,295,295,295,115,115,291,291,291,291,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 30 */
-295,296,296,296,297,297,297,297,297,297,297,297,297,297,297,297,
-297,297,297,296,297,296,296,296,298,298,296,296,296,296,296,296,
-299,299,299,299,299,299,299,299,299,299,300,300,300,300,300,300,
-300,300,300,300,296,298,296,298,296,298,301,302,301,302,303,303,
-295,295,295,295,295,295,295,295,114,295,295,295,295,295,295,295,
-295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,
-295,295,295,295,295,295,295,295,295,295,295,295,295,114,114,114,
-114,298,298,298,298,298,298,298,298,298,298,298,298,298,298,303,
+296,297,297,297,298,298,298,298,298,298,298,298,298,298,298,298,
+298,298,298,297,298,297,297,297,299,299,297,297,297,297,297,297,
+300,300,300,300,300,300,300,300,300,300,301,301,301,301,301,301,
+301,301,301,301,297,299,297,299,297,299,302,303,302,303,304,304,
+296,296,296,296,296,296,296,296,115,296,296,296,296,296,296,296,
+296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,
+296,296,296,296,296,296,296,296,296,296,296,296,296,115,115,115,
+115,299,299,299,299,299,299,299,299,299,299,299,299,299,299,304,
/* block 31 */
-298,298,298,298,298,297,298,298,295,295,295,295,295,298,298,298,
-298,298,298,298,298,298,298,298,114,298,298,298,298,298,298,298,
-298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,
-298,298,298,298,298,298,298,298,298,298,298,298,298,114,296,296,
-296,296,296,296,296,296,298,296,296,296,296,296,296,114,296,296,
-297,297,297,297,297, 19, 19, 19, 19,297,297,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+299,299,299,299,299,298,299,299,296,296,296,296,296,299,299,299,
+299,299,299,299,299,299,299,299,115,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,299,299,299,299,299,299,115,297,297,
+297,297,297,297,297,297,299,297,297,297,297,297,297,115,297,297,
+298,298,298,298,298, 19, 19, 19, 19,298,298,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 32 */
-304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,
-304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,
-304,304,304,304,304,304,304,304,304,304,304,305,305,306,306,306,
-306,307,306,306,306,306,306,306,305,306,306,307,307,306,306,304,
-308,308,308,308,308,308,308,308,308,308,309,309,309,309,309,309,
-304,304,304,304,304,304,307,307,306,306,304,304,304,304,306,306,
-306,304,305,305,305,304,304,305,305,305,305,305,305,305,304,304,
-304,306,306,306,306,304,304,304,304,304,304,304,304,304,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,
+305,305,305,305,305,305,305,305,305,305,305,306,306,307,307,307,
+307,308,307,307,307,307,307,307,306,307,307,308,308,307,307,305,
+309,309,309,309,309,309,309,309,309,309,310,310,310,310,310,310,
+305,305,305,305,305,305,308,308,307,307,305,305,305,305,307,307,
+307,305,306,306,306,305,305,306,306,306,306,306,306,306,305,305,
+305,307,307,307,307,305,305,305,305,305,305,305,305,305,305,305,
/* block 33 */
-304,304,306,305,307,306,306,305,305,305,305,305,305,306,304,305,
-308,308,308,308,308,308,308,308,308,308,305,305,305,306,310,310,
-311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,
-311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,
-311,311,311,311,311,311,114,311,114,114,114,114,114,311,114,114,
+305,305,307,306,308,307,307,306,306,306,306,306,306,307,305,306,
+309,309,309,309,309,309,309,309,309,309,306,306,306,307,311,311,
312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,
312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,
-312,312,312,312,312,312,312,312,312,312,312, 4,313,312,312,312,
+312,312,312,312,312,312,115,312,115,115,115,115,115,312,115,115,
+313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
+313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
+313,313,313,313,313,313,313,313,313,313,313, 4,314,313,313,313,
/* block 34 */
-314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
-314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
-314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
-314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
-314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
-314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
-
-/* block 35 */
315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
-315,315,315,315,315,315,315,315,316,316,316,316,316,316,316,316,
-316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,
316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,
+
+/* block 35 */
316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,
316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,
-
-/* block 36 */
+316,316,316,316,316,316,316,316,317,317,317,317,317,317,317,317,
317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
-317,317,317,317,317,317,317,317,317,114,317,317,317,317,114,114,
-317,317,317,317,317,317,317,114,317,114,317,317,317,317,114,114,
-317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
+/* block 36 */
+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,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,115,318,318,318,318,115,115,
+318,318,318,318,318,318,318,115,318,115,318,318,318,318,115,115,
+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,
+
/* block 37 */
-317,317,317,317,317,317,317,317,317,114,317,317,317,317,114,114,
-317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
-317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
-317,114,317,317,317,317,114,114,317,317,317,317,317,317,317,114,
-317,114,317,317,317,317,114,114,317,317,317,317,317,317,317,317,
-317,317,317,317,317,317,317,114,317,317,317,317,317,317,317,317,
-317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
-317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
+318,318,318,318,318,318,318,318,318,115,318,318,318,318,115,115,
+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,115,318,318,318,318,115,115,318,318,318,318,318,318,318,115,
+318,115,318,318,318,318,115,115,318,318,318,318,318,318,318,318,
+318,318,318,318,318,318,318,115,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,
/* block 38 */
-317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
-317,114,317,317,317,317,114,114,317,317,317,317,317,317,317,317,
-317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
-317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
-317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
-317,317,317,317,317,317,317,317,317,317,317,114,114,318,318,318,
-319,319,319,319,319,319,319,319,319,320,320,320,320,320,320,320,
-320,320,320,320,320,320,320,320,320,320,320,320,320,114,114,114,
+318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,
+318,115,318,318,318,318,115,115,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,318,318,318,318,318,318,318,318,318,
+318,318,318,318,318,318,318,318,318,318,318,115,115,319,319,319,
+320,320,320,320,320,320,320,320,320,321,321,321,321,321,321,321,
+321,321,321,321,321,321,321,321,321,321,321,321,321,115,115,115,
/* block 39 */
-317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
-321,321,321,321,321,321,321,321,321,321,114,114,114,114,114,114,
-322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,
-322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,
-322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,
-322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,
-322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,
-322,322,322,322,322,114,114,114,114,114,114,114,114,114,114,114,
+318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,
+322,322,322,322,322,322,322,322,322,322,115,115,115,115,115,115,
+323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,
+323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,
+323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,
+323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,
+323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,
+324,324,324,324,324,324,115,115,325,325,325,325,325,325,115,115,
/* block 40 */
-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,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
+326,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
/* block 41 */
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
/* block 42 */
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,325,325,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,328,328,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
/* block 43 */
-326,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
-327,327,327,327,327,327,327,327,327,327,327,328,329,114,114,114,
-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,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,330,330,330, 4, 4, 4,331,331,
-331,330,330,330,330,330,330,330,330,114,114,114,114,114,114,114,
+329,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,332,115,115,115,
+333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
+333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
+333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
+333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
+333,333,333,333,333,333,333,333,333,333,333, 4, 4, 4,334,334,
+334,333,333,333,333,333,333,333,333,115,115,115,115,115,115,115,
/* block 44 */
-332,332,332,332,332,332,332,332,332,332,332,332,332,114,332,332,
-332,332,333,333,333,114,114,114,114,114,114,114,114,114,114,114,
-334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,
-334,334,335,335,335, 4, 4,114,114,114,114,114,114,114,114,114,
-336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
-336,336,337,337,114,114,114,114,114,114,114,114,114,114,114,114,
-338,338,338,338,338,338,338,338,338,338,338,338,338,114,338,338,
-338,114,339,339,114,114,114,114,114,114,114,114,114,114,114,114,
+335,335,335,335,335,335,335,335,335,335,335,335,335,115,335,335,
+335,335,336,336,336,115,115,115,115,115,115,115,115,115,115,115,
+337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,
+337,337,338,338,338, 4, 4,115,115,115,115,115,115,115,115,115,
+339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,
+339,339,340,340,115,115,115,115,115,115,115,115,115,115,115,115,
+341,341,341,341,341,341,341,341,341,341,341,341,341,115,341,341,
+341,115,342,342,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 45 */
-340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
-340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
-340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
-340,340,340,340,341,341,342,341,341,341,341,341,341,341,342,342,
-342,342,342,342,342,342,341,342,342,341,341,341,341,341,341,341,
-341,341,341,341,343,343,343,344,343,343,343,345,340,341,114,114,
-346,346,346,346,346,346,346,346,346,346,114,114,114,114,114,114,
-347,347,347,347,347,347,347,347,347,347,114,114,114,114,114,114,
+343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,
+343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,
+343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,
+343,343,343,343,344,344,345,344,344,344,344,344,344,344,345,345,
+345,345,345,345,345,345,344,345,345,344,344,344,344,344,344,344,
+344,344,344,344,346,346,346,347,346,346,346,348,343,344,115,115,
+349,349,349,349,349,349,349,349,349,349,115,115,115,115,115,115,
+350,350,350,350,350,350,350,350,350,350,115,115,115,115,115,115,
/* block 46 */
-348,348, 4, 4,348, 4,349,348,348,348,348,350,350,350,351,114,
-352,352,352,352,352,352,352,352,352,352,114,114,114,114,114,114,
-353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,
-353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,
-353,353,353,354,353,353,353,353,353,353,353,353,353,353,353,353,
-353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,
-353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,
-353,353,353,353,353,353,353,353,114,114,114,114,114,114,114,114,
+351,351, 4, 4,351, 4,352,351,351,351,351,353,353,353,354,115,
+355,355,355,355,355,355,355,355,355,355,115,115,115,115,115,115,
+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,
+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,
+356,356,356,357,356,356,356,356,356,356,356,356,356,356,356,356,
+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,
+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,
+356,356,356,356,356,356,356,356,115,115,115,115,115,115,115,115,
/* block 47 */
-353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,
-353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,
-353,353,353,353,353,353,353,353,353,350,353,114,114,114,114,114,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,
-324,324,324,324,324,324,114,114,114,114,114,114,114,114,114,114,
+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,
+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,
+356,356,356,356,356,356,356,356,356,353,356,115,115,115,115,115,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,115,115,115,115,115,115,115,115,115,115,
/* block 48 */
-355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
-355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,114,
-356,356,356,357,357,357,357,356,356,357,357,357,114,114,114,114,
-357,357,356,357,357,357,357,357,357,356,356,356,114,114,114,114,
-358,114,114,114,359,359,360,360,360,360,360,360,360,360,360,360,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,114,114,
-361,361,361,361,361,114,114,114,114,114,114,114,114,114,114,114,
+358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
+358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,115,
+359,359,359,360,360,360,360,359,359,360,360,360,115,115,115,115,
+360,360,359,360,360,360,360,360,360,359,359,359,115,115,115,115,
+361,115,115,115,362,362,363,363,363,363,363,363,363,363,363,363,
+364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,
+364,364,364,364,364,364,364,364,364,364,364,364,364,364,115,115,
+364,364,364,364,364,115,115,115,115,115,115,115,115,115,115,115,
/* block 49 */
-362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,
-362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,
-362,362,362,362,362,362,362,362,362,362,362,362,114,114,114,114,
-363,363,363,363,363,364,364,364,363,363,364,363,363,363,363,363,
-363,362,362,362,362,362,362,362,363,363,114,114,114,114,114,114,
-365,365,365,365,365,365,365,365,365,365,366,114,114,114,367,367,
-368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,
-368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,
+365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,
+365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,
+365,365,365,365,365,365,365,365,365,365,365,365,115,115,115,115,
+365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,
+365,365,365,365,365,365,365,365,365,365,115,115,115,115,115,115,
+366,366,366,366,366,366,366,366,366,366,367,115,115,115,368,368,
+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,369,369,369,369,369,369,
/* block 50 */
-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,371,371,370,114,114,372,372,
-373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
-373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
-373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
-373,373,373,373,373,374,375,374,375,375,375,375,375,375,375,114,
-375,376,375,376,376,375,375,375,375,375,375,375,375,374,374,374,
-374,374,374,375,375,375,375,375,375,375,375,375,375,114,114,375,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,370,370,371,371,372,372,371,115,115,373,373,
+374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
+374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
+374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
+374,374,374,374,374,375,376,375,376,376,376,376,376,376,376,115,
+376,377,376,377,377,376,376,376,376,376,376,376,376,375,375,375,
+375,375,375,376,376,376,376,376,376,376,376,376,376,115,115,376,
/* block 51 */
-377,377,377,377,377,377,377,377,377,377,114,114,114,114,114,114,
-377,377,377,377,377,377,377,377,377,377,114,114,114,114,114,114,
-378,378,378,378,378,378,378,379,378,378,378,378,378,378,114,114,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,380,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+378,378,378,378,378,378,378,378,378,378,115,115,115,115,115,115,
+378,378,378,378,378,378,378,378,378,378,115,115,115,115,115,115,
+379,379,379,379,379,379,379,380,379,379,379,379,379,379,115,115,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,381,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 52 */
-381,381,381,381,382,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,381,382,381,381,381,381,381,382,381,382,382,382,
-382,382,381,382,382,383,383,383,383,383,383,383,114,114,114,114,
-384,384,384,384,384,384,384,384,384,384,385,385,385,385,385,385,
-385,386,386,386,386,386,386,386,386,386,386,381,381,381,381,381,
-381,381,381,381,386,386,386,386,386,386,386,386,386,114,114,114,
+382,382,382,382,383,384,384,384,384,384,384,384,384,384,384,384,
+384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,
+384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,
+384,384,384,384,382,383,382,382,382,382,382,383,382,383,383,383,
+383,383,382,383,383,384,384,384,384,384,384,384,115,115,115,115,
+385,385,385,385,385,385,385,385,385,385,386,386,386,386,386,386,
+386,387,387,387,387,387,387,387,387,387,387,382,382,382,382,382,
+382,382,382,382,387,387,387,387,387,387,387,387,387,115,115,115,
/* block 53 */
-387,387,388,389,389,389,389,389,389,389,389,389,389,389,389,389,
-389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,
-389,388,387,387,387,387,388,388,387,387,388,387,387,387,389,389,
-390,390,390,390,390,390,390,390,390,390,389,389,389,389,389,389,
-391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,
-391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,
-391,391,391,391,391,391,392,393,392,392,393,393,393,392,393,392,
-392,392,393,393,114,114,114,114,114,114,114,114,394,394,394,394,
+388,388,389,390,390,390,390,390,390,390,390,390,390,390,390,390,
+390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,
+390,389,388,388,388,388,389,389,388,388,389,388,388,388,390,390,
+391,391,391,391,391,391,391,391,391,391,390,390,390,390,390,390,
+392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,
+392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,
+392,392,392,392,392,392,393,394,393,393,394,394,394,393,394,393,
+393,393,394,394,115,115,115,115,115,115,115,115,395,395,395,395,
/* block 54 */
-395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,
-395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,
-395,395,395,395,396,396,396,396,396,396,396,396,397,397,397,397,
-397,397,397,397,396,396,397,397,114,114,114,398,398,398,398,398,
-399,399,399,399,399,399,399,399,399,399,114,114,114,395,395,395,
-400,400,400,400,400,400,400,400,400,400,401,401,401,401,401,401,
-401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,
-401,401,401,401,401,401,401,401,402,402,402,402,402,402,403,403,
+396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,
+396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,
+396,396,396,396,397,397,397,397,397,397,397,397,398,398,398,398,
+398,398,398,398,397,397,398,398,115,115,115,399,399,399,399,399,
+400,400,400,400,400,400,400,400,400,400,115,115,115,396,396,396,
+401,401,401,401,401,401,401,401,401,401,402,402,402,402,402,402,
+402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,
+402,402,402,402,402,402,402,402,403,403,403,403,403,403,404,404,
/* block 55 */
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-404,404,404,404,404,404,404,404,114,114,114,114,114,114,114,114,
-109,109,109, 4,109,109,109,109,109,109,109,109,109,109,109,109,
-109,405,109,109,109,109,109,109,109,406,406,406,406,109,406,406,
-406,406,405,405,109,406,406,114,109,109,114,114,114,114,114,114,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+405,405,405,405,405,405,405,405,115,115,115,115,115,115,115,115,
+110,110,110, 4,110,110,110,110,110,110,110,110,110,110,110,110,
+110,406,110,110,110,110,110,110,110,407,407,407,407,110,407,407,
+407,407,406,406,110,407,407,115,110,110,115,115,115,115,115,115,
/* block 56 */
33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33,122,122,122,122,122,407,106,106,106,106,
-106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
-106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
-106,106,106,106,106,106,106,106,106,106,106,106,106,115,115,115,
-115,115,106,106,106,106,115,115,115,115,115, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33,408,409, 33, 33, 33,410, 33, 33,
+ 33, 33, 33, 33, 33, 33,123,123,123,123,123,408,107,107,107,107,
+107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
+107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
+107,107,107,107,107,107,107,107,107,107,107,107,107,116,116,116,
+116,116,107,107,107,107,116,116,116,116,116, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33,409,410, 33, 33, 33,411, 33, 33,
/* block 57 */
33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,106,106,106,106,106,
-106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
-106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,115,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,114,114,114,114,114,114,109,109,109,109,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,107,107,107,107,107,
+107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
+107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,116,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,115,115,115,115,115,115,110,110,110,110,
/* block 58 */
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
@@ -1937,12 +1964,12 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
-411,412, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
+412,413, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
/* block 59 */
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 33, 33, 33, 33, 33,413, 33, 33,414, 33,
+ 30, 31, 30, 31, 30, 31, 33, 33, 33, 33, 33,414, 33, 33,415, 33,
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
@@ -1951,57 +1978,57 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
/* block 60 */
-415,415,415,415,415,415,415,415,416,416,416,416,416,416,416,416,
-415,415,415,415,415,415,114,114,416,416,416,416,416,416,114,114,
-415,415,415,415,415,415,415,415,416,416,416,416,416,416,416,416,
-415,415,415,415,415,415,415,415,416,416,416,416,416,416,416,416,
-415,415,415,415,415,415,114,114,416,416,416,416,416,416,114,114,
-122,415,122,415,122,415,122,415,114,416,114,416,114,416,114,416,
-415,415,415,415,415,415,415,415,416,416,416,416,416,416,416,416,
-417,417,418,418,418,418,419,419,420,420,421,421,422,422,114,114,
+416,416,416,416,416,416,416,416,417,417,417,417,417,417,417,417,
+416,416,416,416,416,416,115,115,417,417,417,417,417,417,115,115,
+416,416,416,416,416,416,416,416,417,417,417,417,417,417,417,417,
+416,416,416,416,416,416,416,416,417,417,417,417,417,417,417,417,
+416,416,416,416,416,416,115,115,417,417,417,417,417,417,115,115,
+123,416,123,416,123,416,123,416,115,417,115,417,115,417,115,417,
+416,416,416,416,416,416,416,416,417,417,417,417,417,417,417,417,
+418,418,419,419,419,419,420,420,421,421,422,422,423,423,115,115,
/* block 61 */
-415,415,415,415,415,415,415,415,423,423,423,423,423,423,423,423,
-415,415,415,415,415,415,415,415,423,423,423,423,423,423,423,423,
-415,415,415,415,415,415,415,415,423,423,423,423,423,423,423,423,
-415,415,122,424,122,114,122,122,416,416,425,425,426,113,427,113,
-113,113,122,424,122,114,122,122,428,428,428,428,426,113,113,113,
-415,415,122,122,114,114,122,122,416,416,429,429,114,113,113,113,
-415,415,122,122,122,163,122,122,416,416,430,430,168,113,113,113,
-114,114,122,424,122,114,122,122,431,431,432,432,426,113,113,114,
+416,416,416,416,416,416,416,416,424,424,424,424,424,424,424,424,
+416,416,416,416,416,416,416,416,424,424,424,424,424,424,424,424,
+416,416,416,416,416,416,416,416,424,424,424,424,424,424,424,424,
+416,416,123,425,123,115,123,123,417,417,426,426,427,114,428,114,
+114,114,123,425,123,115,123,123,429,429,429,429,427,114,114,114,
+416,416,123,123,115,115,123,123,417,417,430,430,115,114,114,114,
+416,416,123,123,123,164,123,123,417,417,431,431,169,114,114,114,
+115,115,123,425,123,115,123,123,432,432,433,433,427,114,114,115,
/* block 62 */
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 22,433,433, 22, 22,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 22,434,434, 22, 22,
9, 9, 9, 9, 9, 9, 4, 4, 21, 25, 6, 21, 21, 25, 6, 21,
- 4, 4, 4, 4, 4, 4, 4, 4,434,435, 22, 22, 22, 22, 22, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4,435,436, 22, 22, 22, 22, 22, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 21, 25, 4, 4, 4, 4, 15,
15, 4, 4, 4, 8, 6, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 8, 4, 15, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3,
- 22, 22, 22, 22, 22,436, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 23,106,114,114, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,106,
+ 22, 22, 22, 22, 22,437, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23,107,115,115, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,107,
/* block 63 */
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,114,
-106,106,106,106,106,106,106,106,106,106,106,106,106,114,114,114,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 8, 8, 8, 6, 7,115,
+107,107,107,107,107,107,107,107,107,107,107,107,107,115,115,115,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-109,109,109,109,109,109,109,109,109,109,109,109,109,380,380,380,
-380,109,380,380,380,109,109,109,109,109,109,109,109,109,109,109,
-109,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+110,110,110,110,110,110,110,110,110,110,110,110,110,381,381,381,
+381,110,381,381,381,110,110,110,110,110,110,110,110,110,110,110,
+110,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 64 */
- 19, 19,437, 19, 19, 19, 19,437, 19, 19,438,437,437,437,438,438,
-437,437,437,438, 19,437, 19, 19, 8,437,437,437,437,437, 19, 19,
- 19, 19, 19, 19,437, 19,439, 19,437, 19,440,441,437,437, 19,438,
-437,437,442,437,438,406,406,406,406,438, 19, 19,438,438,437,437,
- 8, 8, 8, 8, 8,437,438,438,438,438, 19, 8, 19, 19,443, 19,
+ 19, 19,438, 19, 19, 19, 19,438, 19, 19,439,438,438,438,439,439,
+438,438,438,439, 19,438, 19, 19, 8,438,438,438,438,438, 19, 19,
+ 19, 19, 19, 19,438, 19,440, 19,438, 19,441,442,438,438, 19,439,
+438,438,443,438,439,407,407,407,407,439, 19, 19,439,439,438,438,
+ 8, 8, 8, 8, 8,438,439,439,439,439, 19, 8, 19, 19,444, 19,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,
445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,
+446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,
/* block 65 */
-446,446,446, 30, 31,446,446,446,446, 23,114,114,114,114,114,114,
+447,447,447, 30, 31,447,447,447,447, 23, 19, 19,115,115,115,115,
8, 8, 8, 8, 8, 19, 19, 19, 19, 19, 8, 8, 19, 19, 19, 19,
8, 19, 19, 8, 19, 19, 8, 19, 19, 19, 19, 19, 19, 19, 8, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
@@ -2038,15 +2065,15 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 8, 8, 8, 8,
8, 8, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,
/* block 69 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+ 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
@@ -2054,10 +2081,10 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19,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,
+ 19, 19, 19, 19, 19, 19,448,448,448,448,448,448,448,448,448,448,
448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,
-448,448,448,448,448,448,448,448,448,448, 23, 23, 23, 23, 23, 23,
+449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,
+449,449,449,449,449,449,449,449,449,449, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
/* block 71 */
@@ -2111,14 +2138,14 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
/* block 76 */
-449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,
-449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,
-449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,
-449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,
-449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,
-449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,
-449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,
-449,449,449,449,449,449,449,449,449,449,449,449,449,449,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,450,450,450,450,450,450,450,450,450,
+450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,
+450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,
+450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,
+450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,
+450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,
+450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,
/* block 77 */
8, 8, 8, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6,
@@ -2138,147 +2165,147 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
8, 8, 8, 8, 8, 19, 19, 8, 8, 8, 8, 8, 8, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,114,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
/* block 79 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19,114,114, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19,115,115, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19,114, 19, 19, 19, 19, 19, 19,
- 19, 19,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19,115, 19, 19, 19, 19, 19, 19,
+ 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115, 19, 19, 19, 19,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 80 */
-450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,
-450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,
-450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,114,
451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,
451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,
-451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,114,
- 30, 31,452,453,454,455,456, 30, 31, 30, 31, 30, 31,457,458,459,
-460, 33, 30, 31, 33, 30, 31, 33, 33, 33, 33, 33,106,106,461,461,
+451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,115,
+452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,
+452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,
+452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,115,
+ 30, 31,453,454,455,456,457, 30, 31, 30, 31, 30, 31,458,459,460,
+461, 33, 30, 31, 33, 30, 31, 33, 33, 33, 33, 33,107,107,462,462,
/* block 81 */
-159,160,159,160,159,160,159,160,159,160,159,160,159,160,159,160,
-159,160,159,160,159,160,159,160,159,160,159,160,159,160,159,160,
-159,160,159,160,159,160,159,160,159,160,159,160,159,160,159,160,
-159,160,159,160,159,160,159,160,159,160,159,160,159,160,159,160,
-159,160,159,160,159,160,159,160,159,160,159,160,159,160,159,160,
-159,160,159,160,159,160,159,160,159,160,159,160,159,160,159,160,
-159,160,159,160,462,463,463,463,463,463,463,159,160,159,160,464,
-464,464,159,160,114,114,114,114,114,465,465,465,465,466,465,465,
+160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
+160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
+160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
+160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
+160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
+160,161,160,161,160,161,160,161,160,161,160,161,160,161,160,161,
+160,161,160,161,463,464,464,464,464,464,464,160,161,160,161,465,
+465,465,160,161,115,115,115,115,115,466,466,466,466,467,466,466,
/* block 82 */
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
-467,467,467,467,467,467,114,467,114,114,114,114,114,467,114,114,
-468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,
468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,
468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,
-468,468,468,468,468,468,468,468,114,114,114,114,114,114,114,469,
-470,114,114,114,114,114,114,114,114,114,114,114,114,114,114,471,
+468,468,468,468,468,468,115,468,115,115,115,115,115,468,115,115,
+469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,
+469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,
+469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,
+469,469,469,469,469,469,469,469,115,115,115,115,115,115,115,470,
+471,115,115,115,115,115,115,115,115,115,115,115,115,115,115,472,
/* block 83 */
-317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
-317,317,317,317,317,317,317,114,114,114,114,114,114,114,114,114,
-317,317,317,317,317,317,317,114,317,317,317,317,317,317,317,114,
-317,317,317,317,317,317,317,114,317,317,317,317,317,317,317,114,
-317,317,317,317,317,317,317,114,317,317,317,317,317,317,317,114,
-317,317,317,317,317,317,317,114,317,317,317,317,317,317,317,114,
-177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
-177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,
+318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,
+318,318,318,318,318,318,318,115,115,115,115,115,115,115,115,115,
+318,318,318,318,318,318,318,115,318,318,318,318,318,318,318,115,
+318,318,318,318,318,318,318,115,318,318,318,318,318,318,318,115,
+318,318,318,318,318,318,318,115,318,318,318,318,318,318,318,115,
+318,318,318,318,318,318,318,115,318,318,318,318,318,318,318,115,
+178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,
+178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,
/* block 84 */
4, 4, 21, 25, 21, 25, 4, 4, 4, 21, 25, 4, 21, 25, 4, 4,
4, 4, 4, 4, 4, 4, 4, 9, 4, 4, 9, 4, 21, 25, 4, 4,
- 21, 25, 6, 7, 6, 7, 6, 7, 6, 7, 4, 4, 4, 4, 4,107,
+ 21, 25, 6, 7, 6, 7, 6, 7, 6, 7, 4, 4, 4, 4, 4,108,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 4, 4, 4, 4,
- 9, 4, 6,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+ 9, 4, 6,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 85 */
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,114,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,114,114,114,114,114,114,114,114,114,114,114,114,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,115,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 86 */
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
/* block 87 */
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
-472,472,472,472,472,472,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
/* block 88 */
- 3, 4, 4, 4, 19,473,406,474, 6, 7, 6, 7, 6, 7, 6, 7,
+ 3, 4, 4, 4, 19,474,407,475, 6, 7, 6, 7, 6, 7, 6, 7,
6, 7, 19, 19, 6, 7, 6, 7, 6, 7, 6, 7, 9, 6, 7, 7,
- 19,474,474,474,474,474,474,474,474,474,109,109,109,109,475,475,
- 9,107,107,107,107,107, 19, 19,474,474,474,473,406, 4, 19, 19,
-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,
+ 19,475,475,475,475,475,475,475,475,475,110,110,110,110,476,476,
+ 9,108,108,108,108,108, 19, 19,475,475,475,474,407, 4, 19, 19,
+115,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,
+477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,
+477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,
+477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,
/* block 89 */
-476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
-476,476,476,476,476,476,476,114,114,109,109, 14, 14,477,477,476,
- 9,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
-478,478,478,478,478,478,478,478,478,478,478, 4,107,479,479,478,
+477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,
+477,477,477,477,477,477,477,115,115,110,110, 14, 14,478,478,477,
+ 9,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, 4,108,480,480,479,
/* block 90 */
-114,114,114,114,114,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,114,114,
-114,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
+115,115,115,115,115,481,481,481,481,481,481,481,481,481,481,481,
481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
+481,481,481,481,481,481,481,481,481,481,481,481,481,481,115,115,
+115,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,482,482,482,482,482,482,482,482,482,482,482,482,482,
/* block 91 */
-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,114,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,115,
19, 19, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-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,114,114,114,114,114,
+481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
+481,481,481,481,481,481,481,481,481,481,481,115,115,115,115,115,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114,114,114,
-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
+ 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,
+479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,
/* block 92 */
-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,114,
+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,483,483,115,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 23, 23, 23, 23, 23, 23, 23, 23,
19, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-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, 19,
+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,483,483, 19,
/* block 93 */
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 19, 19, 19, 19, 19, 19,
@@ -2286,53 +2313,23 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-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,483,483,483,
-483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,114,
-
-/* block 94 */
-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,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,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,483, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-
-/* block 95 */
-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,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,484,484,484,484,484,484,484,484,484,484,484,484,484,115,
+
+/* block 94 */
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,
-
-/* block 96 */
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,484,484,484,484,484,114,114,114,114,114,114,114,114,114,114,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+484,484,484,484,484,484,484,484, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-
-/* block 97 */
-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,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,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-/* block 98 */
+/* block 95 */
+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,485,
-485,485,485,485,485,486,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,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,
@@ -2340,877 +2337,957 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
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,485,
-/* block 99 */
+/* block 96 */
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,485,
485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,
+485,485,485,485,485,485,115,115,115,115,115,115,115,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+
+/* block 97 */
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,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,485,485,
485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,
+485,485,485,485,485,485,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+
+/* block 98 */
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,487,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+
+/* block 99 */
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
/* block 100 */
-485,485,485,485,485,485,485,485,485,485,485,485,485,114,114,114,
-487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
-487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
-487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
-487,487,487,487,487,487,487,114,114,114,114,114,114,114,114,114,
+486,486,486,486,486,486,486,486,486,486,486,486,486,115,115,115,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
-488,488,488,488,488,488,488,488,489,489,489,489,489,489,490,490,
+488,488,488,488,488,488,488,115,115,115,115,115,115,115,115,115,
+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,489,489,
+489,489,489,489,489,489,489,489,490,490,490,490,490,490,491,491,
/* block 101 */
-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,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,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,491,491,491,491,
-491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,
+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,
+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,
+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,
+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,
+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,
+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,
+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,
+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,
/* block 102 */
-491,491,491,491,491,491,491,491,491,491,491,491,492,493,493,493,
-491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,
-494,494,494,494,494,494,494,494,494,494,491,491,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,495,177,
-178,178,178,496,177,177,177,177,177,177,177,177,177,177,496,408,
+492,492,492,492,492,492,492,492,492,492,492,492,493,494,494,494,
+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,
+495,495,495,495,495,495,495,495,495,495,492,492,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,496,178,
+179,179,179,497,178,178,178,178,178,178,178,178,178,178,497,409,
/* block 103 */
-174,175,174,175,174,175,174,175,174,175,174,175,174,175,174,175,
-174,175,174,175,174,175,174,175,174,175,174,175,408,408,114,177,
-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,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,497,497,497,497,
-497,497,497,497,497,497,498,498,498,498,498,498,498,498,498,498,
-499,499,500,500,500,500,500,500,114,114,114,114,114,114,114,114,
+175,176,175,176,175,176,175,176,175,176,175,176,175,176,175,176,
+175,176,175,176,175,176,175,176,175,176,175,176,409,409,178,178,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,499,499,499,499,499,499,499,499,499,499,
+500,500,501,501,501,501,501,501,115,115,115,115,115,115,115,115,
/* block 104 */
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14,107,107,107,107,107,107,107,107,107,
+ 14, 14, 14, 14, 14, 14, 14,108,108,108,108,108,108,108,108,108,
14, 14, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
33, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
-106, 33, 33, 33, 33, 33, 33, 33, 33, 30, 31, 30, 31,501, 30, 31,
+107, 33, 33, 33, 33, 33, 33, 33, 33, 30, 31, 30, 31,502, 30, 31,
/* block 105 */
- 30, 31, 30, 31, 30, 31, 30, 31,107, 14, 14, 30, 31,502, 33,114,
+ 30, 31, 30, 31, 30, 31, 30, 31,108, 14, 14, 30, 31,503, 33, 20,
30, 31, 30, 31, 33, 33, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,
- 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,503,504,505,506,114,114,
-507,508,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114, 20,106,106, 33, 20, 20, 20, 20, 20,
+ 30, 31, 30, 31, 30, 31, 30, 31, 30, 31,504,505,506,507,115,115,
+508,509,510,511, 30, 31, 30, 31,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115, 20,107,107, 33, 20, 20, 20, 20, 20,
/* block 106 */
-509,509,510,509,509,509,510,509,509,509,509,510,509,509,509,509,
-509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,
-509,509,509,511,511,510,510,511,512,512,512,512,114,114,114,114,
- 23, 23, 23, 23, 23, 23, 19, 19, 5, 19,114,114,114,114,114,114,
-513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
-513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
-513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
-513,513,513,513,514,514,514,514,114,114,114,114,114,114,114,114,
-
-/* block 107 */
-515,515,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
+512,512,513,512,512,512,513,512,512,512,512,513,512,512,512,512,
+512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,
+512,512,512,514,514,513,513,514,515,515,515,515,115,115,115,115,
+ 23, 23, 23, 23, 23, 23, 19, 19, 5, 19,115,115,115,115,115,115,
516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,515,515,515,515,515,515,515,515,515,515,515,515,
-515,515,515,515,517,114,114,114,114,114,114,114,114,114,518,518,
-519,519,519,519,519,519,519,519,519,519,114,114,114,114,114,114,
-221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
-221,221,223,223,223,223,223,223,225,225,225,223,114,114,114,114,
+516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
+516,516,516,516,517,517,517,517,115,115,115,115,115,115,115,115,
+
+/* block 107 */
+518,518,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+519,519,519,519,518,518,518,518,518,518,518,518,518,518,518,518,
+518,518,518,518,520,115,115,115,115,115,115,115,115,115,521,521,
+522,522,522,522,522,522,522,522,522,522,115,115,115,115,115,115,
+222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,
+222,222,224,224,224,224,224,224,226,226,226,224,226,224,115,115,
/* block 108 */
-520,520,520,520,520,520,520,520,520,520,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,522,522,522,522,522,522,522,522, 4,523,
+523,523,523,523,523,523,523,523,523,523,524,524,524,524,524,524,
524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
-524,524,524,524,524,524,524,525,525,525,525,525,525,525,525,525,
-525,525,526,526,114,114,114,114,114,114,114,114,114,114,114,527,
-314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
-314,314,314,314,314,314,314,314,314,314,314,314,314,114,114,114,
+524,524,524,524,524,524,525,525,525,525,525,525,525,525, 4,526,
+527,527,527,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,528,529,529,115,115,115,115,115,115,115,115,115,115,115,530,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,115,115,115,
/* block 109 */
-528,528,528,529,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,
-530,530,530,528,529,529,528,528,528,528,529,529,528,529,529,529,
-529,531,531,531,531,531,531,531,531,531,531,531,531,531,114,107,
-532,532,532,532,532,532,532,532,532,532,114,114,114,114,531,531,
-304,304,304,304,304,306,533,304,304,304,304,304,304,304,304,304,
-308,308,308,308,308,308,308,308,308,308,304,304,304,304,304,114,
+531,531,531,532,533,533,533,533,533,533,533,533,533,533,533,533,
+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,
+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,
+533,533,533,531,532,532,531,531,531,531,532,532,531,532,532,532,
+532,534,534,534,534,534,534,534,534,534,534,534,534,534,115,108,
+535,535,535,535,535,535,535,535,535,535,115,115,115,115,534,534,
+305,305,305,305,305,307,536,305,305,305,305,305,305,305,305,305,
+309,309,309,309,309,309,309,309,309,309,305,305,305,305,305,115,
/* block 110 */
-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,535,535,535,535,535,535,536,
-536,535,535,536,536,535,535,114,114,114,114,114,114,114,114,114,
-534,534,534,535,534,534,534,534,534,534,534,534,535,536,114,114,
-537,537,537,537,537,537,537,537,537,537,114,114,538,538,538,538,
-304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,
-533,304,304,304,304,304,304,310,310,310,304,305,306,305,304,304,
+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,538,538,538,538,538,538,539,
+539,538,538,539,539,538,538,115,115,115,115,115,115,115,115,115,
+537,537,537,538,537,537,537,537,537,537,537,537,538,539,115,115,
+540,540,540,540,540,540,540,540,540,540,115,115,541,541,541,541,
+305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,
+536,305,305,305,305,305,305,311,311,311,305,306,307,306,305,305,
/* block 111 */
-539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,
-539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,
-539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,
-540,539,540,540,540,539,539,540,540,539,539,539,539,539,540,540,
-539,540,539,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,539,539,541,542,542,
-543,543,543,543,543,543,543,543,543,543,543,544,545,545,544,544,
-546,546,543,547,547,544,545,114,114,114,114,114,114,114,114,114,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,
+543,542,543,543,543,542,542,543,543,542,542,542,542,542,543,543,
+542,543,542,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,542,542,544,545,545,
+546,546,546,546,546,546,546,546,546,546,546,547,548,548,547,547,
+549,549,546,550,550,547,548,115,115,115,115,115,115,115,115,115,
/* block 112 */
-114,317,317,317,317,317,317,114,114,317,317,317,317,317,317,114,
-114,317,317,317,317,317,317,114,114,114,114,114,114,114,114,114,
-317,317,317,317,317,317,317,114,317,317,317,317,317,317,317,114,
+115,318,318,318,318,318,318,115,115,318,318,318,318,318,318,115,
+115,318,318,318,318,318,318,115,115,115,115,115,115,115,115,115,
+318,318,318,318,318,318,318,115,318,318,318,318,318,318,318,115,
33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 14,106,106,106,106,
-114,114,114,114, 33,122,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+ 33, 33, 33,551, 33, 33, 33, 33, 33, 33, 33, 14,107,107,107,107,
+ 33, 33, 33, 33, 33,123,115,115,115,115,115,115,115,115,115,115,
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
/* block 113 */
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,
-543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,
-543,543,543,544,544,545,544,544,545,544,544,546,544,545,114,114,
-548,548,548,548,548,548,548,548,548,548,114,114,114,114,114,114,
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
+546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,
+546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,
+546,546,546,547,547,548,547,547,548,547,547,549,547,548,115,115,
+553,553,553,553,553,553,553,553,553,553,115,115,115,115,115,115,
/* block 114 */
-549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
+554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
/* block 115 */
-550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550,
+555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555,
/* block 116 */
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
/* block 117 */
-550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550,
+555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555,
/* block 118 */
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
/* block 119 */
-550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550,
+555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555,
/* block 120 */
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-549,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,549,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,549,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,554,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,554,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
/* block 121 */
-550,550,550,550,550,550,550,550,549,550,550,550,550,550,550,550,
-550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
-550,550,550,550,114,114,114,114,114,114,114,114,114,114,114,114,
-315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
-315,315,315,315,315,315,315,114,114,114,114,316,316,316,316,316,
+555,555,555,555,555,555,555,555,554,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,115,115,115,115,115,115,115,115,115,115,115,115,
316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,
-316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,
-316,316,316,316,316,316,316,316,316,316,316,316,114,114,114,114,
+316,316,316,316,316,316,316,115,115,115,115,317,317,317,317,317,
+317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
+317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,
+317,317,317,317,317,317,317,317,317,317,317,317,115,115,115,115,
/* block 122 */
-551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
-551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
-551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
-551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
-551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
-551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
-551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
-551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
+556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
+556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
+556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
+556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
+556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
+556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
+556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
+556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
/* block 123 */
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
/* block 124 */
-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,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,484,484,484,484,484,484,484,484,484,484,484,484,114,114,
-484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
+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,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,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,485,485,485,
+485,485,485,485,485,485,485,485,485,485,485,485,485,485,115,115,
+485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,
/* block 125 */
-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,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,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+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,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,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,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 126 */
- 33, 33, 33, 33, 33, 33, 33,114,114,114,114,114,114,114,114,114,
-114,114,114,185,185,185,185,185,114,114,114,114,114,192,189,192,
-192,192,192,192,192,192,192,192,192,553,192,192,192,192,192,192,
-192,192,192,192,192,192,192,114,192,192,192,192,192,114,192,114,
-192,192,114,192,192,114,192,192,192,192,192,192,192,192,192,192,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
+ 33, 33, 33, 33, 33, 33, 33,115,115,115,115,115,115,115,115,115,
+115,115,115,186,186,186,186,186,115,115,115,115,115,193,190,193,
+193,193,193,193,193,193,193,193,193,558,193,193,193,193,193,193,
+193,193,193,193,193,193,193,115,193,193,193,193,193,115,193,115,
+193,193,115,193,193,115,193,193,193,193,193,193,193,193,193,193,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
/* block 127 */
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
-554,554,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
+559,559,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
/* block 128 */
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
/* block 129 */
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199, 7, 6,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200, 7, 6,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
/* block 130 */
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-114,114,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-199,199,199,199,199,199,199,199,199,199,199,199,196,197,114,114,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+115,115,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+200,200,200,200,200,200,200,200,200,200,200,200,197,198,115,115,
/* block 131 */
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
- 4, 4, 4, 4, 4, 4, 4, 6, 7, 4,114,114,114,114,114,114,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,114,114,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+ 4, 4, 4, 4, 4, 4, 4, 6, 7, 4,115,115,115,115,115,115,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,178,178,
4, 9, 9, 15, 15, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6,
7, 6, 7, 6, 7, 4, 4, 6, 7, 4, 4, 4, 4, 15, 15, 15,
- 4, 4, 4,114, 4, 4, 4, 4, 9, 6, 7, 6, 7, 6, 7, 4,
- 4, 4, 8, 9, 8, 8, 8,114, 4, 5, 4, 4,114,114,114,114,
-199,199,199,199,199,114,199,199,199,199,199,199,199,199,199,199,
+ 4, 4, 4,115, 4, 4, 4, 4, 9, 6, 7, 6, 7, 6, 7, 4,
+ 4, 4, 8, 9, 8, 8, 8,115, 4, 5, 4, 4,115,115,115,115,
+200,200,200,200,200,115,200,200,200,200,200,200,200,200,200,200,
/* block 132 */
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,114,114, 22,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,115,115, 22,
/* block 133 */
-114, 4, 4, 4, 5, 4, 4, 4, 6, 7, 4, 8, 4, 9, 4, 4,
+115, 4, 4, 4, 5, 4, 4, 4, 6, 7, 4, 8, 4, 9, 4, 4,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 4, 8, 8, 8, 4,
4, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 6, 4, 7, 14, 15,
14, 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, 6, 8, 7, 8, 6,
- 7, 4, 6, 7, 4, 4,478,478,478,478,478,478,478,478,478,478,
-107,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
+ 7, 4, 6, 7, 4, 4,479,479,479,479,479,479,479,479,479,479,
+108,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,
/* block 134 */
-478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
-478,478,478,478,478,478,478,478,478,478,478,478,478,478,555,555,
-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
-481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,114,
-114,114,481,481,481,481,481,481,114,114,481,481,481,481,481,481,
-114,114,481,481,481,481,481,481,114,114,481,481,481,114,114,114,
- 5, 5, 8, 14, 19, 5, 5,114, 19, 8, 8, 8, 8, 19, 19,114,
-436,436,436,436,436,436,436,436,436, 22, 22, 22, 19, 19,114,114,
+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,560,560,
+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,115,
+115,115,482,482,482,482,482,482,115,115,482,482,482,482,482,482,
+115,115,482,482,482,482,482,482,115,115,482,482,482,115,115,115,
+ 5, 5, 8, 14, 19, 5, 5,115, 19, 8, 8, 8, 8, 19, 19,115,
+437,437,437,437,437,437,437,437,437, 22, 22, 22, 19, 19,115,115,
/* block 135 */
-556,556,556,556,556,556,556,556,556,556,556,556,114,556,556,556,
-556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
-556,556,556,556,556,556,556,114,556,556,556,556,556,556,556,556,
-556,556,556,556,556,556,556,556,556,556,556,114,556,556,114,556,
-556,556,556,556,556,556,556,556,556,556,556,556,556,556,114,114,
-556,556,556,556,556,556,556,556,556,556,556,556,556,556,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+561,561,561,561,561,561,561,561,561,561,561,561,115,561,561,561,
+561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
+561,561,561,561,561,561,561,115,561,561,561,561,561,561,561,561,
+561,561,561,561,561,561,561,561,561,561,561,115,561,561,115,561,
+561,561,561,561,561,561,561,561,561,561,561,561,561,561,115,115,
+561,561,561,561,561,561,561,561,561,561,561,561,561,561,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 136 */
-556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
-556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
-556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
-556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
-556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
-556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
-556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
-556,556,556,556,556,556,556,556,556,556,556,114,114,114,114,114,
+561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
+561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
+561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
+561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
+561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
+561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
+561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
+561,561,561,561,561,561,561,561,561,561,561,115,115,115,115,115,
/* block 137 */
- 4, 4, 4,114,114,114,114, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 4, 4, 4,115,115,115,115, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23,114,114,114, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
-557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
-557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
-557,557,557,557,557,558,558,558,558,559,559,559,559,559,559,559,
+ 23, 23, 23, 23,115,115,115, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
+562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
+562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
+562,562,562,562,562,563,563,563,563,564,564,564,564,564,564,564,
/* block 138 */
-559,559,559,559,559,559,559,559,559,559,558,558,559,114,114,114,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,
-559,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+564,564,564,564,564,564,564,564,564,564,563,563,564,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
+564,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,114,114,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,110,115,115,
/* block 139 */
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 140 */
-560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,
-560,560,560,560,560,560,560,560,560,560,560,560,560,114,114,114,
-561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
-561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
-561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
-561,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-109, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,114,114,114,114,
-
-/* block 141 */
-562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
-562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
-563,563,563,563,114,114,114,114,114,114,114,114,114,114,114,114,
-564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
-564,565,564,564,564,564,564,564,564,564,565,114,114,114,114,114,
+565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,
+565,565,565,565,565,565,565,565,565,565,565,565,565,115,115,115,
+566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,
566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,
566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,
-566,566,566,566,566,566,567,567,567,567,567,114,114,114,114,114,
+566,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+110, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,115,115,115,115,
-/* block 142 */
-568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,
-568,568,568,568,568,568,568,568,568,568,568,568,568,568,114,569,
-570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,
-570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,
-570,570,570,570,114,114,114,114,570,570,570,570,570,570,570,570,
-571,572,572,572,572,572,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+/* block 141 */
+567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,
+567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,
+568,568,568,568,115,115,115,115,115,115,115,115,115,115,115,115,
+569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
+569,570,569,569,569,569,569,569,569,569,570,115,115,115,115,115,
+571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,
+571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,
+571,571,571,571,571,571,572,572,572,572,572,115,115,115,115,115,
-/* block 143 */
-573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+/* block 142 */
573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
-573,573,573,573,573,573,573,573,574,574,574,574,574,574,574,574,
-574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,
-574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,
-575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,115,574,
575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,
575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,
+575,575,575,575,115,115,115,115,575,575,575,575,575,575,575,575,
+576,577,577,577,577,577,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 144 */
-576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,
-576,576,576,576,576,576,576,576,576,576,576,576,576,576,114,114,
-577,577,577,577,577,577,577,577,577,577,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-
-/* block 145 */
+/* block 143 */
578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,114,114,114,114,114,114,114,114,
+578,578,578,578,578,578,578,578,579,579,579,579,579,579,579,579,
579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,
579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,
-579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,
-579,579,579,579,114,114,114,114,114,114,114,114,114,114,114,580,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
+580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
-/* block 146 */
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
+/* block 144 */
581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
+581,581,581,581,581,581,581,581,581,581,581,581,581,581,115,115,
+582,582,582,582,582,582,582,582,582,582,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+
+/* block 145 */
+583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
+583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
+583,583,583,583,583,583,583,583,115,115,115,115,115,115,115,115,
+584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
+584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
+584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
+584,584,584,584,115,115,115,115,115,115,115,115,115,115,115,585,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+
+/* block 146 */
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
/* block 147 */
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
-581,581,581,581,581,581,581,114,114,114,114,114,114,114,114,114,
-581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
-581,581,581,581,581,581,114,114,114,114,114,114,114,114,114,114,
-581,581,581,581,581,581,581,581,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,115,115,115,115,115,115,115,115,115,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,115,115,115,115,115,115,115,115,115,115,
+586,586,586,586,586,586,586,586,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 148 */
-582,582,582,582,582,582,114,114,582,114,582,582,582,582,582,582,
-582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,
-582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,
-582,582,582,582,582,582,114,582,582,114,114,114,582,114,114,582,
-583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
-583,583,583,583,583,583,114,584,585,585,585,585,585,585,585,585,
-586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
-586,586,586,586,586,586,586,587,587,588,588,588,588,588,588,588,
+587,587,587,587,587,587,115,115,587,115,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,115,587,587,115,115,115,587,115,115,587,
+588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,
+588,588,588,588,588,588,115,589,590,590,590,590,590,590,590,590,
+591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
+591,591,591,591,591,591,591,592,592,593,593,593,593,593,593,593,
/* block 149 */
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,
-589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,114,
-114,114,114,114,114,114,114,590,590,590,590,590,590,590,590,590,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,
+594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,115,
+115,115,115,115,115,115,115,595,595,595,595,595,595,595,595,595,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
+596,596,596,115,596,596,115,115,115,115,115,597,597,597,597,597,
/* block 150 */
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,592,592,592,592,592,592,114,114,114,593,
-594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,
-594,594,594,594,594,594,594,594,594,594,114,114,114,114,114,595,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
+598,598,598,598,598,598,599,599,599,599,599,599,115,115,115,600,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,115,115,115,115,115,602,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 151 */
-596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
-596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
-597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
-597,597,597,597,597,597,597,597,114,114,114,114,114,114,597,597,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,
+603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,
+604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,
+604,604,604,604,604,604,604,604,115,115,115,115,605,605,604,604,
+605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,
+115,115,605,605,605,605,605,605,605,605,605,605,605,605,605,605,
+605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,
+605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,
/* block 152 */
-598,599,599,599,114,599,599,114,114,114,114,114,599,599,599,599,
-598,598,598,598,114,598,598,598,114,598,598,598,598,598,598,598,
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
-598,598,598,598,114,114,114,114,599,599,599,114,114,114,114,599,
-600,600,600,600,600,600,600,600,114,114,114,114,114,114,114,114,
-601,601,601,601,601,601,601,601,601,114,114,114,114,114,114,114,
-602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,
-602,602,602,602,602,602,602,602,602,602,602,602,602,603,603,604,
+606,607,607,607,115,607,607,115,115,115,115,115,607,607,607,607,
+606,606,606,606,115,606,606,606,115,606,606,606,606,606,606,606,
+606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
+606,606,606,606,115,115,115,115,607,607,607,115,115,115,115,607,
+608,608,608,608,608,608,608,608,115,115,115,115,115,115,115,115,
+609,609,609,609,609,609,609,609,609,115,115,115,115,115,115,115,
+610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,
+610,610,610,610,610,610,610,610,610,610,610,610,610,611,611,612,
/* block 153 */
-605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,
-605,605,605,605,605,605,605,605,605,605,605,605,605,606,606,606,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-607,607,607,607,607,607,607,607,608,607,607,607,607,607,607,607,
-607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,
-607,607,607,607,607,609,609,114,114,114,114,610,610,610,610,610,
-611,611,611,611,611,611,611,114,114,114,114,114,114,114,114,114,
+613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,
+613,613,613,613,613,613,613,613,613,613,613,613,613,614,614,614,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+615,615,615,615,615,615,615,615,616,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,617,617,115,115,115,115,618,618,618,618,618,
+619,619,619,619,619,619,619,115,115,115,115,115,115,115,115,115,
/* block 154 */
-612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,
-612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,
-612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,
-612,612,612,612,612,612,114,114,114,613,613,613,613,613,613,613,
-614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,
-614,614,614,614,614,614,114,114,615,615,615,615,615,615,615,615,
-616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,
-616,616,616,114,114,114,114,114,617,617,617,617,617,617,617,617,
+620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
+620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
+620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
+620,620,620,620,620,620,115,115,115,621,621,621,621,621,621,621,
+622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,
+622,622,622,622,622,622,115,115,623,623,623,623,623,623,623,623,
+624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,
+624,624,624,115,115,115,115,115,625,625,625,625,625,625,625,625,
/* block 155 */
-618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
-618,618,114,114,114,114,114,114,114,619,619,619,619,114,114,114,
-114,114,114,114,114,114,114,114,114,620,620,620,620,620,620,620,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,
+626,626,115,115,115,115,115,115,115,627,627,627,627,115,115,115,
+115,115,115,115,115,115,115,115,115,628,628,628,628,628,628,628,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 156 */
-621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,
-621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,
-621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,
-621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,
-621,621,621,621,621,621,621,621,621,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,
+629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,
+629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,
+629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,
+629,629,629,629,629,629,629,629,629,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 157 */
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,
-622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,114,
+630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,
+630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,
+630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,
+630,630,630,115,115,115,115,115,115,115,115,115,115,115,115,115,
+631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,
+631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,
+631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,
+631,631,631,115,115,115,115,115,115,115,632,632,632,632,632,632,
/* block 158 */
-623,624,623,625,625,625,625,625,625,625,625,625,625,625,625,625,
-625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,
-625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,
-625,625,625,625,625,625,625,625,624,624,624,624,624,624,624,624,
-624,624,624,624,624,624,624,626,626,626,626,626,626,626,114,114,
-114,114,627,627,627,627,627,627,627,627,627,627,627,627,627,627,
-627,627,627,627,627,627,628,628,628,628,628,628,628,628,628,628,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,624,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,
+633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,115,
/* block 159 */
-629,629,630,631,631,631,631,631,631,631,631,631,631,631,631,631,
-631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,
-631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,
-630,630,630,629,629,629,629,630,630,629,629,632,632,633,632,632,
-632,632,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,
-634,634,634,634,634,634,634,634,634,114,114,114,114,114,114,114,
-635,635,635,635,635,635,635,635,635,635,114,114,114,114,114,114,
+634,635,634,636,636,636,636,636,636,636,636,636,636,636,636,636,
+636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,
+636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,
+636,636,636,636,636,636,636,636,635,635,635,635,635,635,635,635,
+635,635,635,635,635,635,635,637,637,637,637,637,637,637,115,115,
+115,115,638,638,638,638,638,638,638,638,638,638,638,638,638,638,
+638,638,638,638,638,638,639,639,639,639,639,639,639,639,639,639,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,635,
/* block 160 */
-636,636,636,637,637,637,637,637,637,637,637,637,637,637,637,637,
-637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,
-637,637,637,637,637,637,637,636,636,636,636,636,638,636,636,636,
-636,636,636,636,636,114,639,639,639,639,639,639,639,639,639,639,
-640,640,640,640,114,114,114,114,114,114,114,114,114,114,114,114,
-641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,
-641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,
-641,641,641,642,643,643,641,114,114,114,114,114,114,114,114,114,
+640,640,641,642,642,642,642,642,642,642,642,642,642,642,642,642,
+642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,
+642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,
+641,641,641,640,640,640,640,641,641,640,640,643,643,644,643,643,
+643,643,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,
+645,645,645,645,645,645,645,645,645,115,115,115,115,115,115,115,
+646,646,646,646,646,646,646,646,646,646,115,115,115,115,115,115,
/* block 161 */
-644,644,645,646,646,646,646,646,646,646,646,646,646,646,646,646,
-646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,
-646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,
-646,646,646,645,645,645,644,644,644,644,644,644,644,644,644,645,
-645,646,646,646,646,647,647,647,647,114,114,114,114,647,114,114,
-648,648,648,648,648,648,648,648,648,648,646,114,114,114,114,114,
-114,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,
-649,649,649,649,649,114,114,114,114,114,114,114,114,114,114,114,
+647,647,647,648,648,648,648,648,648,648,648,648,648,648,648,648,
+648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,
+648,648,648,648,648,648,648,647,647,647,647,647,649,647,647,647,
+647,647,647,647,647,115,650,650,650,650,650,650,650,650,650,650,
+651,651,651,651,115,115,115,115,115,115,115,115,115,115,115,115,
+652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,
+652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,
+652,652,652,653,654,654,652,115,115,115,115,115,115,115,115,115,
/* block 162 */
-650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,
-650,650,114,650,650,650,650,650,650,650,650,650,650,650,650,650,
-650,650,650,650,650,650,650,650,650,650,650,650,651,651,651,652,
-652,652,651,651,652,651,652,652,653,653,653,653,653,653,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+655,655,656,657,657,657,657,657,657,657,657,657,657,657,657,657,
+657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
+657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
+657,657,657,656,656,656,655,655,655,655,655,655,655,655,655,656,
+656,657,657,657,657,658,658,658,658,658,655,655,655,658,115,115,
+659,659,659,659,659,659,659,659,659,659,657,658,657,658,658,658,
+115,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,
+660,660,660,660,660,115,115,115,115,115,115,115,115,115,115,115,
/* block 163 */
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,
-654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,
-654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,655,
-656,656,656,655,655,655,655,655,655,655,655,114,114,114,114,114,
-657,657,657,657,657,657,657,657,657,657,114,114,114,114,114,114,
+661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,
+661,661,115,661,661,661,661,661,661,661,661,661,661,661,661,661,
+661,661,661,661,661,661,661,661,661,661,661,661,662,662,662,663,
+663,663,662,662,663,662,663,663,664,664,664,664,664,664,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 164 */
-114,658,659,659,114,660,660,660,660,660,660,660,660,114,114,660,
-660,114,114,660,660,660,660,660,660,660,660,660,660,660,660,660,
-660,660,660,660,660,660,660,660,660,114,660,660,660,660,660,660,
-660,114,660,660,114,660,660,660,660,660,114,114,658,660,661,659,
-658,659,659,659,659,114,114,659,659,114,114,659,659,659,114,114,
-114,114,114,114,114,114,114,661,114,114,114,114,114,660,660,660,
-660,660,659,659,114,114,658,658,658,658,658,658,658,114,114,114,
-658,658,658,658,658,114,114,114,114,114,114,114,114,114,114,114,
+665,665,665,665,665,665,665,115,665,115,665,665,665,665,115,665,
+665,665,665,665,665,665,665,665,665,665,665,665,665,665,115,665,
+665,665,665,665,665,665,665,665,665,666,115,115,115,115,115,115,
+667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
+667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
+667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,668,
+669,669,669,668,668,668,668,668,668,668,668,115,115,115,115,115,
+670,670,670,670,670,670,670,670,670,670,115,115,115,115,115,115,
/* block 165 */
-662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,
-662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,
-662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,
-663,664,664,665,665,665,665,665,665,664,665,664,664,663,664,665,
-665,664,665,665,662,662,666,662,114,114,114,114,114,114,114,114,
-667,667,667,667,667,667,667,667,667,667,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+671,671,672,672,115,673,673,673,673,673,673,673,673,115,115,673,
+673,115,115,673,673,673,673,673,673,673,673,673,673,673,673,673,
+673,673,673,673,673,673,673,673,673,115,673,673,673,673,673,673,
+673,115,673,673,115,673,673,673,673,673,115,115,671,673,674,672,
+671,672,672,672,672,115,115,672,672,115,115,672,672,672,115,115,
+673,115,115,115,115,115,115,674,115,115,115,115,115,673,673,673,
+673,673,672,672,115,115,671,671,671,671,671,671,671,115,115,115,
+671,671,671,671,671,115,115,115,115,115,115,115,115,115,115,115,
/* block 166 */
-668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,
-668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,
-668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,669,
-670,670,671,671,671,671,114,114,670,670,670,670,671,671,670,671,
-671,672,672,672,672,672,672,672,672,672,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,
+675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,
+675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,
+676,677,677,678,678,678,678,678,678,677,678,677,677,676,677,678,
+678,677,678,678,675,675,679,675,115,115,115,115,115,115,115,115,
+680,680,680,680,680,680,680,680,680,680,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 167 */
-673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
-673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
-673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
-674,674,674,675,675,675,675,675,675,675,675,674,674,675,674,675,
-675,676,676,676,673,114,114,114,114,114,114,114,114,114,114,114,
-677,677,677,677,677,677,677,677,677,677,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,
+681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,
+681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,682,
+683,683,684,684,684,684,115,115,683,683,683,683,684,684,683,684,
+684,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,
+685,685,685,685,685,685,685,685,681,681,681,681,684,684,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 168 */
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,679,680,679,680,680,
-679,679,679,679,679,679,680,679,114,114,114,114,114,114,114,114,
-681,681,681,681,681,681,681,681,681,681,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,
+686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,
+686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,
+687,687,687,688,688,688,688,688,688,688,688,687,687,688,687,688,
+688,689,689,689,686,115,115,115,115,115,115,115,115,115,115,115,
+690,690,690,690,690,690,690,690,690,690,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 169 */
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,
-682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,
-683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,
-683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,
-684,684,684,684,684,684,684,684,684,684,685,685,685,685,685,685,
-685,685,685,114,114,114,114,114,114,114,114,114,114,114,114,686,
+691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
+691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
+691,691,691,691,691,691,691,691,691,691,691,692,693,692,693,693,
+692,692,692,692,692,692,693,692,115,115,115,115,115,115,115,115,
+694,694,694,694,694,694,694,694,694,694,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 170 */
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,
-687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,
-687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,
-687,687,687,687,687,687,687,687,687,114,114,114,114,114,114,114,
+695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,
+695,695,695,695,695,695,695,695,695,695,115,115,115,696,696,696,
+697,697,696,696,696,696,697,696,696,696,696,696,115,115,115,115,
+698,698,698,698,698,698,698,698,698,698,699,699,700,700,700,701,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 171 */
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,
+702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,
+703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,
+703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,
+704,704,704,704,704,704,704,704,704,704,705,705,705,705,705,705,
+705,705,705,115,115,115,115,115,115,115,115,115,115,115,115,706,
/* block 172 */
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
-688,688,688,688,688,688,688,688,688,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,115,115,115,115,115,115,115,
/* block 173 */
-689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
-689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
-689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
-689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
-689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
-689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
-689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,114,
-690,690,690,690,690,114,114,114,114,114,114,114,114,114,114,114,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
/* block 174 */
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 175 */
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
-691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
+709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
+709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
+709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
+709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
+709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
+709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,115,
+710,710,710,710,710,115,115,115,115,115,115,115,115,115,115,115,
/* block 176 */
-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,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,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,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,497,497,497,497,497,497,497,497,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 177 */
-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,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,114,114,114,114,114,114,114,
-692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,
-692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,114,
-693,693,693,693,693,693,693,693,693,693,114,114,114,114,694,694,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
/* block 178 */
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,
-695,695,695,695,695,695,695,695,695,695,695,695,695,695,114,114,
-696,696,696,696,696,697,114,114,114,114,114,114,114,114,114,114,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 179 */
-698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,
-698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,
-698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,
-699,699,699,699,699,699,699,700,700,700,700,700,701,701,701,701,
-702,702,702,702,700,701,114,114,114,114,114,114,114,114,114,114,
-703,703,703,703,703,703,703,703,703,703,114,704,704,704,704,704,
-704,704,114,698,698,698,698,698,698,698,698,698,698,698,698,698,
-698,698,698,698,698,698,698,698,114,114,114,114,114,698,698,698,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
/* block 180 */
-698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,712,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 181 */
-705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,
-705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,
-705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,
-705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,
-705,705,705,705,705,114,114,114,114,114,114,114,114,114,114,114,
-705,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,
-706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,
-706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,114,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
/* block 182 */
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,707,
-707,707,707,708,708,708,708,708,708,708,708,708,708,708,708,708,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,498,498,498,115,115,115,115,115,115,115,
+713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,
+713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,115,
+714,714,714,714,714,714,714,714,714,714,115,115,115,115,715,715,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 183 */
-478,476,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,
+716,716,716,716,716,716,716,716,716,716,716,716,716,716,115,115,
+717,717,717,717,717,718,115,115,115,115,115,115,115,115,115,115,
/* block 184 */
-709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
-709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
-709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
-709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
-709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
-709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
-709,709,709,709,709,709,709,709,709,709,709,114,114,114,114,114,
-709,709,709,709,709,709,709,709,709,709,709,709,709,114,114,114,
+719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,
+719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,
+719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,
+720,720,720,720,720,720,720,721,721,721,721,721,722,722,722,722,
+723,723,723,723,721,722,115,115,115,115,115,115,115,115,115,115,
+724,724,724,724,724,724,724,724,724,724,115,725,725,725,725,725,
+725,725,115,719,719,719,719,719,719,719,719,719,719,719,719,719,
+719,719,719,719,719,719,719,719,115,115,115,115,115,719,719,719,
/* block 185 */
-709,709,709,709,709,709,709,709,709,114,114,114,114,114,114,114,
-709,709,709,709,709,709,709,709,709,709,114,114,710,711,711,712,
- 22, 22, 22, 22,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
/* block 186 */
+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,
+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,
+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,
+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,
+726,726,726,726,726,115,115,115,115,115,115,115,115,115,115,115,
+726,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,
+727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,
+727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,115,
+
+/* block 187 */
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,728,
+728,728,728,729,729,729,729,729,729,729,729,729,729,729,729,729,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+
+/* block 188 */
+479,477,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+
+/* block 189 */
+730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,
+730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,
+730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,
+730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,
+730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,
+730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,
+730,730,730,730,730,730,730,730,730,730,730,115,115,115,115,115,
+730,730,730,730,730,730,730,730,730,730,730,730,730,115,115,115,
+
+/* block 190 */
+730,730,730,730,730,730,730,730,730,115,115,115,115,115,115,115,
+730,730,730,730,730,730,730,730,730,730,115,115,731,732,732,733,
+ 22, 22, 22, 22,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+
+/* block 191 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
@@ -3218,239 +3295,259 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114,
+ 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,
-/* block 187 */
+/* block 192 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19,114,114, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19,115,115, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19,713,405,109,109,109, 19, 19, 19,405,713,713,
-713,713,713, 22, 22, 22, 22, 22, 22, 22, 22,109,109,109,109,109,
+ 19, 19, 19, 19, 19,734,406,110,110,110, 19, 19, 19,406,734,734,
+734,734,734, 22, 22, 22, 22, 22, 22, 22, 22,110,110,110,110,110,
-/* block 188 */
-109,109,109, 19, 19,109,109,109,109,109,109,109, 19, 19, 19, 19,
+/* block 193 */
+110,110,110, 19, 19,110,110,110,110,110,110,110, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,110,110,110,110, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,109,109,109,109, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 189 */
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,714,714,714,559,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+/* block 194 */
+564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
+564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
+564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
+564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
+564,564,735,735,735,564,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 190 */
+/* block 195 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,
+ 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+ 23, 23,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 191 */
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,438,438,438,438,438,438,
+/* block 196 */
+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,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,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,439,439,439,115,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,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,437,437,437,437,437,437,437,437,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,438,438,
-438,438,438,438,438,114,438,438,438,438,438,438,438,438,438,438,
-438,438,438,438,438,438,438,438,437,437,437,437,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-/* block 192 */
-437,437,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,437,114,437,437,
-114,114,437,114,114,437,437,114,114,437,437,437,437,114,437,437,
-437,437,437,437,437,437,438,438,438,438,114,438,114,438,438,438,
-438,438,438,438,114,438,438,438,438,438,438,438,438,438,438,438,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,438,438,438,438,438,438,
+/* block 197 */
+438,438,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,438,115,438,438,
+115,115,438,115,115,438,438,115,115,438,438,438,438,115,438,438,
+438,438,438,438,438,438,439,439,439,439,115,439,115,439,439,439,
+439,439,439,439,115,439,439,439,439,439,439,439,439,439,439,439,
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,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
-/* block 193 */
-438,438,438,438,437,437,114,437,437,437,437,114,114,437,437,437,
-437,437,437,437,437,114,437,437,437,437,437,437,437,114,438,438,
+/* block 198 */
+439,439,439,439,438,438,115,438,438,438,438,115,115,438,438,438,
+438,438,438,438,438,115,438,438,438,438,438,438,438,115,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,438,438,115,438,438,438,438,115,
+438,438,438,438,438,115,438,115,115,115,438,438,438,438,438,438,
+438,115,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,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,437,437,114,437,437,437,437,114,
-437,437,437,437,437,114,437,114,114,114,437,437,437,437,437,437,
-437,114,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,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-/* block 194 */
-437,437,437,437,437,437,438,438,438,438,438,438,438,438,438,438,
+/* block 199 */
+438,438,438,438,438,438,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,438,438,438,438,438,438,
+438,438,438,438,438,438,438,438,438,438,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,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,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+
+/* block 200 */
+439,439,439,439,439,439,439,439,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,437,437,437,437,437,437,437,437,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,438,438,
+438,438,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,438,438,438,438,
438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,
-
-/* block 195 */
-438,438,438,438,438,438,438,438,437,437,437,437,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-437,437,438,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,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-437,437,437,437,437,437,438,438,438,438,438,438,438,438,438,438,
+438,438,438,438,438,438,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-/* block 196 */
-437,437,437,437,437,437,437,437,437,437,438,438,438,438,438,438,
+/* block 201 */
+438,438,438,438,438,438,438,438,438,438,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439,439,115,115,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,114,114,437,437,437,437,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-437, 8,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, 8,438,438,438,438,
-438,438,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,437, 8,438,438,438,438,
+438, 8,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,439,439,439, 8,439,439,439,439,
+439,439,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, 8,439,439,439,439,
-/* block 197 */
+/* block 202 */
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439, 8,439,439,439,439,439,439,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, 8,438,438,438,438,438,438,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-437,437,437,437,437, 8,438,438,438,438,438,438,438,438,438,438,
+438,438,438,438,438, 8,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439, 8,
+439,439,439,439,439,439,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, 8,
-438,438,438,438,438,438,437,437,437,437,437,437,437,437,437,437,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, 8,
-438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
-/* block 198 */
-438,438,438,438,438,438,438,438,438, 8,438,438,438,438,438,438,
-437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-437,437,437,437,437,437,437,437,437, 8,438,438,438,438,438,438,
+/* block 203 */
+439,439,439,439,439,439,439,439,439, 8,439,439,439,439,439,439,
438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,
-438,438,438, 8,438,438,438,438,438,438,437,438,114,114, 10, 10,
+438,438,438,438,438,438,438,438,438, 8,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+439,439,439, 8,439,439,439,439,439,439,438,439,115,115, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-/* block 199 */
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
+/* block 204 */
+736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,
+736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,
+736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,
+736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,
+736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,
+736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,
+736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,
+736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,
-/* block 200 */
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,114,114,716,716,716,716,716,716,716,716,716,
-717,717,717,717,717,717,717,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+/* block 205 */
+737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,
+737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,
+737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,
+737,737,737,737,737,737,737,736,736,736,736,737,737,737,737,737,
+737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,
+737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,
+737,737,737,737,737,737,737,737,737,737,737,737,737,736,736,736,
+736,736,736,736,736,737,736,736,736,736,736,736,736,736,736,736,
-/* block 201 */
-199,199,199,199,114,199,199,199,199,199,199,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,
-114,199,199,114,199,114,114,199,114,199,199,199,199,199,199,199,
-199,199,199,114,199,199,199,199,114,199,114,199,114,114,114,114,
-114,114,199,114,114,114,114,199,114,199,114,199,114,199,199,199,
-114,199,199,114,199,114,114,199,114,199,114,199,114,199,114,199,
-114,199,199,114,199,114,114,199,199,199,199,114,199,199,199,199,
-199,199,199,114,199,199,199,199,114,199,199,199,199,114,199,114,
+/* block 206 */
+736,736,736,736,737,736,736,738,738,738,738,738,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,737,737,737,737,737,
+115,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 202 */
-199,199,199,199,199,199,199,199,199,199,114,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,114,114,114,114,
-114,199,199,199,114,199,199,199,199,199,114,199,199,199,199,199,
-199,199,199,199,199,199,199,199,199,199,199,199,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-194,194,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+/* block 207 */
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
-/* block 203 */
+/* block 208 */
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,115,115,740,740,740,740,740,740,740,740,740,
+741,741,741,741,741,741,741,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+
+/* block 209 */
+200,200,200,200,115,200,200,200,200,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,
+115,200,200,115,200,115,115,200,115,200,200,200,200,200,200,200,
+200,200,200,115,200,200,200,200,115,200,115,200,115,115,115,115,
+115,115,200,115,115,115,115,200,115,200,115,200,115,200,200,200,
+115,200,200,115,200,115,115,200,115,200,115,200,115,200,115,200,
+115,200,200,115,200,115,115,200,200,200,200,115,200,200,200,200,
+200,200,200,115,200,200,200,200,115,200,200,200,200,115,200,115,
+
+/* block 210 */
+200,200,200,200,200,200,200,200,200,200,115,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,115,115,115,115,
+115,200,200,200,115,200,200,200,200,200,115,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+195,195,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+
+/* block 211 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-/* block 204 */
+/* block 212 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114,114,114,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,
-114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,
+115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114,
+ 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,
-/* block 205 */
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,114,114,114,
+/* block 213 */
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,115,115,115,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-/* block 206 */
+/* block 214 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,718,718,718,718,718,718,718,718,718,718,
-718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,742,742,742,742,742,742,742,742,742,742,
+742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,
-/* block 207 */
-719, 19, 19,114,114,114,114,114,114,114,114,114,114,114,114,114,
+/* block 215 */
+743, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,115,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,
- 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,
- 19, 19,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,
+ 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 208 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+/* block 216 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,
-
-/* block 209 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,
-114,114,114,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 14, 14, 14, 14, 14,
-/* block 210 */
+/* block 217 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
@@ -3458,121 +3555,141 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115, 19, 19, 19, 19, 19,
-/* block 211 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+/* block 218 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19,115, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114, 19, 19, 19, 19, 19,
-
-/* block 212 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+
+/* block 219 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,
+ 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 213 */
+/* block 220 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19,114,114, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 214 */
+/* block 221 */
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,
- 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114,114,114,
+ 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 215 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+/* block 222 */
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114,114,114,
-/* block 216 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+/* block 223 */
+ 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 217 */
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+/* block 224 */
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 218 */
- 19, 19, 19, 19, 19, 19, 19, 19,114,114,114,114,114,114,114,114,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+/* block 225 */
+ 19, 19, 19, 19, 19,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+ 19,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 219 */
-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,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,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+/* block 226 */
+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,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,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,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-/* block 220 */
-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,484,484,484,484,114,114,114,114,114,114,114,114,114,114,114,
-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,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
+/* block 227 */
+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,485,
+485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,
+485,485,485,485,485,115,115,115,115,115,115,115,115,115,115,115,
+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,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,485,485,
-/* block 221 */
-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,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
+/* block 228 */
+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,115,115,
+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,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,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,485,485,485,
-/* block 222 */
-436, 22,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
-436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
+/* block 229 */
+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,485,
+485,485,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+
+/* block 230 */
+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,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+
+/* block 231 */
+437, 22,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
@@ -3580,51 +3697,51 @@ const pcre_uint16 PRIV(ucd_stage2)[] = { /* 58112 bytes, block = 128 */
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-/* block 223 */
-436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
-436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
-436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
-436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
-436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
-436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
-436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
-436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
-
-/* block 224 */
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
+/* block 232 */
+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-/* block 225 */
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
+/* block 233 */
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+
+/* block 234 */
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
-/* block 226 */
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,114,114,
+/* block 235 */
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,115,115,
};
#if UCD_BLOCK_SIZE != 128
-#error Please correct UCD_BLOCK_SIZE in pcre_internal.h
+#error Please correct UCD_BLOCK_SIZE in pcre2_internal.h
#endif
-#endif /* SUPPORT_UCP */
+#endif /* SUPPORT_UNICODE */
-#endif /* PCRE_INCLUDED */
+#endif /* PCRE2_PCRE2TEST */
diff --git a/src/3rdparty/pcre/ucp.h b/src/3rdparty/pcre2/src/pcre2_ucp.h
index 2fa00296e4..0b7553e5e0 100644
--- a/src/3rdparty/pcre/ucp.h
+++ b/src/3rdparty/pcre2/src/pcre2_ucp.h
@@ -1,9 +1,46 @@
/*************************************************
-* Unicode Property Table handler *
+* Perl-Compatible Regular Expressions *
*************************************************/
-#ifndef _UCP_H
-#define _UCP_H
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+#ifndef _PCRE2_UCP_H
+#define _PCRE2_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
@@ -14,7 +51,7 @@ the same as the values that are generated by the maint/MultiStage2.py script,
where the equivalent property descriptive names are listed in vectors.
ALSO: The specific values of the first two enums are assumed for the table
-called catposstab in pcre_compile.c. */
+called catposstab in pcre2_compile.c. */
/* These are the general character categories. */
@@ -216,9 +253,16 @@ enum {
ucp_Pau_Cin_Hau,
ucp_Siddham,
ucp_Tirhuta,
- ucp_Warang_Citi
+ ucp_Warang_Citi,
+ /* New for Unicode 8.0.0: */
+ ucp_Ahom,
+ ucp_Anatolian_Hieroglyphs,
+ ucp_Hatran,
+ ucp_Multani,
+ ucp_Old_Hungarian,
+ ucp_SignWriting
};
#endif
-/* End of ucp.h */
+/* End of pcre2_ucp.h */
diff --git a/src/3rdparty/pcre/pcre_valid_utf8.c b/src/3rdparty/pcre2/src/pcre2_valid_utf.c
index 3b0f6464a3..2dfd8df34d 100644
--- a/src/3rdparty/pcre/pcre_valid_utf8.c
+++ b/src/3rdparty/pcre2/src/pcre2_valid_utf.c
@@ -6,7 +6,8 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2013 University of Cambridge
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -38,107 +39,131 @@ POSSIBILITY OF SUCH DAMAGE.
*/
-/* This module contains an internal function for validating UTF-8 character
-strings. */
-
+/* This module contains an internal function for validating UTF character
+strings. This file is also #included by the pcre2test program, which uses
+macros to change names from _pcre2_xxx to xxxx, thereby avoiding name clashes
+with the library. In this case, PCRE2_PCRE2TEST is defined. */
+#ifndef PCRE2_PCRE2TEST /* We're compiling the library */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include "pcre2_internal.h"
+#endif /* PCRE2_PCRE2TEST */
+
+
+#ifndef SUPPORT_UNICODE
+/*************************************************
+* Dummy function when Unicode is not supported *
+*************************************************/
+
+/* This function should never be called when Unicode is not supported. */
+
+int
+PRIV(valid_utf)(PCRE2_SPTR string, PCRE2_SIZE length, PCRE2_SIZE *erroroffset)
+{
+(void)string;
+(void)length;
+(void)erroroffset;
+return 0;
+}
+#else /* UTF is supported */
-#include "pcre_internal.h"
/*************************************************
-* Validate a UTF-8 string *
+* Validate a UTF 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
+check that a supposed UTF string is actually valid. The early check means
that subsequent code can assume it is dealing with a valid string. The check
can be turned off for maximum performance, but the consequences of supplying an
invalid string are then undefined.
-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
-PCRE_UTF8_ERR22 Unused (was non-character)
-
Arguments:
string points to the string
- length length of string, or -1 if the string is zero-terminated
+ length length of string
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
+Returns: == 0 if the string is a valid UTF string
+ != 0 otherwise, setting the offset of the bad character
*/
int
-PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset)
+PRIV(valid_utf)(PCRE2_SPTR string, PCRE2_SIZE length, PCRE2_SIZE *erroroffset)
{
-#ifdef SUPPORT_UTF
-register PCRE_PUCHAR p;
+register PCRE2_SPTR p;
+register uint32_t c;
-if (length < 0)
- {
- for (p = string; *p != 0; p++);
- length = (int)(p - string);
- }
+/* ----------------- Check a UTF-8 string ----------------- */
-for (p = string; length-- > 0; p++)
+#if PCRE2_CODE_UNIT_WIDTH == 8
+
+/* Originally, this function checked according to RFC 2279, allowing for values
+in the range 0 to 0x7fffffff, up to 6 bytes long, but ensuring that they were
+in the canonical format. Once somebody had pointed out RFC 3629 to me (it
+obsoletes 2279), additional restrictions were applied. The values are now
+limited to be between 0 and 0x0010ffff, no more than 4 bytes long, and the
+subrange 0xd000 to 0xdfff is excluded. However, the format of 5-byte and 6-byte
+characters is still checked. Error returns are as follows:
+
+PCRE2_ERROR_UTF8_ERR1 Missing 1 byte at the end of the string
+PCRE2_ERROR_UTF8_ERR2 Missing 2 bytes at the end of the string
+PCRE2_ERROR_UTF8_ERR3 Missing 3 bytes at the end of the string
+PCRE2_ERROR_UTF8_ERR4 Missing 4 bytes at the end of the string
+PCRE2_ERROR_UTF8_ERR5 Missing 5 bytes at the end of the string
+PCRE2_ERROR_UTF8_ERR6 2nd-byte's two top bits are not 0x80
+PCRE2_ERROR_UTF8_ERR7 3rd-byte's two top bits are not 0x80
+PCRE2_ERROR_UTF8_ERR8 4th-byte's two top bits are not 0x80
+PCRE2_ERROR_UTF8_ERR9 5th-byte's two top bits are not 0x80
+PCRE2_ERROR_UTF8_ERR10 6th-byte's two top bits are not 0x80
+PCRE2_ERROR_UTF8_ERR11 5-byte character is not permitted by RFC 3629
+PCRE2_ERROR_UTF8_ERR12 6-byte character is not permitted by RFC 3629
+PCRE2_ERROR_UTF8_ERR13 4-byte character with value > 0x10ffff is not permitted
+PCRE2_ERROR_UTF8_ERR14 3-byte character with value 0xd800-0xdfff is not permitted
+PCRE2_ERROR_UTF8_ERR15 Overlong 2-byte sequence
+PCRE2_ERROR_UTF8_ERR16 Overlong 3-byte sequence
+PCRE2_ERROR_UTF8_ERR17 Overlong 4-byte sequence
+PCRE2_ERROR_UTF8_ERR18 Overlong 5-byte sequence (won't ever occur)
+PCRE2_ERROR_UTF8_ERR19 Overlong 6-byte sequence (won't ever occur)
+PCRE2_ERROR_UTF8_ERR20 Isolated 0x80 byte (not within UTF-8 character)
+PCRE2_ERROR_UTF8_ERR21 Byte with the illegal value 0xfe or 0xff
+*/
+
+for (p = string; length > 0; p++)
{
- register pcre_uchar ab, c, d;
+ register uint32_t ab, d;
c = *p;
+ length--;
+
if (c < 128) continue; /* ASCII character */
if (c < 0xc0) /* Isolated 10xx xxxx byte */
{
*erroroffset = (int)(p - string);
- return PCRE_UTF8_ERR20;
+ return PCRE2_ERROR_UTF8_ERR20;
}
if (c >= 0xfe) /* Invalid 0xfe or 0xff bytes */
{
*erroroffset = (int)(p - string);
- return PCRE_UTF8_ERR21;
+ return PCRE2_ERROR_UTF8_ERR21;
}
- ab = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */
- if (length < ab)
+ ab = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes (1-5) */
+ if (length < ab) /* Missing bytes */
{
- *erroroffset = (int)(p - string); /* Missing bytes */
- return ab - length; /* Codes ERR1 to ERR5 */
+ *erroroffset = (int)(p - string);
+ switch(ab - length)
+ {
+ case 1: return PCRE2_ERROR_UTF8_ERR1;
+ case 2: return PCRE2_ERROR_UTF8_ERR2;
+ case 3: return PCRE2_ERROR_UTF8_ERR3;
+ case 4: return PCRE2_ERROR_UTF8_ERR4;
+ case 5: return PCRE2_ERROR_UTF8_ERR5;
+ }
}
length -= ab; /* Length remaining */
@@ -147,7 +172,7 @@ for (p = string; length-- > 0; p++)
if (((d = *(++p)) & 0xc0) != 0x80)
{
*erroroffset = (int)(p - string) - 1;
- return PCRE_UTF8_ERR6;
+ return PCRE2_ERROR_UTF8_ERR6;
}
/* For each length, check that the remaining bytes start with the 0x80 bit
@@ -162,7 +187,7 @@ for (p = string; length-- > 0; p++)
case 1: if ((c & 0x3e) == 0)
{
*erroroffset = (int)(p - string) - 1;
- return PCRE_UTF8_ERR15;
+ return PCRE2_ERROR_UTF8_ERR15;
}
break;
@@ -174,17 +199,17 @@ for (p = string; length-- > 0; p++)
if ((*(++p) & 0xc0) != 0x80) /* Third byte */
{
*erroroffset = (int)(p - string) - 2;
- return PCRE_UTF8_ERR7;
+ return PCRE2_ERROR_UTF8_ERR7;
}
if (c == 0xe0 && (d & 0x20) == 0)
{
*erroroffset = (int)(p - string) - 2;
- return PCRE_UTF8_ERR16;
+ return PCRE2_ERROR_UTF8_ERR16;
}
if (c == 0xed && d >= 0xa0)
{
*erroroffset = (int)(p - string) - 2;
- return PCRE_UTF8_ERR14;
+ return PCRE2_ERROR_UTF8_ERR14;
}
break;
@@ -196,22 +221,22 @@ for (p = string; length-- > 0; p++)
if ((*(++p) & 0xc0) != 0x80) /* Third byte */
{
*erroroffset = (int)(p - string) - 2;
- return PCRE_UTF8_ERR7;
+ return PCRE2_ERROR_UTF8_ERR7;
}
if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */
{
*erroroffset = (int)(p - string) - 3;
- return PCRE_UTF8_ERR8;
+ return PCRE2_ERROR_UTF8_ERR8;
}
if (c == 0xf0 && (d & 0x30) == 0)
{
*erroroffset = (int)(p - string) - 3;
- return PCRE_UTF8_ERR17;
+ return PCRE2_ERROR_UTF8_ERR17;
}
if (c > 0xf4 || (c == 0xf4 && d > 0x8f))
{
*erroroffset = (int)(p - string) - 3;
- return PCRE_UTF8_ERR13;
+ return PCRE2_ERROR_UTF8_ERR13;
}
break;
@@ -227,22 +252,22 @@ for (p = string; length-- > 0; p++)
if ((*(++p) & 0xc0) != 0x80) /* Third byte */
{
*erroroffset = (int)(p - string) - 2;
- return PCRE_UTF8_ERR7;
+ return PCRE2_ERROR_UTF8_ERR7;
}
if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */
{
*erroroffset = (int)(p - string) - 3;
- return PCRE_UTF8_ERR8;
+ return PCRE2_ERROR_UTF8_ERR8;
}
if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */
{
*erroroffset = (int)(p - string) - 4;
- return PCRE_UTF8_ERR9;
+ return PCRE2_ERROR_UTF8_ERR9;
}
if (c == 0xf8 && (d & 0x38) == 0)
{
*erroroffset = (int)(p - string) - 4;
- return PCRE_UTF8_ERR18;
+ return PCRE2_ERROR_UTF8_ERR18;
}
break;
@@ -253,27 +278,27 @@ for (p = string; length-- > 0; p++)
if ((*(++p) & 0xc0) != 0x80) /* Third byte */
{
*erroroffset = (int)(p - string) - 2;
- return PCRE_UTF8_ERR7;
+ return PCRE2_ERROR_UTF8_ERR7;
}
if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */
{
*erroroffset = (int)(p - string) - 3;
- return PCRE_UTF8_ERR8;
+ return PCRE2_ERROR_UTF8_ERR8;
}
if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */
{
*erroroffset = (int)(p - string) - 4;
- return PCRE_UTF8_ERR9;
+ return PCRE2_ERROR_UTF8_ERR9;
}
if ((*(++p) & 0xc0) != 0x80) /* Sixth byte */
{
*erroroffset = (int)(p - string) - 5;
- return PCRE_UTF8_ERR10;
+ return PCRE2_ERROR_UTF8_ERR10;
}
if (c == 0xfc && (d & 0x3c) == 0)
{
*erroroffset = (int)(p - string) - 5;
- return PCRE_UTF8_ERR19;
+ return PCRE2_ERROR_UTF8_ERR19;
}
break;
}
@@ -285,17 +310,89 @@ for (p = string; length-- > 0; p++)
if (ab > 3)
{
*erroroffset = (int)(p - string) - ab;
- return (ab == 4)? PCRE_UTF8_ERR11 : PCRE_UTF8_ERR12;
+ return (ab == 4)? PCRE2_ERROR_UTF8_ERR11 : PCRE2_ERROR_UTF8_ERR12;
}
}
+return 0;
-#else /* Not SUPPORT_UTF */
-(void)(string); /* Keep picky compilers happy */
-(void)(length);
-(void)(erroroffset);
-#endif
-return PCRE_UTF8_ERR0; /* This indicates success */
+/* ----------------- Check a UTF-16 string ----------------- */
+
+#elif PCRE2_CODE_UNIT_WIDTH == 16
+
+/* There's not so much work, nor so many errors, for UTF-16.
+PCRE2_ERROR_UTF16_ERR1 Missing low surrogate at the end of the string
+PCRE2_ERROR_UTF16_ERR2 Invalid low surrogate
+PCRE2_ERROR_UTF16_ERR3 Isolated low surrogate
+*/
+
+for (p = string; length > 0; p++)
+ {
+ c = *p;
+ length--;
+
+ if ((c & 0xf800) != 0xd800)
+ {
+ /* Normal UTF-16 code point. Neither high nor low surrogate. */
+ }
+ else if ((c & 0x0400) == 0)
+ {
+ /* High surrogate. Must be a followed by a low surrogate. */
+ if (length == 0)
+ {
+ *erroroffset = p - string;
+ return PCRE2_ERROR_UTF16_ERR1;
+ }
+ p++;
+ length--;
+ if ((*p & 0xfc00) != 0xdc00)
+ {
+ *erroroffset = p - string;
+ return PCRE2_ERROR_UTF16_ERR2;
+ }
+ }
+ else
+ {
+ /* Isolated low surrogate. Always an error. */
+ *erroroffset = p - string;
+ return PCRE2_ERROR_UTF16_ERR3;
+ }
+ }
+return 0;
+
+
+
+/* ----------------- Check a UTF-32 string ----------------- */
+
+#else
+
+/* There is very little to do for a UTF-32 string.
+PCRE2_ERROR_UTF32_ERR1 Surrogate character
+PCRE2_ERROR_UTF32_ERR2 Character > 0x10ffff
+*/
+
+for (p = string; length > 0; length--, p++)
+ {
+ c = *p;
+ if ((c & 0xfffff800u) != 0xd800u)
+ {
+ /* Normal UTF-32 code point. Neither high nor low surrogate. */
+ if (c > 0x10ffffu)
+ {
+ *erroroffset = p - string;
+ return PCRE2_ERROR_UTF32_ERR2;
+ }
+ }
+ else
+ {
+ /* A surrogate */
+ *erroroffset = p - string;
+ return PCRE2_ERROR_UTF32_ERR1;
+ }
+ }
+return 0;
+#endif /* CODE_UNIT_WIDTH */
}
+#endif /* SUPPORT_UNICODE */
-/* End of pcre_valid_utf8.c */
+/* End of pcre2_valid_utf.c */
diff --git a/src/3rdparty/pcre/pcre_xclass.c b/src/3rdparty/pcre2/src/pcre2_xclass.c
index ef759a589a..407d3f5b87 100644
--- a/src/3rdparty/pcre/pcre_xclass.c
+++ b/src/3rdparty/pcre2/src/pcre2_xclass.c
@@ -6,7 +6,8 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
- Copyright (c) 1997-2013 University of Cambridge
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -37,46 +38,46 @@ 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(). */
+class. It is used by pcre2_auto_possessify() and by both pcre2_match() and
+pcre2_def_match(). */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include "pcre_internal.h"
+#include "pcre2_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.
+might contain codepoints above 255 and/or Unicode properties.
Arguments:
c the character
- data points to the flag byte of the XCLASS data
+ data points to the flag code unit of the XCLASS data
+ utf TRUE if in UTF mode
Returns: TRUE if character matches, else FALSE
*/
BOOL
-PRIV(xclass)(pcre_uint32 c, const pcre_uchar *data, BOOL utf)
+PRIV(xclass)(uint32_t c, PCRE2_SPTR data, BOOL utf)
{
-pcre_uchar t;
+PCRE2_UCHAR t;
BOOL negated = (*data & XCL_NOT) != 0;
-(void)utf;
-#ifdef COMPILE_PCRE8
+#if PCRE2_CODE_UNIT_WIDTH == 8
/* 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
+/* Code points < 256 are matched against a bitmap, if one is present. If not,
+we still carry on, because there may be ranges that start below 256 in the
additional data. */
if (c < 256)
@@ -84,37 +85,37 @@ if (c < 256)
if ((*data & XCL_HASPROP) == 0)
{
if ((*data & XCL_MAP) == 0) return negated;
- return (((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0;
+ return (((uint8_t *)(data + 1))[c/8] & (1 << (c&7))) != 0;
}
if ((*data & XCL_MAP) != 0 &&
- (((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0)
+ (((uint8_t *)(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. */
+encounter XCL_PROP or XCL_NOTPROP when UTF support is not compiled. */
-if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(pcre_uchar);
+if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(PCRE2_UCHAR);
while ((t = *data++) != XCL_END)
{
- pcre_uint32 x, y;
+ uint32_t x, y;
if (t == XCL_SINGLE)
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
GETCHARINC(x, data); /* macro generates multiple statements */
}
else
#endif
- x = *data++;
+ x = *data++;
if (c == x) return !negated;
}
else if (t == XCL_RANGE)
{
-#ifdef SUPPORT_UTF
+#ifdef SUPPORT_UNICODE
if (utf)
{
GETCHARINC(x, data); /* macro generates multiple statements */
@@ -129,7 +130,7 @@ while ((t = *data++) != XCL_END)
if (c >= x && c <= y) return !negated;
}
-#ifdef SUPPORT_UCP
+#ifdef SUPPORT_UNICODE
else /* XCL_PROP & XCL_NOTPROP */
{
const ucd_record *prop = GET_UCD(c);
@@ -259,10 +260,12 @@ while ((t = *data++) != XCL_END)
data += 2;
}
-#endif /* SUPPORT_UCP */
+#else
+ (void)utf; /* Avoid compiler warning */
+#endif /* SUPPORT_UNICODE */
}
return negated; /* char did not match */
}
-/* End of pcre_xclass.c */
+/* End of pcre2_xclass.c */
diff --git a/src/3rdparty/pcre/sljit/sljitConfig.h b/src/3rdparty/pcre2/src/sljit/sljitConfig.h
index 1c8a521aa8..a548c37ab6 100644
--- a/src/3rdparty/pcre/sljit/sljitConfig.h
+++ b/src/3rdparty/pcre2/src/sljit/sljitConfig.h
@@ -82,7 +82,7 @@
/* --------------------------------------------------------------------- */
/* If SLJIT_STD_MACROS_DEFINED is not defined, the application should
- define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMMOVE, and NULL. */
+ define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMCPY, and NULL. */
#ifndef SLJIT_STD_MACROS_DEFINED
/* Disabled by default. */
#define SLJIT_STD_MACROS_DEFINED 0
diff --git a/src/3rdparty/pcre/sljit/sljitConfigInternal.h b/src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h
index 9275b14992..566c368063 100644
--- a/src/3rdparty/pcre/sljit/sljitConfigInternal.h
+++ b/src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h
@@ -210,8 +210,8 @@
#define SLJIT_FREE(ptr, allocator_data) free(ptr)
#endif
-#ifndef SLJIT_MEMMOVE
-#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len)
+#ifndef SLJIT_MEMCPY
+#define SLJIT_MEMCPY(dest, src, len) memcpy(dest, src, len)
#endif
#ifndef SLJIT_ZEROMEM
diff --git a/src/3rdparty/pcre/sljit/sljitExecAllocator.c b/src/3rdparty/pcre2/src/sljit/sljitExecAllocator.c
index 54f05f5dd7..54f05f5dd7 100644
--- a/src/3rdparty/pcre/sljit/sljitExecAllocator.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitExecAllocator.c
diff --git a/src/3rdparty/pcre/sljit/sljitLir.c b/src/3rdparty/pcre2/src/sljit/sljitLir.c
index ec1781e4c7..ec1781e4c7 100644
--- a/src/3rdparty/pcre/sljit/sljitLir.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitLir.c
diff --git a/src/3rdparty/pcre/sljit/sljitLir.h b/src/3rdparty/pcre2/src/sljit/sljitLir.h
index df69b8656f..df69b8656f 100644
--- a/src/3rdparty/pcre/sljit/sljitLir.h
+++ b/src/3rdparty/pcre2/src/sljit/sljitLir.h
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_32.c b/src/3rdparty/pcre2/src/sljit/sljitNativeARM_32.c
index b92808f526..b92808f526 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeARM_32.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeARM_32.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_64.c b/src/3rdparty/pcre2/src/sljit/sljitNativeARM_64.c
index d9958512c8..d9958512c8 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeARM_64.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeARM_64.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c b/src/3rdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
index 1ed44a8130..1ed44a8130 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c b/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
index 5096e4f55e..5096e4f55e 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_64.c b/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_64.c
index c7ee8c9c2e..c7ee8c9c2e 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeMIPS_64.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_64.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c b/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_common.c
index c2c251b1ff..c2c251b1ff 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_common.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_32.c b/src/3rdparty/pcre2/src/sljit/sljitNativePPC_32.c
index 0f23cf86dd..0f23cf86dd 100644
--- a/src/3rdparty/pcre/sljit/sljitNativePPC_32.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativePPC_32.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_64.c b/src/3rdparty/pcre2/src/sljit/sljitNativePPC_64.c
index 8e3223f725..8e3223f725 100644
--- a/src/3rdparty/pcre/sljit/sljitNativePPC_64.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativePPC_64.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c b/src/3rdparty/pcre2/src/sljit/sljitNativePPC_common.c
index a3647327bf..a3647327bf 100644
--- a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativePPC_common.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativeSPARC_32.c b/src/3rdparty/pcre2/src/sljit/sljitNativeSPARC_32.c
index 7e589a17c2..7e589a17c2 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeSPARC_32.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeSPARC_32.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c b/src/3rdparty/pcre2/src/sljit/sljitNativeSPARC_common.c
index f3a33a1097..f3a33a1097 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeSPARC_common.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativeTILEGX-encoder.c b/src/3rdparty/pcre2/src/sljit/sljitNativeTILEGX-encoder.c
index 719632908c..719632908c 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeTILEGX-encoder.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeTILEGX-encoder.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c b/src/3rdparty/pcre2/src/sljit/sljitNativeTILEGX_64.c
index 462a8b9cd9..462a8b9cd9 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeTILEGX_64.c
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_32.c b/src/3rdparty/pcre2/src/sljit/sljitNativeX86_32.c
index cd3c656c66..78f3dcb06f 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeX86_32.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeX86_32.c
@@ -34,7 +34,7 @@ static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, s
FAIL_IF(!inst);
INC_SIZE(1 + sizeof(sljit_sw));
*inst++ = opcode;
- *(sljit_sw*)inst = imm;
+ sljit_unaligned_store_sw(inst, imm);
return SLJIT_SUCCESS;
}
@@ -57,7 +57,7 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
if (jump->flags & JUMP_LABEL)
jump->flags |= PATCH_MW;
else
- *(sljit_sw*)code_ptr = jump->u.target - (jump->addr + 4);
+ sljit_unaligned_store_sw(code_ptr, jump->u.target - (jump->addr + 4));
code_ptr += 4;
return code_ptr;
@@ -151,12 +151,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
inst[1] = MOD_REG | (reg_map[TMP_REG1] << 3) | reg_map[SLJIT_SP];
inst[2] = GROUP_F7;
inst[3] = MOD_REG | (0 << 3) | reg_map[SLJIT_SP];
- *(sljit_sw*)(inst + 4) = 0x4;
+ sljit_unaligned_store_sw(inst + 4, 0x4);
inst[8] = JNE_i8;
inst[9] = 6;
inst[10] = GROUP_BINARY_81;
inst[11] = MOD_REG | (5 << 3) | reg_map[SLJIT_SP];
- *(sljit_sw*)(inst + 12) = 0x4;
+ sljit_unaligned_store_sw(inst + 12, 0x4);
inst[16] = PUSH_r + reg_map[TMP_REG1];
}
else
@@ -406,7 +406,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
if (immb <= 127 && immb >= -128)
*buf_ptr++ = immb; /* 8 bit displacement. */
else {
- *(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
+ sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */
buf_ptr += sizeof(sljit_sw);
}
}
@@ -418,7 +418,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
}
else {
*buf_ptr++ |= 0x05;
- *(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
+ sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */
buf_ptr += sizeof(sljit_sw);
}
@@ -426,9 +426,9 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
if (flags & EX86_BYTE_ARG)
*buf_ptr = imma;
else if (flags & EX86_HALF_ARG)
- *(short*)buf_ptr = imma;
+ sljit_unaligned_store_s16(buf_ptr, imma);
else if (!(flags & EX86_SHIFT_INS))
- *(sljit_sw*)buf_ptr = imma;
+ sljit_unaligned_store_sw(buf_ptr, imma);
}
return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
@@ -541,7 +541,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
INC_SIZE(5 + 1);
*inst++ = PUSH_i32;
- *(sljit_sw*)inst = srcw;
+ sljit_unaligned_store_sw(inst, srcw);
inst += sizeof(sljit_sw);
}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_64.c b/src/3rdparty/pcre2/src/sljit/sljitNativeX86_64.c
index 6ea27e5513..e88ddedcd1 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeX86_64.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeX86_64.c
@@ -35,7 +35,7 @@ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg,
INC_SIZE(2 + sizeof(sljit_sw));
*inst++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
*inst++ = MOV_r_i32 + (reg_map[reg] & 0x7);
- *(sljit_sw*)inst = imm;
+ sljit_unaligned_store_sw(inst, imm);
return SLJIT_SUCCESS;
}
@@ -55,7 +55,7 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
if (jump->flags & JUMP_LABEL)
jump->flags |= PATCH_MD;
else
- *(sljit_sw*)code_ptr = jump->u.target;
+ sljit_unaligned_store_sw(code_ptr, jump->u.target);
code_ptr += sizeof(sljit_sw);
*code_ptr++ = REX_B;
@@ -71,13 +71,13 @@ static sljit_u8* generate_fixed_jump(sljit_u8 *code_ptr, sljit_sw addr, sljit_s3
if (delta <= HALFWORD_MAX && delta >= HALFWORD_MIN) {
*code_ptr++ = (type == 2) ? CALL_i32 : JMP_i32;
- *(sljit_sw*)code_ptr = delta;
+ sljit_unaligned_store_sw(code_ptr, delta);
}
else {
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second);
*code_ptr++ = REX_W | REX_B;
*code_ptr++ = MOV_r_i32 + 1;
- *(sljit_sw*)code_ptr = addr;
+ sljit_unaligned_store_sw(code_ptr, addr);
code_ptr += sizeof(sljit_sw);
*code_ptr++ = REX_B;
*code_ptr++ = GROUP_FF;
@@ -193,7 +193,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
*inst++ = REX_W;
*inst++ = MOV_rm_i32;
*inst++ = MOD_REG | reg_lmap[SLJIT_R0];
- *(sljit_s32*)inst = local_size;
+ sljit_unaligned_store_s32(inst, local_size);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
@@ -219,7 +219,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
*inst++ = REX_W;
*inst++ = GROUP_BINARY_81;
*inst++ = MOD_REG | SUB | 4;
- *(sljit_s32*)inst = local_size;
+ sljit_unaligned_store_s32(inst, local_size);
inst += sizeof(sljit_s32);
}
@@ -230,7 +230,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
FAIL_IF(!inst);
INC_SIZE(5);
*inst++ = GROUP_0F;
- *(sljit_s32*)inst = 0x20247429;
+ sljit_unaligned_store_s32(inst, 0x20247429);
}
#endif
@@ -271,7 +271,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
FAIL_IF(!inst);
INC_SIZE(5);
*inst++ = GROUP_0F;
- *(sljit_s32*)inst = 0x20247428;
+ sljit_unaligned_store_s32(inst, 0x20247428);
}
#endif
@@ -292,7 +292,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
*inst++ = REX_W;
*inst++ = GROUP_BINARY_81;
*inst++ = MOD_REG | ADD | 4;
- *(sljit_s32*)inst = compiler->local_size;
+ sljit_unaligned_store_s32(inst, compiler->local_size);
}
tmp = compiler->scratches;
@@ -339,7 +339,7 @@ static sljit_s32 emit_do_imm32(struct sljit_compiler *compiler, sljit_u8 rex, sl
if (rex)
*inst++ = rex;
*inst++ = opcode;
- *(sljit_s32*)inst = imm;
+ sljit_unaligned_store_s32(inst, imm);
return SLJIT_SUCCESS;
}
@@ -516,7 +516,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
if (immb <= 127 && immb >= -128)
*buf_ptr++ = immb; /* 8 bit displacement. */
else {
- *(sljit_s32*)buf_ptr = immb; /* 32 bit displacement. */
+ sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */
buf_ptr += sizeof(sljit_s32);
}
}
@@ -533,7 +533,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
else {
*buf_ptr++ |= 0x04;
*buf_ptr++ = 0x25;
- *(sljit_s32*)buf_ptr = immb; /* 32 bit displacement. */
+ sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */
buf_ptr += sizeof(sljit_s32);
}
@@ -541,9 +541,9 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
if (flags & EX86_BYTE_ARG)
*buf_ptr = imma;
else if (flags & EX86_HALF_ARG)
- *(short*)buf_ptr = imma;
+ sljit_unaligned_store_s16(buf_ptr, imma);
else if (!(flags & EX86_SHIFT_INS))
- *(sljit_s32*)buf_ptr = imma;
+ sljit_unaligned_store_s32(buf_ptr, imma);
}
return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
@@ -676,7 +676,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler
INC_SIZE(5 + 1);
*inst++ = PUSH_i32;
- *(sljit_s32*)inst = srcw;
+ sljit_unaligned_store_s32(inst, srcw);
inst += sizeof(sljit_s32);
}
diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre2/src/sljit/sljitNativeX86_common.c
index 4aa5020623..aa5ba089d2 100644
--- a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitNativeX86_common.c
@@ -279,6 +279,29 @@ static sljit_s32 cpu_has_cmov = -1;
#include <intrin.h>
#endif
+/******************************************************/
+/* Unaligned-store functions */
+/******************************************************/
+
+static SLJIT_INLINE void sljit_unaligned_store_s16(void *addr, sljit_s16 value)
+{
+ SLJIT_MEMCPY(addr, &value, sizeof(value));
+}
+
+static SLJIT_INLINE void sljit_unaligned_store_s32(void *addr, sljit_s32 value)
+{
+ SLJIT_MEMCPY(addr, &value, sizeof(value));
+}
+
+static SLJIT_INLINE void sljit_unaligned_store_sw(void *addr, sljit_sw value)
+{
+ SLJIT_MEMCPY(addr, &value, sizeof(value));
+}
+
+/******************************************************/
+/* Utility functions */
+/******************************************************/
+
static void get_cpu_features(void)
{
sljit_u32 features;
@@ -289,7 +312,7 @@ static void get_cpu_features(void)
__cpuid(CPUInfo, 1);
features = (sljit_u32)CPUInfo[3];
-#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C) || defined(__ghs)
+#elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_C)
/* AT&T syntax. */
__asm__ (
@@ -478,7 +501,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
len = *buf_ptr++;
if (len > 0) {
/* The code is already generated. */
- SLJIT_MEMMOVE(code_ptr, buf_ptr, len);
+ SLJIT_MEMCPY(code_ptr, buf_ptr, len);
code_ptr += len;
buf_ptr += len;
}
@@ -504,7 +527,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
*code_ptr++ = (*buf_ptr == 2) ? CALL_i32 : JMP_i32;
buf_ptr++;
- *(sljit_sw*)code_ptr = *(sljit_sw*)buf_ptr - ((sljit_sw)code_ptr + sizeof(sljit_sw));
+ sljit_unaligned_store_sw(code_ptr, *(sljit_sw*)buf_ptr - ((sljit_sw)code_ptr + sizeof(sljit_sw)));
code_ptr += sizeof(sljit_sw);
buf_ptr += sizeof(sljit_sw) - 1;
#else
@@ -531,24 +554,24 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} else if (jump->flags & PATCH_MW) {
if (jump->flags & JUMP_LABEL) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- *(sljit_sw*)jump->addr = (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sw)));
+ sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_sw))));
#else
SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.label->addr - (jump->addr + sizeof(sljit_s32))) <= HALFWORD_MAX);
- *(sljit_s32*)jump->addr = (sljit_s32)(jump->u.label->addr - (jump->addr + sizeof(sljit_s32)));
+ sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.label->addr - (jump->addr + sizeof(sljit_s32))));
#endif
}
else {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- *(sljit_sw*)jump->addr = (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_sw)));
+ sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_sw))));
#else
SLJIT_ASSERT((sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_s32))) >= HALFWORD_MIN && (sljit_sw)(jump->u.target - (jump->addr + sizeof(sljit_s32))) <= HALFWORD_MAX);
- *(sljit_s32*)jump->addr = (sljit_s32)(jump->u.target - (jump->addr + sizeof(sljit_s32)));
+ sljit_unaligned_store_s32((void*)jump->addr, (sljit_s32)(jump->u.target - (jump->addr + sizeof(sljit_s32))));
#endif
}
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
else if (jump->flags & PATCH_MD)
- *(sljit_sw*)jump->addr = jump->u.label->addr;
+ sljit_unaligned_store_sw((void*)jump->addr, jump->u.label->addr);
#endif
jump = jump->next;
@@ -1699,7 +1722,7 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler,
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
FAIL_IF(!inst);
INC_SIZE(4);
- *(sljit_sw*)inst = src1w;
+ sljit_unaligned_store_sw(inst, src1w);
}
#else
else if (IS_HALFWORD(src1w)) {
@@ -1709,7 +1732,7 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler,
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
FAIL_IF(!inst);
INC_SIZE(4);
- *(sljit_s32*)inst = (sljit_s32)src1w;
+ sljit_unaligned_store_s32(inst, (sljit_s32)src1w);
}
else {
EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src1w);
@@ -1742,7 +1765,7 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler,
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
FAIL_IF(!inst);
INC_SIZE(4);
- *(sljit_sw*)inst = src2w;
+ sljit_unaligned_store_sw(inst, src2w);
}
#else
else if (IS_HALFWORD(src2w)) {
@@ -1752,7 +1775,7 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler,
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
FAIL_IF(!inst);
INC_SIZE(4);
- *(sljit_s32*)inst = (sljit_s32)src2w;
+ sljit_unaligned_store_s32(inst, (sljit_s32)src2w);
}
else {
EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src2w);
@@ -2248,7 +2271,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
FAIL_IF(!inst);
INC_SIZE(size);
- SLJIT_MEMMOVE(inst, instruction, size);
+ SLJIT_MEMCPY(inst, instruction, size);
return SLJIT_SUCCESS;
}
@@ -2926,15 +2949,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
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_sw*)addr = new_addr - (addr + 4);
+ sljit_unaligned_store_sw((void*)addr, new_addr - (addr + 4));
#else
- *(sljit_uw*)addr = new_addr;
+ sljit_unaligned_store_sw((void*)addr, (sljit_sw) new_addr);
#endif
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
{
- *(sljit_sw*)addr = new_constant;
+ sljit_unaligned_store_sw((void*)addr, new_constant);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_x86_is_sse2_available(void)
diff --git a/src/3rdparty/pcre/sljit/sljitUtils.c b/src/3rdparty/pcre2/src/sljit/sljitUtils.c
index ec5c321194..ec5c321194 100644
--- a/src/3rdparty/pcre/sljit/sljitUtils.c
+++ b/src/3rdparty/pcre2/src/sljit/sljitUtils.c
diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/QtANGLE/QtANGLE.pro
index b699ae159a..ee3111b6ee 100644
--- a/src/angle/src/libGLESv2/libGLESv2.pro
+++ b/src/angle/src/QtANGLE/QtANGLE.pro
@@ -1,10 +1,59 @@
CONFIG += simd no_batch
include(../common/common.pri)
+TARGET=$$qtLibraryTarget($${LIBQTANGLE_NAME})
DEF_FILE_TARGET=$${TARGET}
-TARGET=$$qtLibraryTarget($${LIBGLESV2_NAME})
INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libANGLE
+!build_pass {
+ # Merge libGLESv2 and libEGL .def files located under $$ANGLE_DIR into QtANGLE$${SUFFIX}.def
+ DEF_FILES = \
+ libGLESv2/libGLESv2 \
+ libEGL/libEGL
+
+ SUFFIX =
+ for (DEBUG_RELEASE, $$list(0 1)) {
+ DEF_MERGED = \
+ "LIBRARY $${LIBQTANGLE_NAME}$$SUFFIX" \
+ EXPORTS
+ mingw: SUFFIX = $${SUFFIX}_mingw32
+ PASS = 0
+ MAX_ORDINAL = 0
+
+ for (DEF_FILE, DEF_FILES) {
+ DEF_FILE_PATH = $$ANGLE_DIR/src/$$DEF_FILE$${SUFFIX}.def
+ DEF_SRC = $$cat($$DEF_FILE_PATH, lines)
+ DEF_MERGED += \
+ ";" \
+ "; Generated from:" \
+ "; $$DEF_FILE_PATH"
+
+ for (line, DEF_SRC) {
+ !contains(line, "(LIBRARY.*|EXPORTS)") {
+ LINESPLIT = $$split(line, @)
+ !count(LINESPLIT, 1) {
+ equals(PASS, 1) {
+ # In the second .def file we must allocate new ordinals in order
+ # to not clash with the ordinals from the first file. We then start off
+ # from MAX_ORDINAL + 1 and increase sequentially
+ MAX_ORDINAL = $$num_add($$MAX_ORDINAL, 1)
+ line = $$section(line, @, 0, -2)@$$MAX_ORDINAL
+ } else {
+ ORDINAL = $$last(LINESPLIT)
+ greaterThan(ORDINAL, $$MAX_ORDINAL): \
+ MAX_ORDINAL = $$ORDINAL
+ }
+ }
+ DEF_MERGED += $$line
+ }
+ }
+ PASS = 1
+ }
+ write_file($${LIBQTANGLE_NAME}$${SUFFIX}.def, DEF_MERGED)|error()
+ SUFFIX = "d"
+ }
+}
+
# Remember to adapt tools/configure/configureapp.cpp if the Direct X version changes.
!winrt: \
LIBS_PRIVATE += -ld3d9
@@ -234,7 +283,8 @@ SOURCES += \
$$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0.cpp \
$$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0_ext.cpp \
$$ANGLE_DIR/src/libGLESv2/global_state.cpp \
- $$ANGLE_DIR/src/libGLESv2/libGLESv2.cpp
+ $$ANGLE_DIR/src/libGLESv2/libGLESv2.cpp \
+ $$ANGLE_DIR/src/libEGL/libEGL.cpp
SSE2_SOURCES += $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimageSSE2.cpp
@@ -361,8 +411,8 @@ angle_d3d11 {
}
!static {
- DEF_FILE = $$ANGLE_DIR/src/libGLESv2/$${DEF_FILE_TARGET}.def
- mingw:equals(QT_ARCH, i386): DEF_FILE = $$ANGLE_DIR/src/libGLESv2/$${DEF_FILE_TARGET}_mingw32.def
+ DEF_FILE = $$PWD/$${DEF_FILE_TARGET}.def
+ mingw: equals(QT_ARCH, i386): DEF_FILE = $$PWD/$${DEF_FILE_TARGET}_mingw32.def
} else {
DEFINES += DllMain=DllMain_ANGLE # prevent symbol from conflicting with the user's DllMain
}
@@ -610,5 +660,10 @@ gles3_headers.files = \
$$ANGLE_DIR/include/GLES3/gl3ext.h \
$$ANGLE_DIR/include/GLES3/gl3platform.h
gles3_headers.path = $$[QT_INSTALL_HEADERS]/QtANGLE/GLES3
-INSTALLS += khr_headers gles2_headers
+egl_headers.files = \
+ $$ANGLE_DIR/include/EGL/egl.h \
+ $$ANGLE_DIR/include/EGL/eglext.h \
+ $$ANGLE_DIR/include/EGL/eglplatform.h
+egl_headers.path = $$[QT_INSTALL_HEADERS]/QtANGLE/EGL
+INSTALLS += khr_headers gles2_headers egl_headers
angle_d3d11: INSTALLS += gles3_headers
diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro
deleted file mode 100644
index 3b2d516ecb..0000000000
--- a/src/angle/src/libEGL/libEGL.pro
+++ /dev/null
@@ -1,27 +0,0 @@
-include(../common/common.pri)
-DEF_FILE_TARGET=$${TARGET}
-TARGET=$$qtLibraryTarget($${LIBEGL_NAME})
-winrt: LIBS_PRIVATE += -ld3d11
-
-LIBS_PRIVATE += -ldxguid
-QMAKE_USE_PRIVATE += $${LIBGLESV2_NAME}
-
-DEFINES += GL_APICALL= GL_GLEXT_PROTOTYPES= EGLAPI= LIBEGL_IMPLEMENTATION
-
-HEADERS += \
- $$ANGLE_DIR/src/libEGL/resource.h
-
-SOURCES += \
- $$ANGLE_DIR/src/libEGL/libEGL.cpp
-
-!static {
- DEF_FILE = $$ANGLE_DIR/src/libEGL/$${DEF_FILE_TARGET}.def
- mingw:equals(QT_ARCH, i386): DEF_FILE = $$ANGLE_DIR/src/libEGL/$${DEF_FILE_TARGET}_mingw32.def
-}
-
-egl_headers.files = \
- $$ANGLE_DIR/include/EGL/egl.h \
- $$ANGLE_DIR/include/EGL/eglext.h \
- $$ANGLE_DIR/include/EGL/eglplatform.h
-egl_headers.path = $$[QT_INSTALL_HEADERS]/QtANGLE/EGL
-INSTALLS += egl_headers
diff --git a/src/angle/src/src.pro b/src/angle/src/src.pro
index d1f5f57591..77c3ee7198 100644
--- a/src/angle/src/src.pro
+++ b/src/angle/src/src.pro
@@ -1,3 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS += compiler libGLESv2 libEGL
+SUBDIRS += compiler QtANGLE
CONFIG += ordered
diff --git a/src/corelib/configure.json b/src/corelib/configure.json
index c170b38977..f4162956d3 100644
--- a/src/corelib/configure.json
+++ b/src/corelib/configure.json
@@ -11,7 +11,7 @@
"icu": "boolean",
"inotify": "boolean",
"journald": "boolean",
- "pcre": { "type": "enum", "values": [ "qt", "system" ] },
+ "pcre2": { "type": "enum", "values": [ "qt", "system" ] },
"posix-ipc": { "type": "boolean", "name": "ipc_posix" },
"pps": { "type": "boolean", "name": "qqnx_pps" },
"slog2": "boolean",
@@ -81,11 +81,11 @@
"-ldl"
]
},
- "pcre": {
- "label": "PCRE",
- "test": "unix/pcre",
+ "pcre2": {
+ "label": "PCRE2",
+ "test": "unix/pcre2",
"sources": [
- "-lpcre16"
+ "-lpcre2-16"
]
},
"pps": {
@@ -307,14 +307,14 @@
"section": "Utilities",
"output": [ "publicFeature", "feature" ]
},
- "system-pcre": {
- "label": "Using system PCRE",
- "disable": "input.pcre == 'qt'",
- "enable": "input.pcre == 'system'",
- "condition": "libs.pcre",
+ "system-pcre2": {
+ "label": "Using system PCRE2",
+ "disable": "input.pcre2 == 'qt'",
+ "enable": "input.pcre2 == 'system'",
+ "condition": "libs.pcre2",
"output": [
"privateFeature",
- { "type": "privateConfig", "negative": true, "name": "pcre" }
+ { "type": "privateConfig", "negative": true, "name": "pcre2" }
]
},
"poll_ppoll": {
@@ -629,7 +629,7 @@ Please apply the patch corresponding to your Standard Library vendor, found in
"args": "qqnx_pps",
"condition": "config.qnx"
},
- "system-pcre"
+ "system-pcre2"
]
}
]
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp
index 9fd52517c2..f852988e9a 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp
@@ -48,14 +48,6 @@
**
****************************************************************************/
-//! [0]
-QLineEdit *lineEdit = static_cast<QLineEdit *>(
- qt_find_obj_child(myWidget, "QLineEdit", "my line edit"));
-if (lineEdit)
- lineEdit->setText("Default");
-//! [0]
-
-
//! [1]
QObject *obj = new QPushButton;
obj->metaObject()->className(); // returns "QPushButton"
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index 36655ca1dd..d23706e631 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -2,6 +2,8 @@
HEADERS += \
global/qglobal.h \
+ global/qoperatingsystemversion.h \
+ global/qoperatingsystemversion_p.h \
global/qsystemdetection.h \
global/qcompilerdetection.h \
global/qprocessordetection.h \
@@ -27,11 +29,15 @@ SOURCES += \
global/qlibraryinfo.cpp \
global/qmalloc.cpp \
global/qnumeric.cpp \
+ global/qoperatingsystemversion.cpp \
global/qlogging.cpp \
global/qhooks.cpp
VERSIONTAGGING_SOURCES = global/qversiontagging.cpp
+darwin: SOURCES += global/qoperatingsystemversion_darwin.mm
+win32: SOURCES += global/qoperatingsystemversion_win.cpp
+
# qlibraryinfo.cpp includes qconfig.cpp
INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 6efdc4c22c..47aca712b7 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -45,6 +45,8 @@
#include "qthreadstorage.h"
#include "qdir.h"
#include "qdatetime.h"
+#include "qoperatingsystemversion.h"
+#include "qoperatingsystemversion_p.h"
#include <private/qlocale_tools_p.h>
#include <qmutex.h>
@@ -1064,10 +1066,6 @@ bool qSharedBuild() Q_DECL_NOTHROW
on which the application is compiled.
\li \l ByteOrder specifies whether the platform is big-endian or
little-endian.
- \li \l WindowsVersion specifies the version of the Windows operating
- system on which the application is run.
- \li \l MacintoshVersion specifies the version of the Macintosh
- operating system on which the application is run.
\endlist
Some constants are defined only on certain platforms. You can use
@@ -1088,12 +1086,14 @@ bool qSharedBuild() Q_DECL_NOTHROW
*/
/*!
+ \deprecated
\variable QSysInfo::WindowsVersion
\brief the version of the Windows operating system on which the
application is run.
*/
/*!
+ \deprecated
\fn QSysInfo::WindowsVersion QSysInfo::windowsVersion()
\since 4.4
@@ -1103,12 +1103,14 @@ bool qSharedBuild() Q_DECL_NOTHROW
*/
/*!
+ \deprecated
\variable QSysInfo::MacintoshVersion
\brief the version of the Macintosh operating system on which
the application is run.
*/
/*!
+ \deprecated
\fn QSysInfo::MacVersion QSysInfo::macVersion()
Returns the version of Darwin (\macos or iOS) on which the
@@ -1126,6 +1128,7 @@ bool qSharedBuild() Q_DECL_NOTHROW
*/
/*!
+ \deprecated
\enum QSysInfo::WinVersion
This enum provides symbolic names for the various versions of the
@@ -1182,6 +1185,7 @@ bool qSharedBuild() Q_DECL_NOTHROW
*/
/*!
+ \deprecated
\enum QSysInfo::MacVersion
This enum provides symbolic names for the various versions of the
@@ -1949,28 +1953,31 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qnamespace.h"
QT_END_INCLUDE_NAMESPACE
+#if QT_DEPRECATED_SINCE(5, 9)
QSysInfo::MacVersion QSysInfo::macVersion()
{
- const QAppleOperatingSystemVersion version = qt_apple_os_version(); // qtcore_mac_objc.mm
+ const auto version = QOperatingSystemVersion::current();
#if defined(Q_OS_OSX)
- return QSysInfo::MacVersion(Q_MV_OSX(version.major, version.minor));
+ return QSysInfo::MacVersion(Q_MV_OSX(version.majorVersion(), version.minorVersion()));
#elif defined(Q_OS_IOS)
- return QSysInfo::MacVersion(Q_MV_IOS(version.major, version.minor));
+ return QSysInfo::MacVersion(Q_MV_IOS(version.majorVersion(), version.minorVersion()));
#elif defined(Q_OS_TVOS)
- return QSysInfo::MacVersion(Q_MV_TVOS(version.major, version.minor));
+ return QSysInfo::MacVersion(Q_MV_TVOS(version.majorVersion(), version.minorVersion()));
#elif defined(Q_OS_WATCHOS)
- return QSysInfo::MacVersion(Q_MV_WATCHOS(version.major, version.minor));
+ return QSysInfo::MacVersion(Q_MV_WATCHOS(version.majorVersion(), version.minorVersion()));
#else
return QSysInfo::MV_Unknown;
#endif
}
const QSysInfo::MacVersion QSysInfo::MacintoshVersion = QSysInfo::macVersion();
+#endif
-#ifdef Q_OS_OSX
-static const char *osxVer_helper(QAppleOperatingSystemVersion version = qt_apple_os_version())
+#ifdef Q_OS_DARWIN
+static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
{
- if (version.major == 10) {
- switch (version.minor) {
+#ifdef Q_OS_MACOS
+ if (version.majorVersion() == 10) {
+ switch (version.minorVersion()) {
case 9:
return "Mavericks";
case 10:
@@ -1982,6 +1989,9 @@ static const char *osxVer_helper(QAppleOperatingSystemVersion version = qt_apple
}
}
// unknown, future version
+#else
+ Q_UNUSED(version);
+#endif
return 0;
}
#endif
@@ -2022,140 +2032,30 @@ QWindowsSockInit::~QWindowsSockInit()
Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit)
# endif // QT_BOOTSTRAPPED
-#ifdef Q_OS_WINRT
-static inline HMODULE moduleHandleForFunction(LPCVOID address)
-{
- // This is a widely used, decades-old technique for retrieving the handle
- // of a module and is effectively equivalent to GetModuleHandleEx
- // (which is unavailable on WinRT)
- MEMORY_BASIC_INFORMATION mbi = { 0, 0, 0, 0, 0, 0, 0 };
- if (VirtualQuery(address, &mbi, sizeof(mbi)) == 0)
- return 0;
- return reinterpret_cast<HMODULE>(mbi.AllocationBase);
-}
-#endif
-
-static inline OSVERSIONINFOEX determineWinOsVersion()
-{
- OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0};
-
-#define GetProcAddressA GetProcAddress
-
- // GetModuleHandle is not supported in WinRT and linking to it at load time
- // will not pass the Windows App Certification Kit... but it exists and is functional,
- // so use some unusual but widely used techniques to get a pointer to it
-#ifdef Q_OS_WINRT
- // 1. Get HMODULE of kernel32.dll, using the address of some function exported by that DLL
- HMODULE kernelModule = moduleHandleForFunction(reinterpret_cast<LPCVOID>(VirtualQuery));
- if (Q_UNLIKELY(!kernelModule))
- return result;
-
- // 2. Get pointer to GetModuleHandle so we can then load other arbitrary modules (DLLs)
- typedef HMODULE(WINAPI *GetModuleHandleFunction)(LPCWSTR);
- GetModuleHandleFunction pGetModuleHandle = reinterpret_cast<GetModuleHandleFunction>(
- GetProcAddressA(kernelModule, "GetModuleHandleW"));
- if (Q_UNLIKELY(!pGetModuleHandle))
- return result;
-#else
-#define pGetModuleHandle GetModuleHandleW
-#endif
-
-#ifndef Q_OS_WINCE
- HMODULE ntdll = pGetModuleHandle(L"ntdll.dll");
- if (Q_UNLIKELY(!ntdll))
- return result;
-
- // NTSTATUS is not defined on WinRT
- typedef LONG NTSTATUS;
- typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO);
-
- // RtlGetVersion is documented public API but we must load it dynamically
- // because linking to it at load time will not pass the Windows App Certification Kit
- // https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx
- RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(
- GetProcAddressA(ntdll, "RtlGetVersion"));
- if (Q_UNLIKELY(!pRtlGetVersion))
- return result;
-
- // GetVersionEx() has been deprecated in Windows 8.1 and will return
- // only Windows 8 from that version on, so use the kernel API function.
- pRtlGetVersion((LPOSVERSIONINFO) &result); // always returns STATUS_SUCCESS
-#else // !Q_OS_WINCE
- GetVersionEx(&result);
-#endif
- return result;
-}
-
-static OSVERSIONINFOEX winOsVersion()
-{
- OSVERSIONINFOEX realResult = determineWinOsVersion();
-#ifdef QT_DEBUG
- {
- if (Q_UNLIKELY(qEnvironmentVariableIsSet("QT_WINVER_OVERRIDE"))) {
- OSVERSIONINFOEX result = realResult;
- result.dwMajorVersion = 0;
- result.dwMinorVersion = 0;
-
- // Erase any build number and service pack information
- result.dwBuildNumber = 0;
- result.szCSDVersion[0] = L'\0';
- result.wServicePackMajor = 0;
- result.wServicePackMinor = 0;
-
- const QByteArray winVerOverride = qgetenv("QT_WINVER_OVERRIDE");
- if (winVerOverride == "WINDOWS7" || winVerOverride == "2008_R2") {
- result.dwMajorVersion = 6;
- result.dwMinorVersion = 1;
- } else if (winVerOverride == "WINDOWS8" || winVerOverride == "2012") {
- result.dwMajorVersion = 6;
- result.dwMinorVersion = 2;
- } else if (winVerOverride == "WINDOWS8_1" || winVerOverride == "2012_R2") {
- result.dwMajorVersion = 6;
- result.dwMinorVersion = 3;
- } else if (winVerOverride == "WINDOWS10" || winVerOverride == "2016") {
- result.dwMajorVersion = 10;
- } else {
- return realResult;
- }
-
- if (winVerOverride == "2008_R2"
- || winVerOverride == "2012"
- || winVerOverride == "2012_R2"
- || winVerOverride == "2016") {
- // If the current host OS is a domain controller and the override OS
- // is also a server type OS, preserve that information
- if (result.wProductType == VER_NT_WORKSTATION)
- result.wProductType = VER_NT_SERVER;
- } else {
- // Any other OS must be a workstation OS type
- result.wProductType = VER_NT_WORKSTATION;
- }
- }
- }
-#endif
- return realResult;
-}
-
+#if QT_DEPRECATED_SINCE(5, 9)
QSysInfo::WinVersion QSysInfo::windowsVersion()
{
- const OSVERSIONINFOEX osver = winOsVersion();
- if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1)
+ const auto version = QOperatingSystemVersion::current();
+ if (version.majorVersion() == 6 && version.minorVersion() == 1)
return QSysInfo::WV_WINDOWS7;
- if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2)
+ if (version.majorVersion() == 6 && version.minorVersion() == 2)
return QSysInfo::WV_WINDOWS8;
- if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3)
+ if (version.majorVersion() == 6 && version.minorVersion() == 3)
return QSysInfo::WV_WINDOWS8_1;
- if (osver.dwMajorVersion == 10 && osver.dwMinorVersion == 0)
+ if (version.majorVersion() == 10 && version.minorVersion() == 0)
return QSysInfo::WV_WINDOWS10;
return QSysInfo::WV_NT_based;
}
+const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion();
+#endif
static QString winSp_helper()
{
- const qint16 major = winOsVersion().wServicePackMajor;
+ const auto osv = qWindowsVersionInfo();
+ const qint16 major = osv.wServicePackMajor;
if (major) {
QString sp = QStringLiteral(" SP ") + QString::number(major);
- const qint16 minor = winOsVersion().wServicePackMinor;
+ const qint16 minor = osv.wServicePackMinor;
if (minor)
sp += QLatin1Char('.') + QString::number(minor);
@@ -2164,9 +2064,10 @@ static QString winSp_helper()
return QString();
}
-static const char *winVer_helper()
+static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
{
- const OSVERSIONINFOEX osver = winOsVersion();
+ Q_UNUSED(version);
+ const OSVERSIONINFOEX osver = qWindowsVersionInfo();
const bool workstation = osver.wProductType == VER_NT_WORKSTATION;
#define Q_WINVER(major, minor) (major << 8 | minor)
@@ -2185,8 +2086,6 @@ static const char *winVer_helper()
return 0;
}
-const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion();
-
#endif
#if defined(Q_OS_UNIX)
# if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
@@ -2367,6 +2266,68 @@ static bool findUnixOsVersion(QUnixOSVersion &v)
# endif // USE_ETC_OS_RELEASE
#endif // Q_OS_UNIX
+#ifdef Q_OS_ANDROID
+static const char *osVer_helper(QOperatingSystemVersion)
+{
+/* Data:
+
+
+
+Cupcake
+Donut
+Eclair
+Eclair
+Eclair
+Froyo
+Gingerbread
+Gingerbread
+Honeycomb
+Honeycomb
+Honeycomb
+Ice Cream Sandwich
+Ice Cream Sandwich
+Jelly Bean
+Jelly Bean
+Jelly Bean
+KitKat
+KitKat
+Lollipop
+Lollipop
+Marshmallow
+Nougat
+Nougat
+ */
+ static const char versions_string[] =
+ "\0"
+ "Cupcake\0"
+ "Donut\0"
+ "Eclair\0"
+ "Froyo\0"
+ "Gingerbread\0"
+ "Honeycomb\0"
+ "Ice Cream Sandwich\0"
+ "Jelly Bean\0"
+ "KitKat\0"
+ "Lollipop\0"
+ "Marshmallow\0"
+ "Nougat\0"
+ "\0";
+
+ static const int versions_indices[] = {
+ 0, 0, 0, 1, 9, 15, 15, 15,
+ 22, 28, 28, 40, 40, 40, 50, 50,
+ 69, 69, 69, 80, 80, 87, 87, 96,
+ 108, 108, -1
+ };
+
+ static const int versions_count = (sizeof versions_indices) / (sizeof versions_indices[0]);
+
+ // https://source.android.com/source/build-numbers.html
+ // https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels
+ const int sdk_int = QJNIObjectPrivate::getStaticField<jint>("android/os/Build$VERSION", "SDK_INT");
+ return &versions_string[versions_indices[qBound(0, sdk_int, versions_count - 1)]];
+}
+#endif
/*!
\since 5.4
@@ -2615,9 +2576,9 @@ QString QSysInfo::kernelType()
QString QSysInfo::kernelVersion()
{
#ifdef Q_OS_WIN
- const OSVERSIONINFOEX osver = winOsVersion();
- return QString::number(int(osver.dwMajorVersion)) + QLatin1Char('.') + QString::number(int(osver.dwMinorVersion))
- + QLatin1Char('.') + QString::number(int(osver.dwBuildNumber));
+ const auto osver = QOperatingSystemVersion::current();
+ return QString::number(osver.majorVersion()) + QLatin1Char('.') + QString::number(osver.minorVersion())
+ + QLatin1Char('.') + QString::number(osver.microVersion());
#else
struct utsname u;
if (uname(&u) == 0)
@@ -2685,8 +2646,8 @@ QString QSysInfo::productType()
#elif defined(Q_OS_WATCHOS)
return QStringLiteral("watchos");
#elif defined(Q_OS_MACOS)
- const QAppleOperatingSystemVersion version = qt_apple_os_version();
- if (version.major == 10 && version.minor < 12)
+ const auto version = QOperatingSystemVersion::current();
+ if (version.majorVersion() == 10 && version.minorVersion() < 12)
return QStringLiteral("osx");
return QStringLiteral("macos");
#elif defined(Q_OS_DARWIN)
@@ -2708,8 +2669,23 @@ QString QSysInfo::productType()
version could not be determined, this function returns "unknown".
It will return the Android, iOS, \macos, Windows full-product
- versions on those systems. In particular, on OS X, iOS and Windows, the
- returned string is similar to the macVersion() or windowsVersion() enums.
+ versions on those systems.
+
+ Typical returned values are (note: list not exhaustive):
+ \list
+ \li "2016.09" (Amazon Linux AMI 2016.09)
+ \li "7.1" (Android Nougat)
+ \li "25" (Fedora 25)
+ \li "10.1" (iOS 10.1)
+ \li "10.12" (macOS Sierra)
+ \li "10.0" (tvOS 10)
+ \li "16.10" (Ubuntu 16.10)
+ \li "3.1" (watchOS 3.1)
+ \li "7 SP 1" (Windows 7 Service Pack 1)
+ \li "8.1" (Windows 8.1)
+ \li "10" (Windows 10)
+ \li "Server 2016" (Windows Server 2016)
+ \endlist
On Linux systems, it will try to determine the distribution version and will
return that. This is also done on Debian/kFreeBSD, so this function will
@@ -2726,20 +2702,17 @@ QString QSysInfo::productType()
*/
QString QSysInfo::productVersion()
{
-#if defined(Q_OS_MAC)
- const QAppleOperatingSystemVersion version = qt_apple_os_version();
- return QString::number(version.major) + QLatin1Char('.') + QString::number(version.minor);
+#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN)
+ const auto version = QOperatingSystemVersion::current();
+ return QString::number(version.majorVersion()) + QLatin1Char('.') + QString::number(version.minorVersion());
#elif defined(Q_OS_WIN)
- const char *version = winVer_helper();
+ const char *version = osVer_helper();
if (version) {
const QLatin1Char spaceChar(' ');
return QString::fromLatin1(version).remove(spaceChar).toLower() + winSp_helper().remove(spaceChar).toLower();
}
// fall through
-// Android should not fall through to the Unix code
-#elif defined(Q_OS_ANDROID)
- return QJNIObjectPrivate::getStaticObjectField("android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString();
#elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX
QUnixOSVersion unixOsVersion;
findUnixOsVersion(unixOsVersion);
@@ -2767,44 +2740,23 @@ QString QSysInfo::productVersion()
*/
QString QSysInfo::prettyProductName()
{
-#if defined(Q_OS_IOS)
- return QLatin1String("iOS ") + productVersion();
-#elif defined(Q_OS_TVOS)
- return QLatin1String("tvOS ") + productVersion();
-#elif defined(Q_OS_WATCHOS)
- return QLatin1String("watchOS ") + productVersion();
-#elif defined(Q_OS_MACOS)
- const QAppleOperatingSystemVersion version = qt_apple_os_version();
- const char *name = osxVer_helper(version);
- if (name) {
- return (version.major == 10 && version.minor < 12
- ? QLatin1String("OS X ")
- : QLatin1String("macOS "))
- + QLatin1String(name)
- + QLatin1String(" (") + QString::number(version.major)
- + QLatin1Char('.') + QString::number(version.minor)
- + QLatin1Char(')');
- } else {
- return QLatin1String("macOS ")
- + QString::number(version.major) + QLatin1Char('.')
- + QString::number(version.minor);
- }
-#elif defined(Q_OS_WINPHONE)
- return QLatin1String("Windows Phone ") + QLatin1String(winVer_helper());
-#elif defined(Q_OS_WIN)
- const char *name = winVer_helper();
- const OSVERSIONINFOEX osver = winOsVersion();
+#if defined(Q_OS_WINPHONE)
+ return QLatin1String("Windows Phone ") + QLatin1String(osVer_helper());
+#elif defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN)
+ const auto version = QOperatingSystemVersion::current();
+ const char *name = osVer_helper(version);
if (name)
- return QLatin1String("Windows ") + QLatin1String(name) + winSp_helper()
- + QLatin1String(" (") + QString::number(osver.dwMajorVersion)
- + QLatin1Char('.') + QString::number(osver.dwMinorVersion)
+ return version.name() + QLatin1Char(' ') + QLatin1String(name)
+# if defined(Q_OS_WIN)
+ + winSp_helper()
+# endif
+ + QLatin1String(" (") + QString::number(version.majorVersion())
+ + QLatin1Char('.') + QString::number(version.minorVersion())
+ QLatin1Char(')');
- else
- return QLatin1String("Windows ")
- + QString::number(osver.dwMajorVersion) + QLatin1Char('.')
- + QString::number(osver.dwMinorVersion);
-#elif defined(Q_OS_ANDROID)
- return QLatin1String("Android ") + productVersion();
+ else
+ return version.name() + QLatin1Char(' ')
+ + QString::number(version.majorVersion()) + QLatin1Char('.')
+ + QString::number(version.minorVersion());
#elif defined(Q_OS_HAIKU)
return QLatin1String("Haiku ") + productVersion();
#elif defined(Q_OS_UNIX)
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 1737f58c87..4354c85bfe 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -44,6 +44,8 @@
#ifdef __cplusplus
# include <type_traits>
# include <cstddef>
+# include <type_traits>
+# include <utility>
#endif
#include <stddef.h>
@@ -917,17 +919,34 @@ QT_WARNING_DISABLE_MSVC(4530) /* C++ exception handler used, but unwind semantic
#ifndef QT_NO_FOREACH
+namespace QtPrivate {
+
template <typename T>
class QForeachContainer {
QForeachContainer &operator=(const QForeachContainer &) Q_DECL_EQ_DELETE;
public:
QForeachContainer(const T &t) : c(t) {}
QForeachContainer(T &&t) : c(std::move(t)) {}
+ QForeachContainer(const QForeachContainer &other)
+ : c(other.c),
+ i(c.begin()),
+ e(c.end()),
+ control(other.control)
+ {
+ }
+
const T c;
typename T::const_iterator i = c.begin(), e = c.end();
int control = 1;
};
+template<typename T>
+QForeachContainer<typename std::decay<T>::type> qMakeForeachContainer(T &&t)
+{
+ return QForeachContainer<typename std::decay<T>::type>(std::forward<T>(t));
+}
+
+}
// Explanation of the control word:
// - it's initialized to 1
// - that means both the inner and outer loops start
@@ -938,7 +957,7 @@ public:
// - if there was a break inside the inner loop, it will exit with control still
// set to 1; in that case, the outer loop will invert it to 0 and will exit too
#define Q_FOREACH(variable, container) \
-for (QForeachContainer<typename std::remove_reference<decltype(container)>::type> _container_((container)); \
+for (auto _container_ = QtPrivate::qMakeForeachContainer(container); \
_container_.control && _container_.i != _container_.e; \
++_container_.i, _container_.control ^= 1) \
for (variable = *_container_.i; _container_.control; _container_.control = 0)
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index a30344995e..873a36f4a6 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -505,6 +505,7 @@ public:
AA_SynthesizeMouseForUnhandledTabletEvents = 24,
AA_CompressHighFrequencyEvents = 25,
AA_DontCheckOpenGLContextThreadAffinity = 26,
+ AA_DisableShaderDiskCache = 27,
// Add new attributes before this line
AA_AttributeCount
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 250195a512..64f0b5e1da 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -257,6 +257,15 @@
\l{QOpenGLContext::makeCurrent}{makeCurrent()}. This value has been
added in Qt 5.8.
+ \value AA_DisableShaderDiskCache Disables caching of shader program binaries
+ on disk. By default Qt Quick, QPainter's OpenGL backend, and any
+ application using QOpenGLShaderProgram with one of its
+ \e addCacheableShaderFromSource overloads will employ a disk-based
+ \l{Caching Program Binaries}{program binary cache} in either the shared
+ or per-process cache storage location, on systems that support
+ \e glProgramBinary(). In the unlikely event of this being problematic,
+ set this attribute to disable all disk-based caching of shaders.
+
The following values are obsolete:
\value AA_ImmediateWidgetCreation This attribute is no longer fully
diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp
new file mode 100644
index 0000000000..fb1ada905c
--- /dev/null
+++ b/src/corelib/global/qoperatingsystemversion.cpp
@@ -0,0 +1,439 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qoperatingsystemversion.h"
+#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
+#include "qoperatingsystemversion_p.h"
+#endif
+
+#include <qversionnumber.h>
+
+#if defined(Q_OS_ANDROID)
+#include <private/qjni_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QOperatingSystemVersion
+ \inmodule QtCore
+ \since 5.9
+ \brief The QOperatingSystemVersion class provides information about the operating system version.
+
+ Unlike other version functions in QSysInfo, QOperatingSystemVersion provides access to the full
+ version number that \a developers typically use to vary behavior or determine whether to enable
+ APIs or features based on the operating system version (as opposed to the kernel version number
+ or marketing version).
+
+ This class is also a complete replacement for QSysInfo::macVersion and QSysInfo::windowsVersion,
+ additionally providing access to the third (micro) version number component.
+
+ Presently, Android, Apple Platforms (iOS, macOS, tvOS, and watchOS), and Windows are supported.
+
+ The \a majorVersion(), \a minorVersion(), and \a microVersion() functions return the parts of
+ the operating system version number based on:
+
+ \table
+ \header \li Platforms \li Value
+ \row \li Android \li result of parsing
+ \l{https://developer.android.com/reference/android/os/Build.VERSION.html#RELEASE}{android.os.Build.VERSION.RELEASE}
+ using QVersionNumber, with a fallback to
+ \l{https://developer.android.com/reference/android/os/Build.VERSION.html#SDK_INT}{android.os.Build.VERSION.SDK_INT}
+ to determine the major and minor version component if the former fails
+ \row \li Apple Platforms \li majorVersion, minorVersion, and patchVersion from
+ \l{https://developer.apple.com/reference/foundation/nsprocessinfo/1410906-operatingsystemversion?language=objc}{NSProcessInfo.operatingSystemVersion}
+ \row \li Windows \li dwMajorVersion, dwMinorVersion, and dwBuildNumber from
+ \l{https://msdn.microsoft.com/en-us/library/mt723418.aspx}{RtlGetVersion} -
+ note that this function ALWAYS return the version number of the underlying operating system,
+ as opposed to the shim underneath GetVersionEx that hides the real version number
+ if the application is not manifested for that version of the OS
+ \endtable
+*/
+
+/*!
+ \enum QOperatingSystemVersion::OSType
+
+ This enum provides symbolic names for the various operating
+ system families supported by QOperatingSystemVersion.
+
+ \value Android The Google Android operating system.
+ \value IOS The Apple iOS operating system.
+ \value MacOS The Apple macOS operating system.
+ \value TvOS The Apple tvOS operating system.
+ \value WatchOS The Apple watchOS operating system.
+ \value Windows The Microsoft Windows operating system (in both Win32 and WinRT environments).
+
+ \value Unknown An unknown or unsupported operating system.
+*/
+
+/*!
+ \fn QOperatingSystemVersion::QOperatingSystemVersion(int maj, int min, int mic)
+
+ Constructs a QOperatingSystemVersion consisting of the OS type \a os, and
+ major, minor, and micro version numbers \a maj, \a min and \a mic, respectively.
+*/
+
+/*!
+ \fn QOperatingSystemVersion QOperatingSystemVersion::current()
+
+ Returns a QOperatingSystemVersion indicating the current OS and its version number.
+*/
+#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
+QOperatingSystemVersion QOperatingSystemVersion::current()
+{
+ QOperatingSystemVersion version;
+ version.m_os = currentType();
+#if defined(Q_OS_ANDROID)
+#ifndef QT_BOOTSTRAPPED
+ const QVersionNumber v = QVersionNumber::fromString(QJNIObjectPrivate::getStaticObjectField(
+ "android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString());
+ if (!v.isNull()) {
+ version.m_major = v.majorVersion();
+ version.m_minor = v.minorVersion();
+ version.m_micro = v.microVersion();
+ return version;
+ }
+#endif
+
+ version.m_major = -1;
+ version.m_minor = -1;
+
+ static const int versions[][2] = {
+ { 1, 0 }, // API level 1
+ { 1, 1 }, // API level 2
+ { 1, 5 }, // API level 3
+ { 1, 6 }, // API level 4
+ { 2, 0 }, // API level 5
+ { 2, 0 }, // API level 6
+ { 2, 1 }, // API level 7
+ { 2, 2 }, // API level 8
+ { 2, 3 }, // API level 9
+ { 2, 3 }, // API level 10
+ { 3, 0 }, // API level 11
+ { 3, 1 }, // API level 12
+ { 3, 2 }, // API level 13
+ { 4, 0 }, // API level 14
+ { 4, 0 }, // API level 15
+ { 4, 1 }, // API level 16
+ { 4, 2 }, // API level 17
+ { 4, 3 }, // API level 18
+ { 4, 4 }, // API level 19
+ { 4, 4 }, // API level 20
+ { 5, 0 }, // API level 21
+ { 5, 1 }, // API level 22
+ { 6, 0 }, // API level 23
+ { 7, 0 }, // API level 24
+ { 7, 1 }, // API level 25
+ };
+
+ // This will give us at least the first 2 version components
+ const size_t versionIdx = size_t(QJNIObjectPrivate::getStaticField<jint>("android/os/Build$VERSION", "SDK_INT")) - 1;
+ if (versionIdx < sizeof(versions) / sizeof(versions[0])) {
+ version.m_major = versions[versionIdx][0];
+ version.m_minor = versions[versionIdx][1];
+ }
+
+ // API level 6 was exactly version 2.0.1
+ version.m_micro = versionIdx == 5 ? 1 : -1;
+#else
+ version.m_major = -1;
+ version.m_minor = -1;
+ version.m_micro = -1;
+#endif
+ return version;
+}
+#endif
+
+static inline int compareVersionComponents(int lhs, int rhs)
+{
+ return lhs >= 0 && rhs >= 0 ? lhs - rhs : 0;
+}
+
+/*!
+ \fn int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
+ const QOperatingSystemVersion &v2)
+
+ Compares \a v1 with \a v2 and returns an integer less than, equal to, or
+ greater than zero, depending on whether \a v1 is less than, equal to, or
+ greater than \a v2, respectively.
+
+ Comparisons are performed by comparing the version number components of
+ \a v1 and \a v2.
+
+ \note This function cannot take the OS type into account; you should use
+ the overloaded comparison operators to compare QOperatingSystemVersions
+ in a safe manner.
+*/
+int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1, const QOperatingSystemVersion &v2)
+{
+ if (v1.m_major == v2.m_major) {
+ if (v1.m_minor == v2.m_minor) {
+ return compareVersionComponents(v1.m_micro, v2.m_micro);
+ }
+ return compareVersionComponents(v1.m_minor, v2.m_minor);
+ }
+ return compareVersionComponents(v1.m_major, v2.m_major);
+}
+
+#ifndef QT_BOOTSTRAPPED
+/*!
+ \fn QOperatingSystemVersion QOperatingSystemVersion::fromVersionNumber(const QVersionNumber &version,
+ QOperatingSystemVersion::OSType os)
+
+ Returns a QOperatingSystemVersion consisting of the OS type \a os and version number \a version.
+*/
+QOperatingSystemVersion QOperatingSystemVersion::fromVersionNumber(const QVersionNumber &version,
+ QOperatingSystemVersion::OSType os)
+{
+ return QOperatingSystemVersion(os, version.majorVersion(), version.minorVersion(), version.microVersion());
+}
+
+/*!
+ \fn QOperatingSystemVersion QOperatingSystemVersion::toVersionNumber() const
+
+ Returns the QOperatingSystemVersion's version number as a QVersionNumber.
+*/
+QVersionNumber QOperatingSystemVersion::toVersionNumber() const
+{
+ return QVersionNumber(m_major, m_minor, m_micro);
+}
+#endif
+
+/*!
+ \fn int QOperatingSystemVersion::majorVersion() const
+
+ Returns the major version number, that is, the first segment of the operating system's version number.
+
+ See the main class documentation for what the major version number is on a given operating system.
+
+ -1 indicates an unknown or absent version number component.
+
+ \sa minorVersion(), microVersion()
+*/
+
+/*!
+ \fn int QOperatingSystemVersion::minorVersion() const
+
+ Returns the minor version number, that is, the second segment of the operating system's version number.
+
+ See the main class documentation for what the minor version number is on a given operating system.
+
+ -1 indicates an unknown or absent version number component.
+
+ \sa majorVersion(), macro()
+*/
+
+/*!
+ \fn int QOperatingSystemVersion::microVersion() const
+
+ Returns the micro version number, that is, the third segment of the operating system's version number.
+
+ See the main class documentation for what the micro version number is on a given operating system.
+
+ -1 indicates an unknown or absent version number component.
+
+ \sa majorVersion(), minorVersion()
+*/
+
+/*!
+ \fn QOperatingSystemVersion::OSType QOperatingSystemVersion::type() const
+
+ Returns the OS type identified by the QOperatingSystemVersion.
+
+ \sa typeName()
+*/
+
+/*!
+ \fn QString QOperatingSystemVersion::name() const
+
+ Returns a string representation of the OS type identified by the QOperatingSystemVersion.
+
+ \sa type()
+*/
+QString QOperatingSystemVersion::name() const
+{
+ switch (type()) {
+ case QOperatingSystemVersion::Windows:
+ return QStringLiteral("Windows");
+ case QOperatingSystemVersion::MacOS: {
+ if (majorVersion() < 10)
+ return QStringLiteral("Mac OS");
+ if (majorVersion() == 10 && minorVersion() < 8)
+ return QStringLiteral("Mac OS X");
+ if (majorVersion() == 10 && minorVersion() < 12)
+ return QStringLiteral("OS X");
+ return QStringLiteral("macOS");
+ }
+ case QOperatingSystemVersion::IOS: {
+ if (majorVersion() < 4)
+ return QStringLiteral("iPhone OS");
+ return QStringLiteral("iOS");
+ }
+ case QOperatingSystemVersion::TvOS:
+ return QStringLiteral("tvOS");
+ case QOperatingSystemVersion::WatchOS:
+ return QStringLiteral("watchOS");
+ case QOperatingSystemVersion::Android:
+ return QStringLiteral("Android");
+ case QOperatingSystemVersion::Unknown:
+ default:
+ return QString();
+ }
+}
+
+/*!
+ \variable QOperatingSystemVersion::Windows7
+ \brief a version corresponding to Windows 7 (version 6.1).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::Windows7 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 1);
+
+/*!
+ \variable QOperatingSystemVersion::Windows8
+ \brief a version corresponding to Windows 8 (version 6.2).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::Windows8 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 2);
+
+/*!
+ \variable QOperatingSystemVersion::Windows8_1
+ \brief a version corresponding to Windows 8.1 (version 6.3).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::Windows8_1 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 3);
+
+/*!
+ \variable QOperatingSystemVersion::Windows10
+ \brief a version corresponding to Windows 10 (version 10.0).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::Windows10 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10);
+
+/*!
+ \variable QOperatingSystemVersion::OSXMavericks
+ \brief a version corresponding to OS X Mavericks (version 10.9).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::OSXMavericks = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 9);
+
+/*!
+ \variable QOperatingSystemVersion::OSXYosemite
+ \brief a version corresponding to OS X Yosemite (version 10.10).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::OSXYosemite = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 10);
+
+/*!
+ \variable QOperatingSystemVersion::OSXElCapitan
+ \brief a version corresponding to OS X El Capitan (version 10.11).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::OSXElCapitan = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 11);
+
+/*!
+ \variable QOperatingSystemVersion::MacOSSierra
+ \brief a version corresponding to macOS Sierra (version 10.12).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::MacOSSierra = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 12);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidJellyBean
+ \brief a version corresponding to Android Jelly Bean (version 4.1, API level 16).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidJellyBean = QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 1);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidJellyBean_MR1
+ \brief a version corresponding to Android Jelly Bean, maintenance release 1 (version 4.2, API level 17).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidJellyBean_MR1 = QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 2);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidJellyBean_MR2
+ \brief a version corresponding to Android Jelly Bean, maintenance release 2 (version 4.3, API level 18).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidJellyBean_MR2 = QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 3);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidKitKat
+ \brief a version corresponding to Android KitKat (versions 4.4 & 4.4W, API levels 19 & 20).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidKitKat = QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 4);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidLollipop
+ \brief a version corresponding to Android Lollipop (version 5.0, API level 21).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidLollipop = QOperatingSystemVersion(QOperatingSystemVersion::Android, 5, 0);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidLollipop_MR1
+ \brief a version corresponding to Android Lollipop, maintenance release 1 (version 5.1, API level 22).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidLollipop_MR1 = QOperatingSystemVersion(QOperatingSystemVersion::Android, 5, 1);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidMarshmallow
+ \brief a version corresponding to Android Marshmallow (version 6.0, API level 23).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidMarshmallow = QOperatingSystemVersion(QOperatingSystemVersion::Android, 6, 0);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidNougat
+ \brief a version corresponding to Android Nougat (version 7.0, API level 24).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat = QOperatingSystemVersion(QOperatingSystemVersion::Android, 7, 0);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidNougat_MR1
+ \brief a version corresponding to Android Nougat, maintenance release 1 (version 7.0, API level 25).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat_MR1 = QOperatingSystemVersion(QOperatingSystemVersion::Android, 7, 1);
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qoperatingsystemversion.h b/src/corelib/global/qoperatingsystemversion.h
new file mode 100644
index 0000000000..ef999c6ae4
--- /dev/null
+++ b/src/corelib/global/qoperatingsystemversion.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qglobal.h>
+
+#ifndef QOPERATINGSYSTEMVERSION_H
+#define QOPERATINGSYSTEMVERSION_H
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class QVersionNumber;
+
+class Q_CORE_EXPORT QOperatingSystemVersion
+{
+public:
+ enum OSType {
+ Unknown = 0,
+ Windows,
+ MacOS,
+ IOS,
+ TvOS,
+ WatchOS,
+ Android
+ };
+
+ static const QOperatingSystemVersion Windows7;
+ static const QOperatingSystemVersion Windows8;
+ static const QOperatingSystemVersion Windows8_1;
+ static const QOperatingSystemVersion Windows10;
+
+ static const QOperatingSystemVersion OSXMavericks;
+ static const QOperatingSystemVersion OSXYosemite;
+ static const QOperatingSystemVersion OSXElCapitan;
+ static const QOperatingSystemVersion MacOSSierra;
+
+ static const QOperatingSystemVersion AndroidJellyBean;
+ static const QOperatingSystemVersion AndroidJellyBean_MR1;
+ static const QOperatingSystemVersion AndroidJellyBean_MR2;
+ static const QOperatingSystemVersion AndroidKitKat;
+ static const QOperatingSystemVersion AndroidLollipop;
+ static const QOperatingSystemVersion AndroidLollipop_MR1;
+ static const QOperatingSystemVersion AndroidMarshmallow;
+ static const QOperatingSystemVersion AndroidNougat;
+ static const QOperatingSystemVersion AndroidNougat_MR1;
+
+ QOperatingSystemVersion(const QOperatingSystemVersion &other) = default;
+ Q_DECL_CONSTEXPR QOperatingSystemVersion(OSType osType, int vmajor, int vminor = -1, int vmicro = -1)
+ : m_os(osType), m_major(vmajor), m_minor(vminor), m_micro(vmicro) { }
+
+ static QOperatingSystemVersion current();
+
+ static int compare(const QOperatingSystemVersion &v1, const QOperatingSystemVersion &v2);
+
+ QOperatingSystemVersion fromVersionNumber(const QVersionNumber &version, OSType os);
+ QVersionNumber toVersionNumber() const;
+
+ Q_DECL_CONSTEXPR int majorVersion() const { return m_major; }
+ Q_DECL_CONSTEXPR int minorVersion() const { return m_minor; }
+ Q_DECL_CONSTEXPR int microVersion() const { return m_micro; }
+
+ Q_DECL_CONSTEXPR OSType type() const { return m_os; }
+ QString name() const;
+
+private:
+ QOperatingSystemVersion() = default;
+ OSType m_os;
+ int m_major;
+ int m_minor;
+ int m_micro;
+};
+
+inline bool operator>(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
+{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) > 0; }
+
+inline bool operator>=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
+{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) >= 0; }
+
+inline bool operator<(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
+{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) < 0; }
+
+inline bool operator<=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
+{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) <= 0; }
+
+inline bool operator==(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
+{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) == 0; }
+
+inline bool operator!=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
+{ return !(lhs == rhs); }
+
+QT_END_NAMESPACE
+
+#endif // QOPERATINGSYSTEMVERSION_H
diff --git a/src/corelib/global/qoperatingsystemversion_darwin.mm b/src/corelib/global/qoperatingsystemversion_darwin.mm
new file mode 100644
index 0000000000..3dd007cbb3
--- /dev/null
+++ b/src/corelib/global/qoperatingsystemversion_darwin.mm
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qoperatingsystemversion_p.h"
+#import <Foundation/Foundation.h>
+
+#ifdef Q_OS_IOS
+#import <UIKit/UIKit.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+typedef qint16 (*GestaltFunction)(quint32 selector, qint32 *response);
+
+QOperatingSystemVersion QOperatingSystemVersion::current()
+{
+ QOperatingSystemVersion v;
+ v.m_os = currentType();
+ v.m_major = -1;
+ v.m_minor = -1;
+ v.m_micro = -1;
+#if QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_8_0) || defined(Q_OS_TVOS) || defined(Q_OS_WATCHOS)
+ if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) {
+ NSOperatingSystemVersion osv = NSProcessInfo.processInfo.operatingSystemVersion;
+ v.m_major = osv.majorVersion;
+ v.m_minor = osv.minorVersion;
+ v.m_micro = osv.patchVersion;
+ return v;
+ }
+#endif
+ // Use temporary variables so we can return 0.0.0 (unknown version)
+ // in case of an error partway through determining the OS version
+ qint32 major = 0, minor = 0, patch = 0;
+#if QT_MACOS_IOS_DEPLOYMENT_TARGET_BELOW(__MAC_10_10, __IPHONE_8_0)
+#if defined(Q_OS_IOS)
+ @autoreleasepool {
+ NSArray *parts = [UIDevice.currentDevice.systemVersion componentsSeparatedByString:@"."];
+ major = parts.count > 0 ? [[parts objectAtIndex:0] intValue] : 0;
+ minor = parts.count > 1 ? [[parts objectAtIndex:1] intValue] : 0;
+ patch = parts.count > 2 ? [[parts objectAtIndex:2] intValue] : 0;
+ }
+#elif defined(Q_OS_MACOS)
+ static GestaltFunction pGestalt = 0;
+ if (!pGestalt) {
+ CFBundleRef b = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreServices"));
+ pGestalt = reinterpret_cast<GestaltFunction>(CFBundleGetFunctionPointerForName(b,
+ CFSTR("Gestalt")));
+ }
+ if (!pGestalt)
+ return v;
+ if (pGestalt('sys1', &major) != 0)
+ return v;
+ if (pGestalt('sys2', &minor) != 0)
+ return v;
+ if (pGestalt('sys3', &patch) != 0)
+ return v;
+#endif
+#endif
+ v.m_major = major;
+ v.m_minor = minor;
+ v.m_micro = patch;
+ return v;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qoperatingsystemversion_p.h b/src/corelib/global/qoperatingsystemversion_p.h
new file mode 100644
index 0000000000..78d0daf0c6
--- /dev/null
+++ b/src/corelib/global/qoperatingsystemversion_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPERATINGSYSTEMVERSION_P_H
+#define QOPERATINGSYSTEMVERSION_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 "qoperatingsystemversion.h"
+
+#ifdef Q_OS_WIN
+#include <qt_windows.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN
+OSVERSIONINFOEX qWindowsVersionInfo();
+#endif
+
+static inline QOperatingSystemVersion::OSType currentType()
+{
+#if defined(Q_OS_WIN)
+ return QOperatingSystemVersion::Windows;
+#elif defined(Q_OS_MACOS)
+ return QOperatingSystemVersion::MacOS;
+#elif defined(Q_OS_IOS)
+ return QOperatingSystemVersion::IOS;
+#elif defined(Q_OS_TVOS)
+ return QOperatingSystemVersion::TvOS;
+#elif defined(Q_OS_WATCHOS)
+ return QOperatingSystemVersion::WatchOS;
+#elif defined(Q_OS_ANDROID)
+ return QOperatingSystemVersion::Android;
+#else
+ return QOperatingSystemVersion::Unknown;
+#endif
+}
+
+QT_END_NAMESPACE
+
+#endif // QOPERATINGSYSTEMVERSION_P_H
diff --git a/src/corelib/global/qoperatingsystemversion_win.cpp b/src/corelib/global/qoperatingsystemversion_win.cpp
new file mode 100644
index 0000000000..060ca2f7da
--- /dev/null
+++ b/src/corelib/global/qoperatingsystemversion_win.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qoperatingsystemversion_p.h"
+#include <qt_windows.h>
+#include <qbytearray.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WINRT
+static inline HMODULE moduleHandleForFunction(LPCVOID address)
+{
+ // This is a widely used, decades-old technique for retrieving the handle
+ // of a module and is effectively equivalent to GetModuleHandleEx
+ // (which is unavailable on WinRT)
+ MEMORY_BASIC_INFORMATION mbi = { 0, 0, 0, 0, 0, 0, 0 };
+ if (VirtualQuery(address, &mbi, sizeof(mbi)) == 0)
+ return 0;
+ return reinterpret_cast<HMODULE>(mbi.AllocationBase);
+}
+#endif
+
+static inline OSVERSIONINFOEX determineWinOsVersion()
+{
+ OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0};
+
+#define GetProcAddressA GetProcAddress
+
+ // GetModuleHandle is not supported in WinRT and linking to it at load time
+ // will not pass the Windows App Certification Kit... but it exists and is functional,
+ // so use some unusual but widely used techniques to get a pointer to it
+#ifdef Q_OS_WINRT
+ // 1. Get HMODULE of kernel32.dll, using the address of some function exported by that DLL
+ HMODULE kernelModule = moduleHandleForFunction(reinterpret_cast<LPCVOID>(VirtualQuery));
+ if (Q_UNLIKELY(!kernelModule))
+ return result;
+
+ // 2. Get pointer to GetModuleHandle so we can then load other arbitrary modules (DLLs)
+ typedef HMODULE(WINAPI *GetModuleHandleFunction)(LPCWSTR);
+ GetModuleHandleFunction pGetModuleHandle = reinterpret_cast<GetModuleHandleFunction>(
+ GetProcAddressA(kernelModule, "GetModuleHandleW"));
+ if (Q_UNLIKELY(!pGetModuleHandle))
+ return result;
+#else
+#define pGetModuleHandle GetModuleHandleW
+#endif
+
+#ifndef Q_OS_WINCE
+ HMODULE ntdll = pGetModuleHandle(L"ntdll.dll");
+ if (Q_UNLIKELY(!ntdll))
+ return result;
+
+ // NTSTATUS is not defined on WinRT
+ typedef LONG NTSTATUS;
+ typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO);
+
+ // RtlGetVersion is documented public API but we must load it dynamically
+ // because linking to it at load time will not pass the Windows App Certification Kit
+ // https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx
+ RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(
+ GetProcAddressA(ntdll, "RtlGetVersion"));
+ if (Q_UNLIKELY(!pRtlGetVersion))
+ return result;
+
+ // GetVersionEx() has been deprecated in Windows 8.1 and will return
+ // only Windows 8 from that version on, so use the kernel API function.
+ pRtlGetVersion((LPOSVERSIONINFO) &result); // always returns STATUS_SUCCESS
+#else // !Q_OS_WINCE
+ GetVersionEx(&result);
+#endif
+ return result;
+}
+
+OSVERSIONINFOEX qWindowsVersionInfo()
+{
+ OSVERSIONINFOEX realResult = determineWinOsVersion();
+#ifdef QT_DEBUG
+ {
+ if (Q_UNLIKELY(qEnvironmentVariableIsSet("QT_WINVER_OVERRIDE"))) {
+ OSVERSIONINFOEX result = realResult;
+ result.dwMajorVersion = 0;
+ result.dwMinorVersion = 0;
+
+ // Erase any build number and service pack information
+ result.dwBuildNumber = 0;
+ result.szCSDVersion[0] = L'\0';
+ result.wServicePackMajor = 0;
+ result.wServicePackMinor = 0;
+
+ const QByteArray winVerOverride = qgetenv("QT_WINVER_OVERRIDE");
+ if (winVerOverride == "WINDOWS7" || winVerOverride == "2008_R2") {
+ result.dwMajorVersion = 6;
+ result.dwMinorVersion = 1;
+ } else if (winVerOverride == "WINDOWS8" || winVerOverride == "2012") {
+ result.dwMajorVersion = 6;
+ result.dwMinorVersion = 2;
+ } else if (winVerOverride == "WINDOWS8_1" || winVerOverride == "2012_R2") {
+ result.dwMajorVersion = 6;
+ result.dwMinorVersion = 3;
+ } else if (winVerOverride == "WINDOWS10" || winVerOverride == "2016") {
+ result.dwMajorVersion = 10;
+ } else {
+ return realResult;
+ }
+
+ if (winVerOverride == "2008_R2"
+ || winVerOverride == "2012"
+ || winVerOverride == "2012_R2"
+ || winVerOverride == "2016") {
+ // If the current host OS is a domain controller and the override OS
+ // is also a server type OS, preserve that information
+ if (result.wProductType == VER_NT_WORKSTATION)
+ result.wProductType = VER_NT_SERVER;
+ } else {
+ // Any other OS must be a workstation OS type
+ result.wProductType = VER_NT_WORKSTATION;
+ }
+ }
+ }
+#endif
+ return realResult;
+}
+
+QOperatingSystemVersion QOperatingSystemVersion::current()
+{
+ QOperatingSystemVersion v;
+ v.m_os = currentType();
+ const OSVERSIONINFOEX osv = qWindowsVersionInfo();
+ v.m_major = osv.dwMajorVersion;
+ v.m_minor = osv.dwMinorVersion;
+ v.m_micro = osv.dwBuildNumber;
+ return v;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h
index 23f412aa6a..3cbcfd3fc9 100644
--- a/src/corelib/global/qsysinfo.h
+++ b/src/corelib/global/qsysinfo.h
@@ -49,6 +49,23 @@ QT_BEGIN_NAMESPACE
System information
*/
+/*
+ * GCC (5-7) has a regression that causes it to emit wrong deprecated warnings:
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77849
+ *
+ * Try to work around it by defining our own macro.
+ */
+
+#ifdef QT_SYSINFO_DEPRECATED_X
+#error "QT_SYSINFO_DEPRECATED_X already defined"
+#endif
+
+#ifdef Q_CC_GNU
+#define QT_SYSINFO_DEPRECATED_X(x)
+#else
+#define QT_SYSINFO_DEPRECATED_X(x) QT_DEPRECATED_X(x)
+#endif
+
class QString;
class Q_CORE_EXPORT QSysInfo {
public:
@@ -79,7 +96,8 @@ public:
# endif
};
#endif
- enum WinVersion {
+#if QT_DEPRECATED_SINCE(5, 9)
+ enum QT_DEPRECATED_X("Use QOperatingSystemVersion") WinVersion {
WV_None = 0x0000,
WV_32s = 0x0001,
@@ -117,19 +135,25 @@ public:
WV_CE_6 = 0x0400,
WV_CE_based = 0x0f00
};
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
+QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
+QT_WARNING_DISABLE_INTEL(1478)
+QT_WARNING_DISABLE_MSVC(4996)
#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
- static const WinVersion WindowsVersion;
- static WinVersion windowsVersion();
+ QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion;
+ QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static WinVersion windowsVersion();
#else
- static const WinVersion WindowsVersion = WV_None;
- static WinVersion windowsVersion() { return WV_None; }
+ QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion = WV_None;
+ QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static WinVersion windowsVersion() { return WV_None; }
#endif
+QT_WARNING_POP
#define Q_MV_OSX(major, minor) (major == 10 ? minor + 2 : (major == 9 ? 1 : 0))
#define Q_MV_IOS(major, minor) (QSysInfo::MV_IOS | major << 4 | minor)
#define Q_MV_TVOS(major, minor) (QSysInfo::MV_TVOS | major << 4 | minor)
#define Q_MV_WATCHOS(major, minor) (QSysInfo::MV_WATCHOS | major << 4 | minor)
- enum MacVersion {
+ enum QT_DEPRECATED_X("Use QOperatingSystemVersion") MacVersion {
MV_None = 0xffff,
MV_Unknown = 0x0000,
@@ -198,13 +222,20 @@ public:
MV_WATCHOS_2_2 = Q_MV_WATCHOS(2, 2),
MV_WATCHOS_3_0 = Q_MV_WATCHOS(3, 0)
};
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
+QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
+QT_WARNING_DISABLE_INTEL(1478)
+QT_WARNING_DISABLE_MSVC(4996)
#if defined(Q_OS_MAC)
- static const MacVersion MacintoshVersion;
- static MacVersion macVersion();
+ QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const MacVersion MacintoshVersion;
+ QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static MacVersion macVersion();
#else
- static const MacVersion MacintoshVersion = MV_None;
- static MacVersion macVersion() { return MV_None; }
+ QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const MacVersion MacintoshVersion = MV_None;
+ QT_SYSINFO_DEPRECATED_X("Use QOperatingSystemVersion::current()") static MacVersion macVersion() { return MV_None; }
#endif
+QT_WARNING_POP
+#endif // QT_DEPRECATED_SINCE(5, 9)
static QString buildCpuArchitecture();
static QString currentCpuArchitecture();
@@ -219,5 +250,7 @@ public:
static QString machineHostName();
};
+#undef QT_SYSINFO_DEPRECATED_X
+
QT_END_NAMESPACE
#endif // QSYSINFO_H
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index ac58677b77..994ed88791 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -95,10 +95,11 @@ public:
Qt_5_6 = 17,
Qt_5_7 = Qt_5_6,
Qt_5_8 = Qt_5_7,
-#if QT_VERSION >= 0x050900
+ Qt_5_9 = Qt_5_8,
+#if QT_VERSION >= 0x050a00
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
- Qt_DefaultCompiledVersion = Qt_5_8
+ Qt_DefaultCompiledVersion = Qt_5_9
};
enum ByteOrder {
@@ -222,6 +223,98 @@ private:
QDataStream::Status oldStatus;
};
+template <typename Container>
+QDataStream &readArrayBasedContainer(QDataStream &s, Container &c)
+{
+ StreamStateSaver stateSaver(&s);
+
+ c.clear();
+ quint32 n;
+ s >> n;
+ c.reserve(n);
+ for (quint32 i = 0; i < n; ++i) {
+ typename Container::value_type t;
+ s >> t;
+ if (s.status() != QDataStream::Ok) {
+ c.clear();
+ break;
+ }
+ c.append(t);
+ }
+
+ return s;
+}
+
+template <typename Container>
+QDataStream &readListBasedContainer(QDataStream &s, Container &c)
+{
+ StreamStateSaver stateSaver(&s);
+
+ c.clear();
+ quint32 n;
+ s >> n;
+ for (quint32 i = 0; i < n; ++i) {
+ typename Container::value_type t;
+ s >> t;
+ if (s.status() != QDataStream::Ok) {
+ c.clear();
+ break;
+ }
+ c << t;
+ }
+
+ return s;
+}
+
+template <typename Container>
+QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
+{
+ StreamStateSaver stateSaver(&s);
+
+ c.clear();
+ quint32 n;
+ s >> n;
+ for (quint32 i = 0; i < n; ++i) {
+ typename Container::key_type k;
+ typename Container::mapped_type t;
+ s >> k >> t;
+ if (s.status() != QDataStream::Ok) {
+ c.clear();
+ break;
+ }
+ c.insertMulti(k, t);
+ }
+
+ return s;
+}
+
+template <typename Container>
+QDataStream &writeSequentialContainer(QDataStream &s, const Container &c)
+{
+ s << quint32(c.size());
+ for (const typename Container::value_type &t : c)
+ s << t;
+
+ return s;
+}
+
+template <typename Container>
+QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
+{
+ s << quint32(c.size());
+ // Deserialization should occur in the reverse order.
+ // Otherwise, value() will return the least recently inserted
+ // value instead of the most recently inserted one.
+ auto it = c.constEnd();
+ auto begin = c.constBegin();
+ while (it != begin) {
+ --it;
+ s << it.key() << it.value();
+ }
+
+ return s;
+}
+
} // QtPrivate namespace
/*****************************************************************************
@@ -265,209 +358,75 @@ inline QDataStream &QDataStream::operator<<(quint64 i)
{ return *this << qint64(i); }
template <typename T>
-QDataStream& operator>>(QDataStream& s, QList<T>& l)
+inline QDataStream &operator>>(QDataStream &s, QList<T> &l)
{
- QtPrivate::StreamStateSaver stateSaver(&s);
-
- l.clear();
- quint32 c;
- s >> c;
- l.reserve(c);
- for(quint32 i = 0; i < c; ++i)
- {
- T t;
- s >> t;
- if (s.status() != QDataStream::Ok) {
- l.clear();
- break;
- }
- l.append(t);
- }
-
- return s;
+ return QtPrivate::readArrayBasedContainer(s, l);
}
template <typename T>
-QDataStream& operator<<(QDataStream& s, const QList<T>& l)
+inline QDataStream &operator<<(QDataStream &s, const QList<T> &l)
{
- s << quint32(l.size());
- for (int i = 0; i < l.size(); ++i)
- s << l.at(i);
- return s;
+ return QtPrivate::writeSequentialContainer(s, l);
}
template <typename T>
-QDataStream& operator>>(QDataStream& s, QLinkedList<T>& l)
+inline QDataStream &operator>>(QDataStream &s, QLinkedList<T> &l)
{
- QtPrivate::StreamStateSaver stateSaver(&s);
-
- l.clear();
- quint32 c;
- s >> c;
- for(quint32 i = 0; i < c; ++i)
- {
- T t;
- s >> t;
- if (s.status() != QDataStream::Ok) {
- l.clear();
- break;
- }
- l.append(t);
- }
-
- return s;
+ return QtPrivate::readListBasedContainer(s, l);
}
template <typename T>
-QDataStream& operator<<(QDataStream& s, const QLinkedList<T>& l)
+inline QDataStream &operator<<(QDataStream &s, const QLinkedList<T> &l)
{
- s << quint32(l.size());
- typename QLinkedList<T>::ConstIterator it = l.constBegin();
- for(; it != l.constEnd(); ++it)
- s << *it;
- return s;
+ return QtPrivate::writeSequentialContainer(s, l);
}
template<typename T>
-QDataStream& operator>>(QDataStream& s, QVector<T>& v)
+inline QDataStream &operator>>(QDataStream &s, QVector<T> &v)
{
- QtPrivate::StreamStateSaver stateSaver(&s);
-
- v.clear();
- quint32 c;
- s >> c;
- v.resize(c);
- for(quint32 i = 0; i < c; ++i) {
- T t;
- s >> t;
- if (s.status() != QDataStream::Ok) {
- v.clear();
- break;
- }
- v[i] = t;
- }
-
- return s;
+ return QtPrivate::readArrayBasedContainer(s, v);
}
template<typename T>
-QDataStream& operator<<(QDataStream& s, const QVector<T>& v)
+inline QDataStream &operator<<(QDataStream &s, const QVector<T> &v)
{
- s << quint32(v.size());
- for (typename QVector<T>::const_iterator it = v.begin(); it != v.end(); ++it)
- s << *it;
- return s;
+ return QtPrivate::writeSequentialContainer(s, v);
}
template <typename T>
-QDataStream &operator>>(QDataStream &in, QSet<T> &set)
+inline QDataStream &operator>>(QDataStream &s, QSet<T> &set)
{
- QtPrivate::StreamStateSaver stateSaver(&in);
-
- set.clear();
- quint32 c;
- in >> c;
- for (quint32 i = 0; i < c; ++i) {
- T t;
- in >> t;
- if (in.status() != QDataStream::Ok) {
- set.clear();
- break;
- }
- set << t;
- }
-
- return in;
+ return QtPrivate::readListBasedContainer(s, set);
}
template <typename T>
-QDataStream& operator<<(QDataStream &out, const QSet<T> &set)
+inline QDataStream &operator<<(QDataStream &s, const QSet<T> &set)
{
- out << quint32(set.size());
- typename QSet<T>::const_iterator i = set.constBegin();
- while (i != set.constEnd()) {
- out << *i;
- ++i;
- }
- return out;
+ return QtPrivate::writeSequentialContainer(s, set);
}
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QHash<Key, T> &hash)
+inline QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash)
{
- QtPrivate::StreamStateSaver stateSaver(&in);
-
- hash.clear();
- quint32 n;
- in >> n;
-
- for (quint32 i = 0; i < n; ++i) {
- if (in.status() != QDataStream::Ok)
- break;
-
- Key k;
- T t;
- in >> k >> t;
- hash.insertMulti(k, t);
- }
-
- if (in.status() != QDataStream::Ok)
- hash.clear();
- return in;
+ return QtPrivate::readAssociativeContainer(s, hash);
}
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const QHash<Key, T>& hash)
+inline QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash)
{
- out << quint32(hash.size());
- typename QHash<Key, T>::ConstIterator it = hash.end();
- typename QHash<Key, T>::ConstIterator begin = hash.begin();
- while (it != begin) {
- --it;
- out << it.key() << it.value();
- }
- return out;
+ return QtPrivate::writeAssociativeContainer(s, hash);
}
-#ifdef Q_QDOC
+
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap<Key, T> &map)
-#else
-template <class aKey, class aT>
-Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap<aKey, aT> &map)
-#endif
+inline QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map)
{
- QtPrivate::StreamStateSaver stateSaver(&in);
-
- map.clear();
- quint32 n;
- in >> n;
-
- map.detach();
- for (quint32 i = 0; i < n; ++i) {
- if (in.status() != QDataStream::Ok)
- break;
-
- aKey key;
- aT value;
- in >> key >> value;
- map.insertMulti(key, value);
- }
- if (in.status() != QDataStream::Ok)
- map.clear();
- return in;
+ return QtPrivate::readAssociativeContainer(s, map);
}
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const QMap<Key, T> &map)
+inline QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map)
{
- out << quint32(map.size());
- typename QMap<Key, T>::ConstIterator it = map.end();
- typename QMap<Key, T>::ConstIterator begin = map.begin();
- while (it != begin) {
- --it;
- out << it.key() << it.value();
- }
- return out;
+ return QtPrivate::writeAssociativeContainer(s, map);
}
#ifndef QT_NO_DATASTREAM
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index cdb64d08e1..663d9cd61d 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -38,7 +38,7 @@
****************************************************************************/
#include "qfilesystemengine_p.h"
-
+#include "qoperatingsystemversion.h"
#include "qplatformdefs.h"
#include "qsysinfo.h"
#include "private/qabstractfileengine_p.h"
@@ -637,7 +637,7 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
FILE_SHARE_READ, OPEN_EXISTING, NULL);
#endif // Q_OS_WINRT
if (handle) {
- result = QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS8 ?
+ result = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ?
fileIdWin8(handle) : fileId(handle);
CloseHandle(handle);
}
diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp
index 2ce7bd7a4b..9140118872 100644
--- a/src/corelib/io/qfilesystemiterator_win.cpp
+++ b/src/corelib/io/qfilesystemiterator_win.cpp
@@ -39,6 +39,7 @@
#include "qfilesystemiterator_p.h"
#include "qfilesystemengine_p.h"
+#include "qoperatingsystemversion.h"
#include "qplatformdefs.h"
#include "qvector.h"
@@ -93,7 +94,7 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa
haveData = true;
int infoLevel = 0 ; // FindExInfoStandard;
DWORD dwAdditionalFlags = 0;
- if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows7) {
dwAdditionalFlags = 2; // FIND_FIRST_EX_LARGE_FETCH
infoLevel = 1 ; // FindExInfoBasic;
}
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index a1d90c76f4..612b3fa57c 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -64,6 +64,9 @@
# include "qfilesystemwatcher_fsevents_p.h"
#endif
+#include <algorithm>
+#include <iterator>
+
QT_BEGIN_NAMESPACE
QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject *parent)
@@ -102,6 +105,17 @@ void QFileSystemWatcherPrivate::init()
SIGNAL(directoryChanged(QString,bool)),
q,
SLOT(_q_directoryChanged(QString,bool)));
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ QObject::connect(static_cast<QWindowsFileSystemWatcherEngine *>(native),
+ &QWindowsFileSystemWatcherEngine::driveLockForRemoval,
+ q, [this] (const QString &p) { _q_winDriveLockForRemoval(p); });
+ QObject::connect(static_cast<QWindowsFileSystemWatcherEngine *>(native),
+ &QWindowsFileSystemWatcherEngine::driveLockForRemovalFailed,
+ q, [this] (const QString &p) { _q_winDriveLockForRemovalFailed(p); });
+ QObject::connect(static_cast<QWindowsFileSystemWatcherEngine *>(native),
+ &QWindowsFileSystemWatcherEngine::driveRemoved,
+ q, [this] (const QString &p) { _q_winDriveRemoved(p); });
+#endif // !Q_OS_WINRT
}
}
@@ -146,7 +160,46 @@ void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool re
emit q->directoryChanged(path, QFileSystemWatcher::QPrivateSignal());
}
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+
+void QFileSystemWatcherPrivate::_q_winDriveLockForRemoval(const QString &path)
+{
+ // Windows: Request to lock a (removable/USB) drive for removal, release
+ // its paths under watch, temporarily storing them should the lock fail.
+ Q_Q(QFileSystemWatcher);
+ QStringList pathsToBeRemoved;
+ auto pred = [&path] (const QString &f) { return !f.startsWith(path, Qt::CaseInsensitive); };
+ std::remove_copy_if(files.cbegin(), files.cend(),
+ std::back_inserter(pathsToBeRemoved), pred);
+ std::remove_copy_if(directories.cbegin(), directories.cend(),
+ std::back_inserter(pathsToBeRemoved), pred);
+ if (!pathsToBeRemoved.isEmpty()) {
+ q->removePaths(pathsToBeRemoved);
+ temporarilyRemovedPaths.insert(path.at(0), pathsToBeRemoved);
+ }
+}
+
+void QFileSystemWatcherPrivate::_q_winDriveLockForRemovalFailed(const QString &path)
+{
+ // Windows: Request to lock a (removable/USB) drive failed (blocked by other
+ // application), restore the watched paths.
+ Q_Q(QFileSystemWatcher);
+ if (!path.isEmpty()) {
+ const auto it = temporarilyRemovedPaths.find(path.at(0));
+ if (it != temporarilyRemovedPaths.end()) {
+ q->addPaths(it.value());
+ temporarilyRemovedPaths.erase(it);
+ }
+ }
+}
+void QFileSystemWatcherPrivate::_q_winDriveRemoved(const QString &path)
+{
+ // Windows: Drive finally removed, clear out paths stored in lock request.
+ if (!path.isEmpty())
+ temporarilyRemovedPaths.remove(path.at(0));
+}
+#endif // Q_OS_WIN && !Q_OS_WINRT
/*!
\class QFileSystemWatcher
diff --git a/src/corelib/io/qfilesystemwatcher_p.h b/src/corelib/io/qfilesystemwatcher_p.h
index 6c64411f92..4220c1db28 100644
--- a/src/corelib/io/qfilesystemwatcher_p.h
+++ b/src/corelib/io/qfilesystemwatcher_p.h
@@ -58,6 +58,7 @@
#include <private/qobject_p.h>
#include <QtCore/qstringlist.h>
+#include <QtCore/qhash.h>
QT_BEGIN_NAMESPACE
@@ -106,6 +107,15 @@ public:
// private slots
void _q_fileChanged(const QString &path, bool removed);
void _q_directoryChanged(const QString &path, bool removed);
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ void _q_winDriveLockForRemoval(const QString &);
+ void _q_winDriveLockForRemovalFailed(const QString &);
+ void _q_winDriveRemoved(const QString &);
+
+private:
+ QHash<QChar, QStringList> temporarilyRemovedPaths;
+#endif // Q_OS_WIN && !Q_OS_WINRT
};
diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp
index be56d8dd1d..c385a82fc5 100644
--- a/src/corelib/io/qfilesystemwatcher_win.cpp
+++ b/src/corelib/io/qfilesystemwatcher_win.cpp
@@ -52,6 +52,16 @@
#include <qt_windows.h>
+#ifndef Q_OS_WINRT
+# include <qabstractnativeeventfilter.h>
+# include <qcoreapplication.h>
+# include <qdir.h>
+# include <private/qeventdispatcher_win_p.h>
+# include <dbt.h>
+# include <algorithm>
+# include <vector>
+#endif // !Q_OS_WINRT
+
QT_BEGIN_NAMESPACE
// #define WINQFSW_DEBUG
@@ -61,11 +71,275 @@ QT_BEGIN_NAMESPACE
# define DEBUG if (false) qDebug
#endif
+#ifndef Q_OS_WINRT
+///////////
+// QWindowsRemovableDriveListener
+// Listen for the various WM_DEVICECHANGE message indicating drive addition/removal
+// requests and removals.
+///////////
+class QWindowsRemovableDriveListener : public QObject, public QAbstractNativeEventFilter
+{
+ Q_OBJECT
+public:
+ // Device UUids as declared in ioevent.h (GUID_IO_VOLUME_LOCK, ...)
+ enum VolumeUuid { UnknownUuid, UuidIoVolumeLock, UuidIoVolumeLockFailed,
+ UuidIoVolumeUnlock, UuidIoMediaRemoval };
+
+ struct RemovableDriveEntry {
+ HDEVNOTIFY devNotify;
+ wchar_t drive;
+ };
+
+ explicit QWindowsRemovableDriveListener(QObject *parent = nullptr);
+ ~QWindowsRemovableDriveListener();
+
+ // Call from QFileSystemWatcher::addPaths() to set up notifications on drives
+ void addPath(const QString &path);
+
+ bool nativeEventFilter(const QByteArray &, void *messageIn, long *) override;
+
+signals:
+ void driveAdded();
+ void driveRemoved(const QString &);
+ void driveLockForRemoval(const QString &);
+ void driveLockForRemovalFailed(const QString &);
+
+private:
+ static VolumeUuid volumeUuid(const UUID &needle);
+ void handleDbtCustomEvent(const MSG *msg);
+ void handleDbtDriveArrivalRemoval(const MSG *msg);
+
+ std::vector<RemovableDriveEntry> m_removableDrives;
+ quintptr m_lastMessageHash;
+};
+
+static inline QEventDispatcherWin32 *winEventDispatcher()
+{
+ return static_cast<QEventDispatcherWin32 *>(QCoreApplication::instance()->eventDispatcher());
+}
+
+QWindowsRemovableDriveListener::QWindowsRemovableDriveListener(QObject *parent)
+ : QObject(parent)
+ , m_lastMessageHash(0)
+{
+ winEventDispatcher()->installNativeEventFilter(this);
+}
+
+static void stopDeviceNotification(QWindowsRemovableDriveListener::RemovableDriveEntry &e)
+{
+ UnregisterDeviceNotification(e.devNotify);
+ e.devNotify = 0;
+}
+
+template <class Iterator> // Search sequence of RemovableDriveEntry for HDEVNOTIFY.
+static inline Iterator findByHDevNotify(Iterator i1, Iterator i2, HDEVNOTIFY hdevnotify)
+{
+ return std::find_if(i1, i2,
+ [hdevnotify] (const QWindowsRemovableDriveListener::RemovableDriveEntry &e) { return e.devNotify == hdevnotify; });
+}
+
+QWindowsRemovableDriveListener::~QWindowsRemovableDriveListener()
+{
+ std::for_each(m_removableDrives.begin(), m_removableDrives.end(), stopDeviceNotification);
+}
+
+static QString pathFromEntry(const QWindowsRemovableDriveListener::RemovableDriveEntry &re)
+{
+ QString path = QStringLiteral("A:/");
+ path[0] = QChar::fromLatin1(re.drive);
+ return path;
+}
+
+// Handle WM_DEVICECHANGE+DBT_CUSTOMEVENT, which is sent based on the registration
+// on the volume handle with QEventDispatcherWin32's message window in the class.
+// Capture the GUID_IO_VOLUME_LOCK indicating the drive is to be removed.
+QWindowsRemovableDriveListener::VolumeUuid QWindowsRemovableDriveListener::volumeUuid(const UUID &needle)
+{
+ static const struct VolumeUuidMapping // UUIDs from IoEvent.h (missing in MinGW)
+ {
+ VolumeUuid v;
+ UUID uuid;
+ } mapping[] = {
+ { UuidIoVolumeLock, // GUID_IO_VOLUME_LOCK
+ {0x50708874, 0xc9af, 0x11d1, {0x8f, 0xef, 0x0, 0xa0, 0xc9, 0xa0, 0x6d, 0x32}} },
+ { UuidIoVolumeLockFailed, // GUID_IO_VOLUME_LOCK_FAILED
+ {0xae2eed10, 0x0ba8, 0x11d2, {0x8f, 0xfb, 0x0, 0xa0, 0xc9, 0xa0, 0x6d, 0x32}} },
+ { UuidIoVolumeUnlock, // GUID_IO_VOLUME_UNLOCK
+ {0x9a8c3d68, 0xd0cb, 0x11d1, {0x8f, 0xef, 0x0, 0xa0, 0xc9, 0xa0, 0x6d, 0x32}} },
+ { UuidIoMediaRemoval, // GUID_IO_MEDIA_REMOVAL
+ {0xd07433c1, 0xa98e, 0x11d2, {0x91, 0x7a, 0x0, 0xa0, 0xc9, 0x06, 0x8f, 0xf3}} }
+ };
+
+ static const VolumeUuidMapping *end = mapping + sizeof(mapping) / sizeof(mapping[0]);
+ const VolumeUuidMapping *m =
+ std::find_if(mapping, end, [&needle] (const VolumeUuidMapping &m) { return IsEqualGUID(m.uuid, needle); });
+ return m != end ? m->v : UnknownUuid;
+}
+
+inline void QWindowsRemovableDriveListener::handleDbtCustomEvent(const MSG *msg)
+{
+ const DEV_BROADCAST_HDR *broadcastHeader = reinterpret_cast<const DEV_BROADCAST_HDR *>(msg->lParam);
+ if (broadcastHeader->dbch_devicetype != DBT_DEVTYP_HANDLE)
+ return;
+ const DEV_BROADCAST_HANDLE *broadcastHandle = reinterpret_cast<const DEV_BROADCAST_HANDLE *>(broadcastHeader);
+ const auto it = findByHDevNotify(m_removableDrives.cbegin(), m_removableDrives.cend(),
+ broadcastHandle->dbch_hdevnotify);
+ if (it == m_removableDrives.cend())
+ return;
+ switch (volumeUuid(broadcastHandle->dbch_eventguid)) {
+ case UuidIoVolumeLock: // Received for removable USB media
+ emit driveLockForRemoval(pathFromEntry(*it));
+ break;
+ case UuidIoVolumeLockFailed:
+ emit driveLockForRemovalFailed(pathFromEntry(*it));
+ break;
+ case UuidIoVolumeUnlock:
+ break;
+ case UuidIoMediaRemoval: // Received for optical drives
+ break;
+ default:
+ break;
+ }
+}
+
+// Handle WM_DEVICECHANGE+DBT_DEVICEARRIVAL/DBT_DEVICEREMOVECOMPLETE which are
+// sent to all top level windows and cannot be registered for (that is, their
+// triggering depends on top level windows being present)
+inline void QWindowsRemovableDriveListener::handleDbtDriveArrivalRemoval(const MSG *msg)
+{
+ const DEV_BROADCAST_HDR *broadcastHeader = reinterpret_cast<const DEV_BROADCAST_HDR *>(msg->lParam);
+ switch (broadcastHeader->dbch_devicetype) {
+ case DBT_DEVTYP_HANDLE: // WM_DEVICECHANGE/DBT_DEVTYP_HANDLE is sent for our registered drives.
+ if (msg->wParam == DBT_DEVICEREMOVECOMPLETE) {
+ const DEV_BROADCAST_HANDLE *broadcastHandle = reinterpret_cast<const DEV_BROADCAST_HANDLE *>(broadcastHeader);
+ const auto it = findByHDevNotify(m_removableDrives.begin(), m_removableDrives.end(),
+ broadcastHandle->dbch_hdevnotify);
+ // Emit for removable USB drives we were registered for.
+ if (it != m_removableDrives.end()) {
+ emit driveRemoved(pathFromEntry(*it));
+ stopDeviceNotification(*it);
+ m_removableDrives.erase(it);
+ }
+ }
+ break;
+ case DBT_DEVTYP_VOLUME: {
+ const DEV_BROADCAST_VOLUME *broadcastVolume = reinterpret_cast<const DEV_BROADCAST_VOLUME *>(broadcastHeader);
+ // WM_DEVICECHANGE/DBT_DEVTYP_VOLUME messages are sent to all toplevel windows. Compare a hash value to ensure
+ // it is handled only once.
+ const quintptr newHash = reinterpret_cast<quintptr>(broadcastVolume) + msg->wParam
+ + quintptr(broadcastVolume->dbcv_flags) + quintptr(broadcastVolume->dbcv_unitmask);
+ if (newHash == m_lastMessageHash)
+ return;
+ m_lastMessageHash = newHash;
+ // Check for DBTF_MEDIA (inserted/Removed Optical drives). Ignore for now.
+ if (broadcastVolume->dbcv_flags & DBTF_MEDIA)
+ return;
+ // Continue with plugged in USB media where dbcv_flags=0.
+ switch (msg->wParam) {
+ case DBT_DEVICEARRIVAL:
+ emit driveAdded();
+ break;
+ case DBT_DEVICEREMOVECOMPLETE: // handled by DBT_DEVTYP_HANDLE above
+ break;
+ }
+ }
+ break;
+ }
+}
+
+bool QWindowsRemovableDriveListener::nativeEventFilter(const QByteArray &, void *messageIn, long *)
+{
+ const MSG *msg = reinterpret_cast<const MSG *>(messageIn);
+ if (msg->message == WM_DEVICECHANGE) {
+ switch (msg->wParam) {
+ case DBT_CUSTOMEVENT:
+ handleDbtCustomEvent(msg);
+ break;
+ case DBT_DEVICEARRIVAL:
+ case DBT_DEVICEREMOVECOMPLETE:
+ handleDbtDriveArrivalRemoval(msg);
+ break;
+ }
+ }
+ return false;
+}
+
+// Set up listening for WM_DEVICECHANGE+DBT_CUSTOMEVENT for a removable drive path,
+void QWindowsRemovableDriveListener::addPath(const QString &p)
+{
+ const wchar_t drive = p.size() >= 2 && p.at(0).isLetter() && p.at(1) == QLatin1Char(':')
+ ? wchar_t(p.at(0).toUpper().unicode()) : L'\0';
+ if (!drive)
+ return;
+ // Already listening?
+ if (std::any_of(m_removableDrives.cbegin(), m_removableDrives.cend(),
+ [drive](const RemovableDriveEntry &e) { return e.drive == drive; })) {
+ return;
+ }
+
+ wchar_t devicePath[8] = L"\\\\.\\A:\\";
+ devicePath[4] = drive;
+ RemovableDriveEntry re;
+ re.drive = drive;
+ if (GetDriveTypeW(devicePath + 4) != DRIVE_REMOVABLE)
+ return;
+ const HANDLE volumeHandle =
+ CreateFile(devicePath, FILE_READ_ATTRIBUTES,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 0,
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, // Volume requires BACKUP_SEMANTICS
+ 0);
+ if (volumeHandle == INVALID_HANDLE_VALUE) {
+ qErrnoWarning("CreateFile %s failed.",
+ qPrintable(QString::fromWCharArray(devicePath)));
+ return;
+ }
+
+ DEV_BROADCAST_HANDLE notify;
+ ZeroMemory(&notify, sizeof(notify));
+ notify.dbch_size = sizeof(notify);
+ notify.dbch_devicetype = DBT_DEVTYP_HANDLE;
+ notify.dbch_handle = volumeHandle;
+ re.devNotify = RegisterDeviceNotification(winEventDispatcher()->internalHwnd(),
+ &notify, DEVICE_NOTIFY_WINDOW_HANDLE);
+ // Empirically found: The notifications also work when the handle is immediately
+ // closed. Do it here to avoid having to close/reopen in lock message handling.
+ CloseHandle(volumeHandle);
+ if (!re.devNotify) {
+ qErrnoWarning("RegisterDeviceNotification %s failed.",
+ qPrintable(QString::fromWCharArray(devicePath)));
+ return;
+ }
+
+ m_removableDrives.push_back(re);
+}
+#endif // !Q_OS_WINRT
+
+///////////
+// QWindowsFileSystemWatcherEngine
+///////////
QWindowsFileSystemWatcherEngine::Handle::Handle()
: handle(INVALID_HANDLE_VALUE), flags(0u)
{
}
+QWindowsFileSystemWatcherEngine::QWindowsFileSystemWatcherEngine(QObject *parent)
+ : QFileSystemWatcherEngine(parent)
+#ifndef Q_OS_WINRT
+ , m_driveListener(new QWindowsRemovableDriveListener(this))
+#endif
+{
+#ifndef Q_OS_WINRT
+ parent->setProperty("_q_driveListener",
+ QVariant::fromValue(static_cast<QObject *>(m_driveListener)));
+ QObject::connect(m_driveListener, &QWindowsRemovableDriveListener::driveLockForRemoval,
+ this, &QWindowsFileSystemWatcherEngine::driveLockForRemoval);
+ QObject::connect(m_driveListener, &QWindowsRemovableDriveListener::driveLockForRemovalFailed,
+ this, &QWindowsFileSystemWatcherEngine::driveLockForRemovalFailed);
+ QObject::connect(m_driveListener, &QWindowsRemovableDriveListener::driveRemoved,
+ this, &QWindowsFileSystemWatcherEngine::driveRemoved);
+#endif // !Q_OS_WINRT
+}
+
QWindowsFileSystemWatcherEngine::~QWindowsFileSystemWatcherEngine()
{
for (auto *thread : qAsConst(threads))
@@ -210,6 +484,13 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths,
}
}
}
+
+#ifndef Q_OS_WINRT
+ for (const QString &path : paths) {
+ if (!p.contains(path))
+ m_driveListener->addPath(path);
+ }
+#endif // !Q_OS_WINRT
return p;
}
@@ -439,4 +720,9 @@ void QWindowsFileSystemWatcherEngineThread::wakeup()
}
QT_END_NAMESPACE
+
+#ifndef Q_OS_WINRT
+# include "qfilesystemwatcher_win.moc"
+#endif
+
#endif // QT_NO_FILESYSTEMWATCHER
diff --git a/src/corelib/io/qfilesystemwatcher_win_p.h b/src/corelib/io/qfilesystemwatcher_win_p.h
index e8f5c49dec..51c7082483 100644
--- a/src/corelib/io/qfilesystemwatcher_win_p.h
+++ b/src/corelib/io/qfilesystemwatcher_win_p.h
@@ -66,6 +66,7 @@
QT_BEGIN_NAMESPACE
class QWindowsFileSystemWatcherEngineThread;
+class QWindowsRemovableDriveListener;
// Even though QWindowsFileSystemWatcherEngine is derived of QThread
// via QFileSystemWatcher, it does not start a thread.
@@ -75,9 +76,7 @@ class QWindowsFileSystemWatcherEngine : public QFileSystemWatcherEngine
{
Q_OBJECT
public:
- inline QWindowsFileSystemWatcherEngine(QObject *parent)
- : QFileSystemWatcherEngine(parent)
- { }
+ explicit QWindowsFileSystemWatcherEngine(QObject *parent);
~QWindowsFileSystemWatcherEngine();
QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories);
@@ -121,9 +120,17 @@ public:
|| lastModified != fileInfo.lastModified());
}
};
+
+signals:
+ void driveLockForRemoval(const QString &);
+ void driveLockForRemovalFailed(const QString &);
+ void driveRemoved(const QString &);
+
private:
QList<QWindowsFileSystemWatcherEngineThread *> threads;
-
+#ifndef Q_OS_WINRT
+ QWindowsRemovableDriveListener *m_driveListener;
+#endif
};
class QFileSystemWatcherPathKey : public QString
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index bf2f47d399..b2e3df79b8 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -144,7 +144,7 @@ static inline bool setCloseOnExec(int fd)
static inline QString msgOpenDirectory()
{
const char message[] = QT_TRANSLATE_NOOP("QIODevice", "file to open is a directory");
-#ifndef QT_BOOTSTRAPPED
+#if QT_CONFIG(translation)
return QIODevice::tr(message);
#else
return QLatin1String(message);
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 23a3cc1a16..45f0a0e8c0 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -1526,7 +1526,7 @@ void QProcess::setStandardOutputProcess(QProcess *destination)
dto->stdinChannel.pipeFrom(dfrom);
}
-#if defined(Q_OS_WIN)
+#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
/*!
\since 4.7
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
index 4ce0503761..75a0bac2ed 100644
--- a/src/corelib/io/qprocess.h
+++ b/src/corelib/io/qprocess.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_PROCESS
-#if !defined(Q_OS_WIN) || defined(Q_QDOC)
+#if !defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
typedef qint64 Q_PID;
#else
QT_END_NAMESPACE
@@ -187,7 +187,7 @@ public:
void setStandardErrorFile(const QString &fileName, OpenMode mode = Truncate);
void setStandardOutputProcess(QProcess *destination);
-#if defined(Q_OS_WIN)
+#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
QString nativeArguments() const;
void setNativeArguments(const QString &arguments);
struct CreateProcessArguments
@@ -206,7 +206,7 @@ public:
typedef std::function<void(CreateProcessArguments *)> CreateProcessArgumentModifier;
CreateProcessArgumentModifier createProcessArgumentsModifier() const;
void setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier);
-#endif // Q_OS_WIN
+#endif // Q_OS_WIN || Q_CLANG_QDOC
QString workingDirectory() const;
void setWorkingDirectory(const QString &dir);
diff --git a/src/corelib/io/qsavefile.h b/src/corelib/io/qsavefile.h
index 10857c27d1..0a6af91261 100644
--- a/src/corelib/io/qsavefile.h
+++ b/src/corelib/io/qsavefile.h
@@ -84,6 +84,9 @@ protected:
private:
void close() Q_DECL_OVERRIDE;
+#if !QT_CONFIG(translation)
+ static QString tr(const char *string) { return QString::fromLatin1(string); }
+#endif
private:
Q_DISABLE_COPY(QSaveFile)
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 8c67d97afa..1a69891d3b 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -128,7 +128,18 @@ Q_DECLARE_TYPEINFO(QConfFileCustomFormat, Q_MOVABLE_TYPE);
typedef QHash<QString, QConfFile *> ConfFileHash;
typedef QCache<QString, QConfFile> ConfFileCache;
-typedef QHash<int, QString> PathHash;
+namespace {
+ struct Path
+ {
+ // Note: Defining constructors explicitly because of buggy C++11
+ // implementation in MSVC (uniform initialization).
+ Path() {}
+ Path(const QString & p, bool ud) : path(p), userDefined(ud) {}
+ QString path;
+ bool userDefined; //!< true - user defined, overridden by setPath
+ };
+}
+typedef QHash<int, Path> PathHash;
typedef QVector<QConfFileCustomFormat> CustomFormatVector;
Q_GLOBAL_STATIC(ConfFileHash, usedHashFunc)
@@ -220,7 +231,7 @@ void QConfFile::clearCache()
// QSettingsPrivate
QSettingsPrivate::QSettingsPrivate(QSettings::Format format)
- : format(format), scope(QSettings::UserScope /* nothing better to put */), iniCodec(0), spec(0), fallbacks(true),
+ : format(format), scope(QSettings::UserScope /* nothing better to put */), iniCodec(0), fallbacks(true),
pendingChanges(false), status(QSettings::NoError)
{
}
@@ -228,7 +239,7 @@ QSettingsPrivate::QSettingsPrivate(QSettings::Format format)
QSettingsPrivate::QSettingsPrivate(QSettings::Format format, QSettings::Scope scope,
const QString &organization, const QString &application)
: format(format), scope(scope), organizationName(organization), applicationName(application),
- iniCodec(0), spec(0), fallbacks(true), pendingChanges(false), status(QSettings::NoError)
+ iniCodec(0), fallbacks(true), pendingChanges(false), status(QSettings::NoError)
{
}
@@ -940,7 +951,7 @@ void QConfFileSettingsPrivate::initFormat()
void QConfFileSettingsPrivate::initAccess()
{
- if (confFiles[spec]) {
+ if (!confFiles.isEmpty()) {
if (format > QSettings::IniFormat) {
if (!readFunc)
setStatus(QSettings::AccessError);
@@ -1070,22 +1081,22 @@ static void initDefaultPaths(QMutexLocker *locker)
const QString programDataFolder = windowsConfigPath(FOLDERID_ProgramData);
# endif
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope),
- roamingAppDataFolder + QDir::separator());
+ Path(roamingAppDataFolder + QDir::separator(), false));
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope),
- programDataFolder + QDir::separator());
+ Path(programDataFolder + QDir::separator(), false));
#else
const QString userPath = make_user_path();
- pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), userPath);
- pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), systemPath);
+ pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), Path(userPath, false));
+ pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), Path(systemPath, false));
#ifndef Q_OS_MAC
- pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::UserScope), userPath);
- pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::SystemScope), systemPath);
+ pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::UserScope), Path(userPath, false));
+ pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::SystemScope), Path(systemPath, false));
#endif
#endif // Q_OS_WIN
}
}
-static QString getPath(QSettings::Format format, QSettings::Scope scope)
+static Path getPath(QSettings::Format format, QSettings::Scope scope)
{
Q_ASSERT((int)QSettings::NativeFormat == 0);
Q_ASSERT((int)QSettings::IniFormat == 1);
@@ -1095,14 +1106,23 @@ static QString getPath(QSettings::Format format, QSettings::Scope scope)
if (pathHash->isEmpty())
initDefaultPaths(&locker);
- QString result = pathHash->value(pathHashKey(format, scope));
- if (!result.isEmpty())
+ Path result = pathHash->value(pathHashKey(format, scope));
+ if (!result.path.isEmpty())
return result;
// fall back on INI path
return pathHash->value(pathHashKey(QSettings::IniFormat, scope));
}
+#if defined(QT_BUILD_INTERNAL) && defined(Q_XDG_PLATFORM) && !defined(QT_NO_STANDARDPATHS)
+// Note: Suitable only for autotests.
+void Q_AUTOTEST_EXPORT clearDefaultPaths()
+{
+ QMutexLocker locker(&settingsGlobalMutex);
+ pathHashFunc()->clear();
+}
+#endif // QT_BUILD_INTERNAL && Q_XDG_PLATFORM && !QT_NO_STANDARDPATHS
+
QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
QSettings::Scope scope,
const QString &organization,
@@ -1110,7 +1130,6 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
: QSettingsPrivate(format, scope, organization, application),
nextPosition(0x40000000) // big positive number
{
- int i;
initFormat();
QString org = organization;
@@ -1123,22 +1142,43 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
QString orgFile = org + extension;
if (scope == QSettings::UserScope) {
- QString userPath = getPath(format, QSettings::UserScope);
+ Path userPath = getPath(format, QSettings::UserScope);
if (!application.isEmpty())
- confFiles[F_User | F_Application].reset(QConfFile::fromName(userPath + appFile, true));
- confFiles[F_User | F_Organization].reset(QConfFile::fromName(userPath + orgFile, true));
+ confFiles.append(QConfFile::fromName(userPath.path + appFile, true));
+ confFiles.append(QConfFile::fromName(userPath.path + orgFile, true));
}
- QString systemPath = getPath(format, QSettings::SystemScope);
- if (!application.isEmpty())
- confFiles[F_System | F_Application].reset(QConfFile::fromName(systemPath + appFile, false));
- confFiles[F_System | F_Organization].reset(QConfFile::fromName(systemPath + orgFile, false));
-
- for (i = 0; i < NumConfFiles; ++i) {
- if (confFiles[i]) {
- spec = i;
- break;
+ Path systemPath = getPath(format, QSettings::SystemScope);
+#if defined(Q_XDG_PLATFORM) && !defined(QT_NO_STANDARDPATHS)
+ // check if the systemPath wasn't overridden by QSettings::setPath()
+ if (!systemPath.userDefined) {
+ // Note: We can't use QStandardPaths::locateAll() as we need all the
+ // possible files (not just the existing ones) and there is no way
+ // to exclude user specific (XDG_CONFIG_HOME) directory from the search.
+ QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation);
+ // remove the QStandardLocation::writableLocation() (XDG_CONFIG_HOME)
+ if (!dirs.isEmpty())
+ dirs.takeFirst();
+ QStringList paths;
+ if (!application.isEmpty()) {
+ paths.reserve(dirs.size() * 2);
+ for (const auto &dir : qAsConst(dirs))
+ paths.append(dir + QLatin1Char('/') + appFile);
+ } else {
+ paths.reserve(dirs.size());
}
+ for (const auto &dir : qAsConst(dirs))
+ paths.append(dir + QLatin1Char('/') + orgFile);
+
+ // Note: No check for existence of files is done intentionaly.
+ for (const auto &path : qAsConst(paths))
+ confFiles.append(QConfFile::fromName(path, false));
+ } else
+#endif // Q_XDG_PLATFORM && !QT_NO_STANDARDPATHS
+ {
+ if (!application.isEmpty())
+ confFiles.append(QConfFile::fromName(systemPath.path + appFile, false));
+ confFiles.append(QConfFile::fromName(systemPath.path + orgFile, false));
}
initAccess();
@@ -1151,7 +1191,7 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(const QString &fileName,
{
initFormat();
- confFiles[0].reset(QConfFile::fromName(fileName, true));
+ confFiles.append(QConfFile::fromName(fileName, true));
initAccess();
}
@@ -1162,40 +1202,39 @@ QConfFileSettingsPrivate::~QConfFileSettingsPrivate()
ConfFileHash *usedHash = usedHashFunc();
ConfFileCache *unusedCache = unusedCacheFunc();
- for (int i = 0; i < NumConfFiles; ++i) {
- if (confFiles[i] && !confFiles[i]->ref.deref()) {
- if (confFiles[i]->size == 0) {
- delete confFiles[i].take();
+ for (auto conf_file : qAsConst(confFiles)) {
+ if (!conf_file->ref.deref()) {
+ if (conf_file->size == 0) {
+ delete conf_file;
} else {
if (usedHash)
- usedHash->remove(confFiles[i]->name);
+ usedHash->remove(conf_file->name);
if (unusedCache) {
QT_TRY {
// compute a better size?
- unusedCache->insert(confFiles[i]->name, confFiles[i].data(),
- 10 + (confFiles[i]->originalKeys.size() / 4));
- confFiles[i].take();
+ unusedCache->insert(conf_file->name, conf_file,
+ 10 + (conf_file->originalKeys.size() / 4));
} QT_CATCH(...) {
// out of memory. Do not cache the file.
- delete confFiles[i].take();
+ delete conf_file;
}
} else {
// unusedCache is gone - delete the entry to prevent a memory leak
- delete confFiles[i].take();
+ delete conf_file;
}
}
}
- // prevent the ScopedPointer to deref it again.
- confFiles[i].take();
}
}
void QConfFileSettingsPrivate::remove(const QString &key)
{
- QConfFile *confFile = confFiles[spec].data();
- if (!confFile)
+ if (confFiles.isEmpty())
return;
+ // Note: First config file is always the most specific.
+ QConfFile *confFile = confFiles.at(0);
+
QSettingsKey theKey(key, caseSensitivity);
QSettingsKey prefix(key + QLatin1Char('/'), caseSensitivity);
QMutexLocker locker(&confFile->mutex);
@@ -1219,10 +1258,12 @@ void QConfFileSettingsPrivate::remove(const QString &key)
void QConfFileSettingsPrivate::set(const QString &key, const QVariant &value)
{
- QConfFile *confFile = confFiles[spec].data();
- if (!confFile)
+ if (confFiles.isEmpty())
return;
+ // Note: First config file is always the most specific.
+ QConfFile *confFile = confFiles.at(0);
+
QSettingsKey theKey(key, caseSensitivity, nextPosition++);
QMutexLocker locker(&confFile->mutex);
confFile->removedKeys.remove(theKey);
@@ -1235,29 +1276,27 @@ bool QConfFileSettingsPrivate::get(const QString &key, QVariant *value) const
ParsedSettingsMap::const_iterator j;
bool found = false;
- for (int i = 0; i < NumConfFiles; ++i) {
- if (QConfFile *confFile = confFiles[i].data()) {
- QMutexLocker locker(&confFile->mutex);
+ for (auto confFile : qAsConst(confFiles)) {
+ QMutexLocker locker(&confFile->mutex);
- if (!confFile->addedKeys.isEmpty()) {
- j = confFile->addedKeys.constFind(theKey);
- found = (j != confFile->addedKeys.constEnd());
- }
- if (!found) {
- ensureSectionParsed(confFile, theKey);
- j = confFile->originalKeys.constFind(theKey);
- found = (j != confFile->originalKeys.constEnd()
- && !confFile->removedKeys.contains(theKey));
- }
+ if (!confFile->addedKeys.isEmpty()) {
+ j = confFile->addedKeys.constFind(theKey);
+ found = (j != confFile->addedKeys.constEnd());
+ }
+ if (!found) {
+ ensureSectionParsed(confFile, theKey);
+ j = confFile->originalKeys.constFind(theKey);
+ found = (j != confFile->originalKeys.constEnd()
+ && !confFile->removedKeys.contains(theKey));
+ }
- if (found && value)
- *value = *j;
+ if (found && value)
+ *value = *j;
- if (found)
- return true;
- if (!fallbacks)
- break;
- }
+ if (found)
+ return true;
+ if (!fallbacks)
+ break;
}
return false;
}
@@ -1270,34 +1309,31 @@ QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec
QSettingsKey thePrefix(prefix, caseSensitivity);
int startPos = prefix.size();
- for (int i = 0; i < NumConfFiles; ++i) {
- if (QConfFile *confFile = confFiles[i].data()) {
- QMutexLocker locker(&confFile->mutex);
+ for (auto confFile : qAsConst(confFiles)) {
+ QMutexLocker locker(&confFile->mutex);
- if (thePrefix.isEmpty()) {
- ensureAllSectionsParsed(confFile);
- } else {
- ensureSectionParsed(confFile, thePrefix);
- }
-
- j = const_cast<const ParsedSettingsMap *>(
- &confFile->originalKeys)->lowerBound( thePrefix);
- while (j != confFile->originalKeys.constEnd() && j.key().startsWith(thePrefix)) {
- if (!confFile->removedKeys.contains(j.key()))
- processChild(j.key().originalCaseKey().midRef(startPos), spec, result);
- ++j;
- }
+ if (thePrefix.isEmpty())
+ ensureAllSectionsParsed(confFile);
+ else
+ ensureSectionParsed(confFile, thePrefix);
- j = const_cast<const ParsedSettingsMap *>(
- &confFile->addedKeys)->lowerBound(thePrefix);
- while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) {
+ j = const_cast<const ParsedSettingsMap *>(
+ &confFile->originalKeys)->lowerBound( thePrefix);
+ while (j != confFile->originalKeys.constEnd() && j.key().startsWith(thePrefix)) {
+ if (!confFile->removedKeys.contains(j.key()))
processChild(j.key().originalCaseKey().midRef(startPos), spec, result);
- ++j;
- }
+ ++j;
+ }
- if (!fallbacks)
- break;
+ j = const_cast<const ParsedSettingsMap *>(
+ &confFile->addedKeys)->lowerBound(thePrefix);
+ while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) {
+ processChild(j.key().originalCaseKey().midRef(startPos), spec, result);
+ ++j;
}
+
+ if (!fallbacks)
+ break;
}
std::sort(result.begin(), result.end());
result.erase(std::unique(result.begin(), result.end()),
@@ -1307,10 +1343,12 @@ QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec
void QConfFileSettingsPrivate::clear()
{
- QConfFile *confFile = confFiles[spec].data();
- if (!confFile)
+ if (confFiles.isEmpty())
return;
+ // Note: First config file is always the most specific.
+ QConfFile *confFile = confFiles.at(0);
+
QMutexLocker locker(&confFile->mutex);
ensureAllSectionsParsed(confFile);
confFile->addedKeys.clear();
@@ -1322,12 +1360,9 @@ void QConfFileSettingsPrivate::sync()
// people probably won't be checking the status a whole lot, so in case of
// error we just try to go on and make the best of it
- for (int i = 0; i < NumConfFiles; ++i) {
- QConfFile *confFile = confFiles[i].data();
- if (confFile) {
- QMutexLocker locker(&confFile->mutex);
- syncConfFile(i);
- }
+ for (auto confFile : qAsConst(confFiles)) {
+ QMutexLocker locker(&confFile->mutex);
+ syncConfFile(confFile);
}
}
@@ -1338,10 +1373,11 @@ void QConfFileSettingsPrivate::flush()
QString QConfFileSettingsPrivate::fileName() const
{
- QConfFile *confFile = confFiles[spec].data();
- if (!confFile)
+ if (confFiles.isEmpty())
return QString();
- return confFile->name;
+
+ // Note: First config file is always the most specific.
+ return confFiles.at(0)->name;
}
bool QConfFileSettingsPrivate::isWritable() const
@@ -1349,16 +1385,14 @@ bool QConfFileSettingsPrivate::isWritable() const
if (format > QSettings::IniFormat && !writeFunc)
return false;
- QConfFile *confFile = confFiles[spec].data();
- if (!confFile)
+ if (confFiles.isEmpty())
return false;
- return confFile->isWritable();
+ return confFiles.at(0)->isWritable();
}
-void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
+void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
{
- QConfFile *confFile = confFiles[confFileNo].data();
bool readOnly = confFile->addedKeys.isEmpty() && confFile->removedKeys.isEmpty();
/*
@@ -2188,9 +2222,10 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
\list 1
\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}
+ \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft/Star Runner.conf}
+ \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft.conf}
\endlist
+ \note If XDG_CONFIG_DIRS is unset, the default value of \c{/etc/xdg} is used.
On \macos versions 10.2 and 10.3, these files are used by
default:
@@ -2225,9 +2260,10 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
\list 1
\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}
+ \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft/Star Runner.ini}
+ \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft.ini}
\endlist
+ \note If XDG_CONFIG_DIRS is unset, the default value of \c{/etc/xdg} is used.
On Windows, the following files are used:
@@ -3380,7 +3416,7 @@ void QSettings::setPath(Format format, Scope scope, const QString &path)
PathHash *pathHash = pathHashFunc();
if (pathHash->isEmpty())
initDefaultPaths(&locker);
- pathHash->insert(pathHashKey(format, scope), path + QDir::separator());
+ pathHash->insert(pathHashKey(format, scope), Path(path + QDir::separator(), true));
}
/*!
diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp
index b79abfb874..dcaefd1613 100644
--- a/src/corelib/io/qsettings_mac.cpp
+++ b/src/corelib/io/qsettings_mac.cpp
@@ -422,20 +422,15 @@ QMacSettingsPrivate::QMacSettingsPrivate(QSettings::Scope scope, const QString &
javaPackageName.prepend(QLatin1String("com."));
suiteId = javaPackageName;
- if (scope == QSettings::SystemScope)
- spec |= F_System;
-
- if (application.isEmpty()) {
- spec |= F_Organization;
- } else {
+ if (!application.isEmpty()) {
javaPackageName += QLatin1Char('.');
javaPackageName += application;
applicationId = javaPackageName;
}
numDomains = 0;
- for (int i = (spec & F_System) ? 1 : 0; i < 2; ++i) {
- for (int j = (spec & F_Organization) ? 1 : 0; j < 3; ++j) {
+ for (int i = (scope == QSettings::SystemScope) ? 1 : 0; i < 2; ++i) {
+ for (int j = (application.isEmpty()) ? 1 : 0; j < 3; ++j) {
SearchDomain &domain = domains[numDomains++];
domain.userName = (i == 0) ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
if (j == 0)
@@ -576,7 +571,7 @@ bool QMacSettingsPrivate::isWritable() const
QString QMacSettingsPrivate::fileName() const
{
QString result;
- if ((spec & F_System) == 0)
+ if (scope == QSettings::UserScope)
result = QDir::homePath();
result += QLatin1String("/Library/Preferences/");
result += QString::fromCFString(domains[0].applicationOrSuiteId);
diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h
index e6d3413bab..639605d8c4 100644
--- a/src/corelib/io/qsettings_p.h
+++ b/src/corelib/io/qsettings_p.h
@@ -236,19 +236,6 @@ public:
QTextCodec *codec);
static QStringList splitArgs(const QString &s, int idx);
- /*
- The numeric values of these enums define their search order. For example,
- F_User | F_Organization is searched before F_System | F_Application,
- because their values are respectively 1 and 2.
- */
- enum {
- F_Application = 0x0,
- F_Organization = 0x1,
- F_User = 0x0,
- F_System = 0x2,
- NumConfFiles = 4
- };
-
QSettings::Format format;
QSettings::Scope scope;
QString organizationName;
@@ -258,7 +245,6 @@ public:
protected:
QStack<QSettingsGroup> groupStack;
QString groupPrefix;
- int spec;
bool fallbacks;
bool pendingChanges;
mutable QSettings::Status status;
@@ -293,7 +279,7 @@ public:
private:
void initFormat();
void initAccess();
- void syncConfFile(int confFileNo);
+ void syncConfFile(QConfFile *confFile);
bool writeIniFile(QIODevice &device, const ParsedSettingsMap &map);
#ifdef Q_OS_MAC
bool readPlistFile(const QByteArray &data, ParsedSettingsMap *map) const;
@@ -302,7 +288,7 @@ private:
void ensureAllSectionsParsed(QConfFile *confFile) const;
void ensureSectionParsed(QConfFile *confFile, const QSettingsKey &key) const;
- QScopedSharedPointer<QConfFile> confFiles[NumConfFiles];
+ QVector<QConfFile *> confFiles;
QSettings::ReadFunc readFunc;
QSettings::WriteFunc writeFunc;
QString extension;
diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp
index 1c10548cbc..edcae16776 100644
--- a/src/corelib/io/qsettings_win.cpp
+++ b/src/corelib/io/qsettings_win.cpp
@@ -138,21 +138,6 @@ static void mergeKeySets(NameSet *dest, const QStringList &src)
** Wrappers for the insane windows registry API
*/
-static QString errorCodeToString(DWORD errorCode)
-{
- wchar_t *data = 0;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, errorCode, 0, data, 0, 0);
- QString result = QString::fromWCharArray(data);
-
- if (data != 0)
- LocalFree(data);
-
- if (result.endsWith(QLatin1Char('\n')))
- result.truncate(result.length() - 1);
-
- return result;
-}
-
// Open a key with the specified "perms".
// "access" is to explicitly use the 32- or 64-bit branch.
static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey, REGSAM access = 0)
@@ -184,7 +169,7 @@ static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSub
return resultHandle;
//qWarning("QSettings: Failed to create subkey \"%s\": %s",
- // rSubKey.toLatin1().data(), errorCodeToString(res).toLatin1().data());
+ // qPrintable(rSubKey), qPrintable(qt_error_string(int(res))));
return 0;
}
@@ -224,7 +209,7 @@ static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildS
&numKeys, &maxKeySize, 0, 0, 0);
if (res != ERROR_SUCCESS) {
- qWarning("QSettings: RegQueryInfoKey() failed: %s", errorCodeToString(res).toLatin1().data());
+ qWarning("QSettings: RegQueryInfoKey() failed: %s", qPrintable(qt_error_string(int(res))));
return result;
}
@@ -258,7 +243,7 @@ static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildS
item = QString::fromWCharArray((const wchar_t *)buff.constData(), l);
if (res != ERROR_SUCCESS) {
- qWarning("QSettings: RegEnumValue failed: %s", errorCodeToString(res).toLatin1().data());
+ qWarning("QSettings: RegEnumValue failed: %s", qPrintable(qt_error_string(int(res))));
continue;
}
if (item.isEmpty())
@@ -313,7 +298,7 @@ static void deleteChildGroups(HKEY parentHandle, REGSAM access = 0)
LONG res = RegDeleteKey(parentHandle, reinterpret_cast<const wchar_t *>(group.utf16()));
if (res != ERROR_SUCCESS) {
qWarning("QSettings: RegDeleteKey failed on subkey \"%s\": %s",
- group.toLatin1().data(), errorCodeToString(res).toLatin1().data());
+ qPrintable(group), qPrintable(qt_error_string(int(res))));
return;
}
}
@@ -613,7 +598,7 @@ QWinSettingsPrivate::~QWinSettingsPrivate()
DWORD res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(emptyKey.utf16()));
if (res != ERROR_SUCCESS) {
qWarning("QSettings: Failed to delete key \"%s\": %s",
- regList.at(0).key().toLatin1().data(), errorCodeToString(res).toLatin1().data());
+ qPrintable(regList.at(0).key()), qPrintable(qt_error_string(int(res))));
}
}
@@ -652,7 +637,7 @@ void QWinSettingsPrivate::remove(const QString &uKey)
LONG res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(group.utf16()));
if (res != ERROR_SUCCESS) {
qWarning("QSettings: RegDeleteValue failed on subkey \"%s\": %s",
- group.toLatin1().data(), errorCodeToString(res).toLatin1().data());
+ qPrintable(group), qPrintable(qt_error_string(int(res))));
}
}
} else {
@@ -660,7 +645,7 @@ void QWinSettingsPrivate::remove(const QString &uKey)
if (res != ERROR_SUCCESS) {
qWarning("QSettings: RegDeleteKey failed on key \"%s\": %s",
- rKey.toLatin1().data(), errorCodeToString(res).toLatin1().data());
+ qPrintable(rKey), qPrintable(qt_error_string(int(res))));
}
}
RegCloseKey(handle);
@@ -758,7 +743,7 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
deleteWriteHandleOnExit = false;
} else {
qWarning("QSettings: failed to set subkey \"%s\": %s",
- rKey.toLatin1().data(), errorCodeToString(res).toLatin1().data());
+ qPrintable(rKey), qPrintable(qt_error_string(int(res))));
setStatus(QSettings::AccessError);
}
diff --git a/src/corelib/io/qstorageinfo.cpp b/src/corelib/io/qstorageinfo.cpp
index 3773b72606..9885da1af9 100644
--- a/src/corelib/io/qstorageinfo.cpp
+++ b/src/corelib/io/qstorageinfo.cpp
@@ -260,7 +260,7 @@ QByteArray QStorageInfo::fileSystemType() const
devpath like \c /dev/sda0 for local storages. On Windows, it returns the UNC
path starting with \c \\\\?\\ for local storages (in other words, the volume GUID).
- \sa rootPath()
+ \sa rootPath(), subvolume()
*/
QByteArray QStorageInfo::device() const
{
@@ -268,6 +268,26 @@ QByteArray QStorageInfo::device() const
}
/*!
+ \since 5.8
+ Returns the subvolume name for this volume.
+
+ Some filesystem types allow multiple subvolumes inside one device, which
+ may be mounted in different paths. If the subvolume could be detected, it
+ is returned here. The format of the subvolume name is specific to each
+ filesystem type.
+
+ If this volume was not mounted from a subvolume of a larger filesystem or
+ if the subvolume could not be detected, this function returns an empty byte
+ array.
+
+ \sa device()
+*/
+QByteArray QStorageInfo::subvolume() const
+{
+ return d->subvolume;
+}
+
+/*!
Returns the human-readable name of a filesystem, usually called \c label.
Not all filesystems support this feature. In this case, the value returned by
diff --git a/src/corelib/io/qstorageinfo.h b/src/corelib/io/qstorageinfo.h
index 8941c11a16..e2d9747ceb 100644
--- a/src/corelib/io/qstorageinfo.h
+++ b/src/corelib/io/qstorageinfo.h
@@ -71,6 +71,7 @@ public:
QString rootPath() const;
QByteArray device() const;
+ QByteArray subvolume() const;
QByteArray fileSystemType() const;
QString name() const;
QString displayName() const;
@@ -100,7 +101,7 @@ inline bool operator==(const QStorageInfo &first, const QStorageInfo &second)
{
if (first.d == second.d)
return true;
- return first.device() == second.device();
+ return first.device() == second.device() && first.rootPath() == second.rootPath();
}
inline bool operator!=(const QStorageInfo &first, const QStorageInfo &second)
diff --git a/src/corelib/io/qstorageinfo_p.h b/src/corelib/io/qstorageinfo_p.h
index a14fa8480a..ec5bb785e3 100644
--- a/src/corelib/io/qstorageinfo_p.h
+++ b/src/corelib/io/qstorageinfo_p.h
@@ -85,6 +85,7 @@ protected:
public:
QString rootPath;
QByteArray device;
+ QByteArray subvolume;
QByteArray fileSystemType;
QString name;
diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
index ae5c42ffd1..fcc7b8ca50 100644
--- a/src/corelib/io/qstorageinfo_unix.cpp
+++ b/src/corelib/io/qstorageinfo_unix.cpp
@@ -120,6 +120,7 @@ public:
inline QString rootPath() const;
inline QByteArray fileSystemType() const;
inline QByteArray device() const;
+ inline QByteArray options() const;
private:
#if defined(Q_OS_BSD4)
QT_STATFSBUF *stat_buf;
@@ -133,6 +134,7 @@ private:
QByteArray m_rootPath;
QByteArray m_fileSystemType;
QByteArray m_device;
+ QByteArray m_options;
#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
FILE *fp;
mntent mnt;
@@ -228,6 +230,11 @@ inline QByteArray QStorageIterator::device() const
return QByteArray(stat_buf[currentIndex].f_mntfromname);
}
+inline QByteArray QStorageIterator::options() const
+{
+ return QByteArray();
+}
+
#elif defined(Q_OS_SOLARIS)
static const char pathMounted[] = "/etc/mnttab";
@@ -301,6 +308,7 @@ inline bool QStorageIterator::next()
m_device = data.at(0);
m_rootPath = data.at(1);
m_fileSystemType = data.at(2);
+ m_options = data.at(3);
return true;
}
@@ -320,6 +328,11 @@ inline QByteArray QStorageIterator::device() const
return m_device;
}
+inline QByteArray QStorageIterator::options() const
+{
+ return m_options;
+}
+
#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
static const char pathMounted[] = "/etc/mtab";
@@ -363,6 +376,11 @@ inline QByteArray QStorageIterator::device() const
return QByteArray(mnt.mnt_fsname);
}
+inline QByteArray QStorageIterator::options() const
+{
+ return QByteArray(mnt.mnt_opts);
+}
+
#elif defined(Q_OS_HAIKU)
inline QStorageIterator::QStorageIterator()
{
@@ -420,6 +438,11 @@ inline QByteArray QStorageIterator::device() const
return m_device;
}
+inline QByteArray QStorageIterator::options() const
+{
+ return QByteArray();
+}
+
#else
inline QStorageIterator::QStorageIterator()
@@ -455,8 +478,35 @@ inline QByteArray QStorageIterator::device() const
return QByteArray();
}
+inline QByteArray QStorageIterator::options() const
+{
+ return QByteArray();
+}
+
#endif
+static QByteArray extractSubvolume(const QStorageIterator &it)
+{
+#ifdef Q_OS_LINUX
+ if (it.fileSystemType() == "btrfs") {
+ const QByteArrayList opts = it.options().split(',');
+ QByteArray id;
+ for (const QByteArray &opt : opts) {
+ static const char subvol[] = "subvol=";
+ static const char subvolid[] = "subvolid=";
+ if (opt.startsWith(subvol))
+ return std::move(opt).mid(strlen(subvol));
+ if (opt.startsWith(subvolid))
+ id = std::move(opt).mid(strlen(subvolid));
+ }
+
+ // if we didn't find the subvolume name, return the subvolume ID
+ return id;
+ }
+#endif
+ return QByteArray();
+}
+
void QStorageInfoPrivate::initRootPath()
{
rootPath = QFileInfo(rootPath).canonicalFilePath();
@@ -483,6 +533,7 @@ void QStorageInfoPrivate::initRootPath()
rootPath = mountDir;
device = it.device();
fileSystemType = fsName;
+ subvolume = extractSubvolume(it);
}
}
}
diff --git a/src/corelib/io/qtemporarydir.cpp b/src/corelib/io/qtemporarydir.cpp
index 6e50a8513e..b2bf9fce97 100644
--- a/src/corelib/io/qtemporarydir.cpp
+++ b/src/corelib/io/qtemporarydir.cpp
@@ -305,6 +305,33 @@ QString QTemporaryDir::path() const
}
/*!
+ \since 5.9
+
+ Returns the path name of a file in the temporary directory.
+ Does \e not check if the file actually exists in the directory.
+ Redundant multiple separators or "." and ".." directories in
+ \a fileName are not removed (see QDir::cleanPath()). Absolute
+ paths are not allowed.
+*/
+QString QTemporaryDir::filePath(const QString &fileName) const
+{
+ if (QDir::isAbsolutePath(fileName)) {
+ qWarning("QTemporaryDir::filePath: Absolute paths are not allowed: %s", qUtf8Printable(fileName));
+ return QString();
+ }
+
+ if (!d_ptr->success)
+ return QString();
+
+ QString ret = d_ptr->pathOrError;
+ if (!fileName.isEmpty()) {
+ ret += QLatin1Char('/');
+ ret += fileName;
+ }
+ return ret;
+}
+
+/*!
Returns \c true if the QTemporaryDir is in auto remove
mode. Auto-remove mode will automatically delete the directory from
disk upon destruction. This makes it very easy to create your
diff --git a/src/corelib/io/qtemporarydir.h b/src/corelib/io/qtemporarydir.h
index 2e70d34ae4..3f6b70a2eb 100644
--- a/src/corelib/io/qtemporarydir.h
+++ b/src/corelib/io/qtemporarydir.h
@@ -65,6 +65,7 @@ public:
bool remove();
QString path() const;
+ QString filePath(const QString &fileName) const;
private:
QScopedPointer<QTemporaryDirPrivate> d_ptr;
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index 4fdb1505ff..9b565bff9d 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -2547,6 +2547,7 @@ QTextStream &QTextStream::operator<<(double f)
}
uint flags = 0;
+ const QLocale::NumberOptions numberOptions = locale().numberOptions();
if (numberFlags() & ShowBase)
flags |= QLocaleData::ShowBase;
if (numberFlags() & ForceSign)
@@ -2555,12 +2556,18 @@ QTextStream &QTextStream::operator<<(double f)
flags |= QLocaleData::UppercaseBase;
if (numberFlags() & UppercaseDigits)
flags |= QLocaleData::CapitalEorX;
- if (numberFlags() & ForcePoint)
- flags |= QLocaleData::Alternate;
- if (locale() != QLocale::c() && !(locale().numberOptions() & QLocale::OmitGroupSeparator))
+ if (numberFlags() & ForcePoint) {
+ flags |= QLocaleData::ForcePoint;
+
+ // Only for backwards compatibility
+ flags |= QLocaleData::AddTrailingZeroes | QLocaleData::ShowBase;
+ }
+ if (locale() != QLocale::c() && !(numberOptions & QLocale::OmitGroupSeparator))
flags |= QLocaleData::ThousandsGroup;
- if (!(locale().numberOptions() & QLocale::OmitLeadingZeroInExponent))
+ if (!(numberOptions & QLocale::OmitLeadingZeroInExponent))
flags |= QLocaleData::ZeroPadExponent;
+ if (numberOptions & QLocale::IncludeTrailingZeroesAfterDot)
+ flags |= QLocaleData::AddTrailingZeroes;
const QLocaleData *dd = d->locale.d->m_data;
QString num = dd->doubleToString(f, d->params.realNumberPrecision, form, -1, flags);
diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp
index 6390d5f389..6c7101d41f 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.cpp
+++ b/src/corelib/itemmodels/qitemselectionmodel.cpp
@@ -274,8 +274,6 @@ QItemSelectionRange QItemSelectionRange::intersected(const QItemSelectionRange &
*/
/*!
- \fn bool QItemSelectionRange::operator<(const QItemSelectionRange &other) const
-
Returns \c true if the selection range is less than the \a other
range given; otherwise returns \c false.
@@ -284,6 +282,33 @@ QItemSelectionRange QItemSelectionRange::intersected(const QItemSelectionRange &
class can be used with QMap.
*/
+bool QItemSelectionRange::operator<(const QItemSelectionRange &other) const
+{
+ // ### Qt 6: This is inconsistent with op== and needs to be fixed, nay,
+ // ### removed, but cannot, because it was inline up to and including 5.9
+
+ // Comparing parents will compare the models, but if two equivalent ranges
+ // in two different models have invalid parents, they would appear the same
+ if (other.tl.model() == tl.model()) {
+ // parent has to be calculated, so we only do so once.
+ const QModelIndex topLeftParent = tl.parent();
+ const QModelIndex otherTopLeftParent = other.tl.parent();
+ if (topLeftParent == otherTopLeftParent) {
+ if (other.tl.row() == tl.row()) {
+ if (other.tl.column() == tl.column()) {
+ if (other.br.row() == br.row()) {
+ return br.column() < other.br.column();
+ }
+ return br.row() < other.br.row();
+ }
+ return tl.column() < other.tl.column();
+ }
+ return tl.row() < other.tl.row();
+ }
+ return topLeftParent < otherTopLeftParent;
+ }
+ return tl.model() < other.tl.model();
+}
/*!
\fn bool QItemSelectionRange::isValid() const
diff --git a/src/corelib/itemmodels/qitemselectionmodel.h b/src/corelib/itemmodels/qitemselectionmodel.h
index 3d3cb00750..92c459a243 100644
--- a/src/corelib/itemmodels/qitemselectionmodel.h
+++ b/src/corelib/itemmodels/qitemselectionmodel.h
@@ -116,30 +116,7 @@ public:
{ return (tl == other.tl && br == other.br); }
inline bool operator!=(const QItemSelectionRange &other) const
{ return !operator==(other); }
- inline bool operator<(const QItemSelectionRange &other) const
- {
- // Comparing parents will compare the models, but if two equivalent ranges
- // in two different models have invalid parents, they would appear the same
- if (other.tl.model() == tl.model()) {
- // parent has to be calculated, so we only do so once.
- const QModelIndex topLeftParent = tl.parent();
- const QModelIndex otherTopLeftParent = other.tl.parent();
- if (topLeftParent == otherTopLeftParent) {
- if (other.tl.row() == tl.row()) {
- if (other.tl.column() == tl.column()) {
- if (other.br.row() == br.row()) {
- return br.column() < other.br.column();
- }
- return br.row() < other.br.row();
- }
- return tl.column() < other.tl.column();
- }
- return tl.row() < other.tl.row();
- }
- return topLeftParent < otherTopLeftParent;
- }
- return tl.model() < other.tl.model();
- }
+ bool operator<(const QItemSelectionRange &other) const;
inline bool isValid() const
{
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index d7e8d4847a..231afb991c 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -47,14 +47,8 @@
#include <qdebug.h>
-#if defined(Q_OS_IOS)
-#import <UIKit/UIKit.h>
-#endif
-
QT_BEGIN_NAMESPACE
-typedef qint16 (*GestaltFunction)(quint32 selector, qint32 *response);
-
// -------------------------------------------------------------------------
QDebug operator<<(QDebug dbg, const NSObject *nsObject)
@@ -87,54 +81,6 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_DECLARE_WEAK_QDEBUG_OPERATOR_FOR_CF_TY
// -------------------------------------------------------------------------
-QAppleOperatingSystemVersion qt_apple_os_version()
-{
- QAppleOperatingSystemVersion v = {0, 0, 0};
-#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_8_0) || defined(Q_OS_TVOS) || defined(Q_OS_WATCHOS)
- if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) {
- NSOperatingSystemVersion osv = NSProcessInfo.processInfo.operatingSystemVersion;
- v.major = osv.majorVersion;
- v.minor = osv.minorVersion;
- v.patch = osv.patchVersion;
- return v;
- }
-#endif
- // Use temporary variables so we can return 0.0.0 (unknown version)
- // in case of an error partway through determining the OS version
- qint32 major = 0, minor = 0, patch = 0;
-#if QT_MAC_DEPLOYMENT_TARGET_BELOW(__MAC_10_10, __IPHONE_8_0)
-#if defined(Q_OS_IOS)
- @autoreleasepool {
- NSArray *parts = [UIDevice.currentDevice.systemVersion componentsSeparatedByString:@"."];
- major = parts.count > 0 ? [[parts objectAtIndex:0] intValue] : 0;
- minor = parts.count > 1 ? [[parts objectAtIndex:1] intValue] : 0;
- patch = parts.count > 2 ? [[parts objectAtIndex:2] intValue] : 0;
- }
-#elif defined(Q_OS_OSX)
- static GestaltFunction pGestalt = 0;
- if (!pGestalt) {
- CFBundleRef b = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreServices"));
- pGestalt = reinterpret_cast<GestaltFunction>(CFBundleGetFunctionPointerForName(b,
- CFSTR("Gestalt")));
- }
- if (!pGestalt)
- return v;
- if (pGestalt('sys1', &major) != 0)
- return v;
- if (pGestalt('sys2', &minor) != 0)
- return v;
- if (pGestalt('sys3', &patch) != 0)
- return v;
-#endif
-#endif
- v.major = major;
- v.minor = minor;
- v.patch = patch;
- return v;
-}
-
-// -------------------------------------------------------------------------
-
QMacAutoReleasePool::QMacAutoReleasePool()
: pool([[NSAutoreleasePool alloc] init])
{
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index cb709f9d4b..d0edef33a2 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -131,12 +131,6 @@ private:
QString string;
};
-typedef struct {
- int major, minor, patch;
-} QAppleOperatingSystemVersion;
-
-QAppleOperatingSystemVersion qt_apple_os_version();
-
#ifdef Q_OS_OSX
Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
diff --git a/src/corelib/kernel/qdeadlinetimer.cpp b/src/corelib/kernel/qdeadlinetimer.cpp
index d670637d53..99d223ca88 100644
--- a/src/corelib/kernel/qdeadlinetimer.cpp
+++ b/src/corelib/kernel/qdeadlinetimer.cpp
@@ -173,9 +173,9 @@ Q_DECL_CONST_FUNCTION static inline QPair<qint64, qint64> toSecsAndNSecs(qint64
*/
/*!
- \fn QDeadlineTimer::QDeadlineTimer(ForeverConstant foreverConstant, Qt::TimerType timerType)
+ \fn QDeadlineTimer::QDeadlineTimer(ForeverConstant forever, Qt::TimerType timerType)
- QDeadlineTimer objects created with parameter \a foreverConstant never expire.
+ QDeadlineTimer objects created with parameter \a forever never expire.
For such objects, remainingTime() will return -1, deadline() will return the
maximum value, and isForever() will return true.
@@ -341,54 +341,6 @@ void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::Time
*/
/*!
- \fn std::chrono::nanoseconds remainingTimeAsDuration() const
-
- Returns a \c{std::chrono::duration} object of type \c{Duration} containing
- the remaining time in this QDeadlineTimer, if it still has time left. If
- the deadline has passed, this returns \c{Duration::zero()}, whereas if the
- object is set to never expire, it returns \c{Duration::max()} (instead of
- -1).
-
- It is not possible to obtain the overdue time for expired timers with this
- function. To do that, see deadline().
-
- \note The overload of this function without template parameter always
- returns milliseconds.
-
- \sa setRemainingTime(), deadline<Clock, Duration>()
-*/
-
-/*!
- \overload
- \fn std::chrono::time_point<Clock, Duration> QDeadlineTimer::deadline() const
-
- Returns the absolute time point for the deadline stored in QDeadlineTimer
- object as a \c{std::chrono::time_point} object. The template parameter
- \c{Clock} is mandatory and indicates which of the C++ timekeeping clocks to
- use as a reference. The value will be in the past if this QDeadlineTimer
- has expired.
-
- If this QDeadlineTimer never expires, this function returns
- \c{std::chrono::time_point<Clock, Duration>::max()}.
-
- This function can be used to calculate the amount of time a timer is
- overdue, by subtracting the current time point of the reference clock, as
- in the following example:
-
- \code
- auto realTimeLeft = std::chrono::nanoseconds::max();
- auto tp = deadline.deadline<std::chrono::steady_clock>();
- if (tp != std::chrono::steady_clock::max())
- realTimeLeft = tp - std::chrono::steady_clock::now();
- \endcode
-
- \note Timers that were created as expired have an indetermine time point in
- the past as their deadline, so the above calculation may not work.
-
- \sa remainingTime(), deadlineNSecs(), setDeadline()
-*/
-
-/*!
\fn bool QDeadlineTimer::isForever() const
Returns true if this QDeadlineTimer object never expires, false otherwise.
@@ -789,6 +741,30 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
To subtract times of precision greater than 1 millisecond, use addNSecs().
*/
+/*!
+ \fn void QDeadlineTimer::swap(QDeadlineTimer &other)
+
+ Swaps this deadline timer with the \a other deadline timer.
+ */
+
+/*!
+ \fn QDeadlineTimer & QDeadlineTimer::operator=(std::chrono::time_point<Clock, Duration> deadline_)
+
+ Assigns \a deadline_ to this deadline timer.
+ */
+
+/*!
+ \fn QDeadlineTimer & QDeadlineTimer::operator=(std::chrono::duration<Rep, Period> remaining)
+
+ Sets this deadline timer to the \a remaining time.
+ */
+
+/*!
+ \fn std::chrono::nanoseconds QDeadlineTimer::remainingTimeAsDuration() const
+
+ Returns the time remaining before the deadline.
+ */
+
// the rest of the functions are in qelapsedtimer_xxx.cpp
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index 1a0efae2dc..75ac104155 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -42,6 +42,7 @@
#include "qcoreapplication.h"
#include <private/qsystemlibrary_p.h>
+#include "qoperatingsystemversion.h"
#include "qpair.h"
#include "qset.h"
#include "qsocketnotifier.h"
@@ -236,7 +237,7 @@ static inline UINT inputTimerMask()
// QTBUG 28513, QTBUG-29097, QTBUG-29435: QS_TOUCH, QS_POINTER became part of
// QS_INPUT in Windows Kit 8. They should not be used when running on pre-Windows 8.
#if WINVER > 0x0601
- if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8)
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8)
result &= ~(QS_TOUCH | QS_POINTER);
#endif // WINVER > 0x0601
return result;
@@ -1058,4 +1059,11 @@ void QEventDispatcherWin32::sendPostedEvents()
QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
}
+HWND QEventDispatcherWin32::internalHwnd()
+{
+ Q_D(QEventDispatcherWin32);
+ createInternalHwnd();
+ return d->internalHwnd;
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h
index 773315c04f..227fcf89ff 100644
--- a/src/corelib/kernel/qeventdispatcher_win_p.h
+++ b/src/corelib/kernel/qeventdispatcher_win_p.h
@@ -106,6 +106,8 @@ public:
bool event(QEvent *e);
+ HWND internalHwnd();
+
protected:
QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent = 0);
virtual void sendPostedEvents();
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 63b02d2c0c..fd1c767b4c 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -147,12 +147,13 @@ static inline QMutex *signalSlotLock(const QObject *o)
uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)]);
}
-// ### Qt >= 5.6, remove qt_add/removeObject
+#if QT_VERSION < 0x60000
extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
{}
extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
{}
+#endif
struct QConnectionSenderSwitcher {
QObject *receiver;
@@ -754,30 +755,6 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
\sa {Object Trees & Ownership}
*/
-/*!
- \relates QObject
-
- Returns a pointer to the object named \a name that inherits \a
- type and with a given \a parent.
-
- Returns 0 if there is no such child.
-
- \snippet code/src_corelib_kernel_qobject.cpp 0
-*/
-
-void *qt_find_obj_child(QObject *parent, const char *type, const QString &name)
-{
- QObjectList list = parent->children();
- if (list.size() == 0) return 0;
- for (int i = 0; i < list.size(); ++i) {
- QObject *obj = list.at(i);
- if (name == obj->objectName() && obj->inherits(type))
- return obj;
- }
- return 0;
-}
-
-
/*****************************************************************************
QObject member functions
*****************************************************************************/
@@ -835,7 +812,9 @@ QObject::QObject(QObject *parent)
QT_RETHROW;
}
}
+#if QT_VERSION < 0x60000
qt_addObject(this);
+#endif
if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
}
@@ -868,7 +847,9 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent)
QT_RETHROW;
}
}
+#if QT_VERSION < 0x60000
qt_addObject(this);
+#endif
if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
}
@@ -1040,7 +1021,9 @@ QObject::~QObject()
if (!d->children.isEmpty())
d->deleteChildren();
+#if QT_VERSION < 0x60000
qt_removeObject(this);
+#endif
if (Q_UNLIKELY(qtHookData[QHooks::RemoveQObject]))
reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject])(this);
@@ -3941,9 +3924,8 @@ QList<QByteArray> QObject::dynamicPropertyNames() const
QObject debugging output routines.
*****************************************************************************/
-static void dumpRecursive(int level, QObject *object)
+static void dumpRecursive(int level, const QObject *object)
{
-#if defined(QT_DEBUG)
if (object) {
QByteArray buf;
buf.fill(' ', level / 2 * 8);
@@ -3972,45 +3954,65 @@ static void dumpRecursive(int level, QObject *object)
dumpRecursive(level+1, children.at(i));
}
}
-#else
- Q_UNUSED(level)
- Q_UNUSED(object)
-#endif
}
/*!
- Dumps a tree of children to the debug output.
+ \overload
+ \obsolete
- This function is useful for debugging, but does nothing if the
- library has been compiled in release mode (i.e. without debugging
- information).
+ Dumps a tree of children to the debug output.
\sa dumpObjectInfo()
*/
void QObject::dumpObjectTree()
{
+ const_cast<const QObject *>(this)->dumpObjectTree();
+}
+
+/*!
+ Dumps a tree of children to the debug output.
+
+ \note before Qt 5.9, this function was not const.
+
+ \sa dumpObjectInfo()
+*/
+
+void QObject::dumpObjectTree() const
+{
dumpRecursive(0, this);
}
/*!
+ \overload
+ \obsolete
+
Dumps information about signal connections, etc. for this object
to the debug output.
- This function is useful for debugging, but does nothing if the
- library has been compiled in release mode (i.e. without debugging
- information).
-
\sa dumpObjectTree()
*/
void QObject::dumpObjectInfo()
{
-#if defined(QT_DEBUG)
+ const_cast<const QObject *>(this)->dumpObjectInfo();
+}
+
+/*!
+ Dumps information about signal connections, etc. for this object
+ to the debug output.
+
+ \note before Qt 5.9, this function was not const.
+
+ \sa dumpObjectTree()
+*/
+
+void QObject::dumpObjectInfo() const
+{
qDebug("OBJECT %s::%s", metaObject()->className(),
objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
- Q_D(QObject);
+ Q_D(const QObject);
QMutexLocker locker(signalSlotLock(this));
// first, look for connections where this object is the sender
@@ -4066,7 +4068,6 @@ void QObject::dumpObjectInfo()
} else {
qDebug(" <None>");
}
-#endif
}
#ifndef QT_NO_USERDATA
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index 69b70ad6ec..25acdefeaf 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -375,8 +375,12 @@ public:
#endif //Q_QDOC
- void dumpObjectTree();
- void dumpObjectInfo();
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ void dumpObjectTree(); // ### Qt 6: remove
+ void dumpObjectInfo(); // ### Qt 6: remove
+#endif
+ void dumpObjectTree() const;
+ void dumpObjectInfo() const;
#ifndef QT_NO_PROPERTIES
bool setProperty(const char *name, const QVariant &value);
diff --git a/src/corelib/kernel/qsystemsemaphore_systemv.cpp b/src/corelib/kernel/qsystemsemaphore_systemv.cpp
index 1967899a58..83da09da44 100644
--- a/src/corelib/kernel/qsystemsemaphore_systemv.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_systemv.cpp
@@ -72,7 +72,13 @@ QT_BEGIN_NAMESPACE
key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
{
if (key.isEmpty()){
- errorString = QCoreApplication::tr("%1: key is empty", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
+ errorString =
+#if QT_CONFIG(translation)
+ QCoreApplication::tr("%1: key is empty", "QSystemSemaphore")
+#else
+ QString::fromLatin1("%1: key is empty")
+#endif
+ .arg(QLatin1String("QSystemSemaphore::handle:"));
error = QSystemSemaphore::KeyError;
return -1;
}
@@ -84,16 +90,30 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
// Create the file needed for ftok
int built = QSharedMemoryPrivate::createUnixKeyFile(fileName);
if (-1 == built) {
- errorString = QCoreApplication::tr("%1: unable to make key", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
+ errorString =
+#if QT_CONFIG(translation)
+ QCoreApplication::tr("%1: unable to make key", "QSystemSemaphore")
+#else
+ QString::fromLatin1("%1: unable to make key")
+#endif
+ .arg(QLatin1String("QSystemSemaphore::handle:"));
error = QSystemSemaphore::KeyError;
return -1;
}
createdFile = (1 == built);
+#if !defined(QT_NO_SHAREDMEMORY) && !defined(QT_POSIX_IPC) && !defined(Q_OS_ANDROID)
// Get the unix key for the created file
unix_key = qt_safe_ftok(QFile::encodeName(fileName), 'Q');
+#endif
if (-1 == unix_key) {
- errorString = QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
+ errorString =
+#if QT_CONFIG(translation)
+ QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore")
+#else
+ QString::fromLatin1("%1: ftok failed")
+#endif
+ .arg(QLatin1String("QSystemSemaphore::handle:"));
error = QSystemSemaphore::KeyError;
return -1;
}
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 0ffc22d810..4a4d5b9294 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -2914,7 +2914,7 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
static const size_t qCanConvertMatrixMaximumTargetType = 8 * sizeof(*qCanConvertMatrix);
#ifndef QT_BOOTSTRAPPED
-/*!
+/*
Returns \c true if from inherits to.
*/
static bool canConvertMetaObject(const QMetaObject *from, const QMetaObject *to)
diff --git a/src/corelib/kernel/qwineventnotifier.h b/src/corelib/kernel/qwineventnotifier.h
index f17fa059a1..f29f325d13 100644
--- a/src/corelib/kernel/qwineventnotifier.h
+++ b/src/corelib/kernel/qwineventnotifier.h
@@ -42,7 +42,7 @@
#include "QtCore/qobject.h"
-#ifdef Q_OS_WIN
+#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp
index 7693055cc1..20b4461b03 100644
--- a/src/corelib/mimetypes/qmimetypeparser.cpp
+++ b/src/corelib/mimetypes/qmimetypeparser.cpp
@@ -165,7 +165,8 @@ bool QMimeTypeParserBase::parseNumber(const QStringRef &n, int *target, QString
bool ok;
*target = n.toInt(&ok);
if (Q_UNLIKELY(!ok)) {
- *errorMessage = QLatin1String("Not a number '") + n + QLatin1String("'.");
+ if (errorMessage)
+ *errorMessage = QLatin1String("Not a number '") + n + QLatin1String("'.");
return false;
}
return true;
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index 55af7256be..a04536b18b 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -63,6 +63,29 @@ QT_WARNING_POP
static const QArrayData &qt_array_empty = qt_array[0];
static const QArrayData &qt_array_unsharable_empty = qt_array[1];
+static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, size_t headerSize,
+ uint options)
+{
+ // Calculate the byte size
+ // allocSize = objectSize * capacity + headerSize, but checked for overflow
+ // plus padded to grow in size
+ if (options & QArrayData::Grow) {
+ auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
+ capacity = r.elementCount;
+ return r.size;
+ } else {
+ return qCalculateBlockSize(capacity, objectSize, headerSize);
+ }
+}
+
+static QArrayData *reallocateData(QArrayData *header, size_t allocSize, uint options)
+{
+ header = static_cast<QArrayData *>(::realloc(header, allocSize));
+ if (header)
+ header->capacityReserved = bool(options & QArrayData::CapacityReserved);
+ return header;
+}
+
QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
size_t capacity, AllocationOptions options) Q_DECL_NOTHROW
{
@@ -91,18 +114,7 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
if (headerSize > size_t(MaxAllocSize))
return 0;
- // Calculate the byte size
- // allocSize = objectSize * capacity + headerSize, but checked for overflow
- // plus padded to grow in size
- size_t allocSize;
- if (options & Grow) {
- auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
- capacity = r.elementCount;
- allocSize = r.size;
- } else {
- allocSize = qCalculateBlockSize(capacity, objectSize, headerSize);
- }
-
+ size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize));
if (header) {
quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1)
@@ -122,6 +134,21 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
return header;
}
+QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize, size_t capacity,
+ AllocationOptions options) Q_DECL_NOTHROW
+{
+ Q_ASSERT(data);
+ Q_ASSERT(data->isMutable());
+ Q_ASSERT(!data->ref.isShared());
+
+ size_t headerSize = sizeof(QArrayData);
+ size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
+ QArrayData *header = static_cast<QArrayData *>(reallocateData(data, allocSize, options));
+ if (header)
+ header->alloc = capacity;
+ return header;
+}
+
void QArrayData::deallocate(QArrayData *data, size_t objectSize,
size_t alignment) Q_DECL_NOTHROW
{
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index 5a369baf08..bc20932cca 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -115,6 +115,9 @@ struct Q_CORE_EXPORT QArrayData
static QArrayData *allocate(size_t objectSize, size_t alignment,
size_t capacity, AllocationOptions options = Default)
Q_DECL_NOTHROW Q_REQUIRED_RESULT;
+ static QArrayData *reallocateUnaligned(QArrayData *data, size_t objectSize,
+ size_t newCapacity, AllocationOptions newOptions = Default)
+ Q_DECL_NOTHROW Q_REQUIRED_RESULT;
static void deallocate(QArrayData *data, size_t objectSize,
size_t alignment) Q_DECL_NOTHROW;
@@ -222,6 +225,14 @@ struct QTypedArrayData
Q_ALIGNOF(AlignmentDummy), capacity, options));
}
+ static QTypedArrayData *reallocateUnaligned(QTypedArrayData *data, size_t capacity,
+ AllocationOptions options = Default)
+ {
+ Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
+ return static_cast<QTypedArrayData *>(QArrayData::reallocateUnaligned(data, sizeof(T),
+ capacity, options));
+ }
+
static void deallocate(QArrayData *data)
{
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 9298472305..7d9c5dc325 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -663,6 +663,20 @@ QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel)
*/
#ifndef QT_NO_COMPRESS
+namespace {
+struct QByteArrayDataDeleter
+{
+ static inline void cleanup(QTypedArrayData<char> *d)
+ { if (d) QTypedArrayData<char>::deallocate(d); }
+};
+}
+
+static QByteArray invalidCompressedData()
+{
+ qWarning("qUncompress: Input data is corrupted");
+ return QByteArray();
+}
+
QByteArray qUncompress(const uchar* data, int nbytes)
{
if (!data) {
@@ -677,53 +691,29 @@ QByteArray qUncompress(const uchar* data, int nbytes)
ulong expectedSize = uint((data[0] << 24) | (data[1] << 16) |
(data[2] << 8) | (data[3] ));
ulong len = qMax(expectedSize, 1ul);
- QScopedPointer<QByteArray::Data, QScopedPointerPodDeleter> d;
+ const ulong maxPossibleSize = MaxAllocSize - sizeof(QByteArray::Data);
+ if (Q_UNLIKELY(len >= maxPossibleSize)) {
+ // QByteArray does not support that huge size anyway.
+ return invalidCompressedData();
+ }
+ QScopedPointer<QByteArray::Data, QByteArrayDataDeleter> d(QByteArray::Data::allocate(expectedSize + 1));
+ if (Q_UNLIKELY(d.data() == nullptr))
+ return invalidCompressedData();
+
+ d->size = expectedSize;
forever {
ulong alloc = len;
- if (len >= (1u << 31u) - sizeof(QByteArray::Data)) {
- //QByteArray does not support that huge size anyway.
- qWarning("qUncompress: Input data is corrupted");
- return QByteArray();
- }
- QByteArray::Data *p = static_cast<QByteArray::Data *>(::realloc(d.data(), sizeof(QByteArray::Data) + alloc + 1));
- if (!p) {
- // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
- qWarning("qUncompress: could not allocate enough memory to uncompress data");
- return QByteArray();
- }
- d.take(); // realloc was successful
- d.reset(p);
- d->offset = sizeof(QByteArrayData);
- d->size = 0; // Shut up valgrind "uninitialized variable" warning
int res = ::uncompress((uchar*)d->data(), &len,
data+4, nbytes-4);
switch (res) {
case Z_OK:
- if (len != alloc) {
- if (len >= (1u << 31u) - sizeof(QByteArray::Data)) {
- //QByteArray does not support that huge size anyway.
- qWarning("qUncompress: Input data is corrupted");
- return QByteArray();
- }
- QByteArray::Data *p = static_cast<QByteArray::Data *>(::realloc(d.data(), sizeof(QByteArray::Data) + len + 1));
- if (!p) {
- // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
- qWarning("qUncompress: could not allocate enough memory to uncompress data");
- return QByteArray();
- }
- d.take(); // realloc was successful
- d.reset(p);
- }
- d->ref.initializeOwned();
+ Q_ASSERT(len <= alloc);
+ Q_UNUSED(alloc);
d->size = len;
- d->alloc = uint(len) + 1u;
- d->capacityReserved = false;
- d->offset = sizeof(QByteArrayData);
d->data()[len] = 0;
-
{
QByteArrayDataPtr dataPtr = { d.take() };
return QByteArray(dataPtr);
@@ -735,6 +725,17 @@ QByteArray qUncompress(const uchar* data, int nbytes)
case Z_BUF_ERROR:
len *= 2;
+ if (Q_UNLIKELY(len >= maxPossibleSize)) {
+ // QByteArray does not support that huge size anyway.
+ return invalidCompressedData();
+ } else {
+ // grow the block
+ QByteArray::Data *p = QByteArray::Data::reallocateUnaligned(d.data(), len + 1);
+ if (Q_UNLIKELY(p == nullptr))
+ return invalidCompressedData();
+ d.take(); // don't free
+ d.reset(p);
+ }
continue;
case Z_DATA_ERROR:
@@ -1707,19 +1708,8 @@ void QByteArray::reallocData(uint alloc, Data::AllocationOptions options)
Data::deallocate(d);
d = x;
} else {
- size_t blockSize;
- if (options & Data::Grow) {
- auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data));
- blockSize = r.size;
- alloc = uint(r.elementCount);
- } else {
- blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data));
- }
-
- Data *x = static_cast<Data *>(::realloc(d, blockSize));
+ Data *x = Data::reallocateUnaligned(d, alloc, options);
Q_CHECK_PTR(x);
- x->alloc = alloc;
- x->capacityReserved = (options & Data::CapacityReserved) ? 1 : 0;
d = x;
}
}
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index 477402d6de..6875cbd764 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -252,7 +252,7 @@ public:
void truncate(int pos);
void chop(int n);
-#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP)
+#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) && !defined(Q_CLANG_QDOC)
# if defined(Q_CC_GNU)
// required due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61941
# pragma push_macro("Q_REQUIRED_RESULT")
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index 287861eee8..c820892307 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -424,7 +424,7 @@ QT_BEGIN_NAMESPACE
\enum QChar::Direction
This enum type defines the Unicode direction attributes. See the
- \l{http://www.unicode.org/}{Unicode Standard} for a description
+ \l{http://www.unicode.org/reports/tr9/tr9-35.html#Table_Bidirectional_Character_Types}{Unicode Standard} for a description
of the values.
In order to conform to C/C++ naming conventions "Dir" is prepended
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index a642358770..d52f03acae 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -929,7 +929,7 @@ QString QDate::toString(Qt::DateFormat format) const
*/
QString QDate::toString(const QString& format) const
{
- return QLocale::system().toString(*this, format);
+ return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
}
#endif //QT_NO_DATESTRING
@@ -1333,6 +1333,7 @@ QDate QDate::fromString(const QString &string, const QString &format)
QDate date;
#if QT_CONFIG(timezone)
QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
+ // dt.setDefaultLocale(QLocale::c()); ### Qt 6
if (dt.parseFormat(format))
dt.fromString(string, &date, 0);
#else
@@ -1676,7 +1677,7 @@ QString QTime::toString(Qt::DateFormat format) const
*/
QString QTime::toString(const QString& format) const
{
- return QLocale::system().toString(*this, format);
+ return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
}
#endif //QT_NO_DATESTRING
/*!
@@ -2030,6 +2031,7 @@ QTime QTime::fromString(const QString &string, const QString &format)
QTime time;
#if QT_CONFIG(timezone)
QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
+ // dt.setDefaultLocale(QLocale::c()); ### Qt 6
if (dt.parseFormat(format))
dt.fromString(string, 0, &time);
#else
@@ -2592,7 +2594,7 @@ static void refreshDateTime(QDateTimeData &d)
if (!d->m_timeZone.isValid())
status &= ~QDateTimePrivate::ValidDateTime;
else
- epochMSecs = QDateTimePrivate::zoneMSecsToEpochMSecs(msecs, d->m_timeZone, &testDate, &testTime);
+ epochMSecs = QDateTimePrivate::zoneMSecsToEpochMSecs(msecs, d->m_timeZone, extractDaylightStatus(status), &testDate, &testTime);
}
#endif // timezone
@@ -2913,11 +2915,13 @@ inline QDateTime::Data QDateTimePrivate::create(const QDate &toDate, const QTime
}
// Convert a TimeZone time expressed in zone msecs encoding into a UTC epoch msecs
+// DST transitions are disambiguated by hint.
inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QTimeZone &zone,
+ DaylightStatus hint,
QDate *localDate, QTime *localTime)
{
// Get the effective data from QTimeZone
- QTimeZonePrivate::Data data = zone.d->dataForLocalTime(zoneMSecs);
+ QTimeZonePrivate::Data data = zone.d->dataForLocalTime(zoneMSecs, int(hint));
// Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
// but all affected times afterwards will have DST applied.
if (data.atMSecsSinceEpoch >= 0) {
@@ -3530,7 +3534,8 @@ qint64 QDateTime::toMSecsSinceEpoch() const
#if !QT_CONFIG(timezone)
return 0;
#else
- return QDateTimePrivate::zoneMSecsToEpochMSecs(d->m_msecs, d->m_timeZone);
+ return QDateTimePrivate::zoneMSecsToEpochMSecs(d->m_msecs, d->m_timeZone,
+ extractDaylightStatus(getStatus(d)));
#endif
}
Q_UNREACHABLE();
@@ -3629,10 +3634,16 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs)
// Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
// but all affected times afterwards will have DST applied.
d.detach();
- if (msecs >= 0)
+ if (msecs >= 0) {
+ status = mergeDaylightStatus(status,
+ d->m_timeZone.d->isDaylightTime(msecs)
+ ? QDateTimePrivate::DaylightTime
+ : QDateTimePrivate::StandardTime);
d->m_offsetFromUtc = d->m_timeZone.d->offsetFromUtc(msecs);
- else
+ } else {
+ status = mergeDaylightStatus(status, QDateTimePrivate::StandardTime);
d->m_offsetFromUtc = d->m_timeZone.d->standardTimeOffset(msecs);
+ }
msecs = msecs + (d->m_offsetFromUtc * 1000);
status = status
| QDateTimePrivate::ValidDate
@@ -3896,7 +3907,7 @@ QString QDateTime::toString(Qt::DateFormat format) const
*/
QString QDateTime::toString(const QString& format) const
{
- return QLocale::system().toString(*this, format);
+ return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
}
#endif //QT_NO_DATESTRING
@@ -3920,7 +3931,10 @@ static inline void massageAdjustedDateTime(const QDateTimeData &d, QDate *date,
localMSecsToEpochMSecs(timeToMSecs(*date, *time), &status, date, time);
#if QT_CONFIG(timezone)
} else if (spec == Qt::TimeZone) {
- QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time), d->m_timeZone, date, time);
+ QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time),
+ d->m_timeZone,
+ QDateTimePrivate::UnknownDaylightTime,
+ date, time);
#endif // timezone
}
}
@@ -4950,6 +4964,7 @@ QDateTime QDateTime::fromString(const QString &string, const QString &format)
QDate date;
QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
+ // dt.setDefaultLocale(QLocale::c()); ### Qt 6
if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
return QDateTime(date, time);
#else
diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h
index eb33dddbb7..a217990c8d 100644
--- a/src/corelib/tools/qdatetime_p.h
+++ b/src/corelib/tools/qdatetime_p.h
@@ -134,6 +134,7 @@ public:
#if QT_CONFIG(timezone)
static qint64 zoneMSecsToEpochMSecs(qint64 msecs, const QTimeZone &zone,
+ DaylightStatus hint = UnknownDaylightTime,
QDate *localDate = 0, QTime *localTime = 0);
#endif // timezone
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index f499681ca9..77f7ba963b 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -2018,6 +2018,8 @@ QString QLocale::toString(double i, char f, int prec) const
flags |= QLocaleData::ThousandsGroup;
if (!(d->m_numberOptions & OmitLeadingZeroInExponent))
flags |= QLocaleData::ZeroPadExponent;
+ if (d->m_numberOptions & IncludeTrailingZeroesAfterDot)
+ flags |= QLocaleData::AddTrailingZeroes;
return d->m_data->doubleToString(i, prec, form, -1, flags);
}
@@ -2779,7 +2781,7 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
reinterpret_cast<ushort *>(digits.data())[i] += z;
}
- bool always_show_decpt = (flags & Alternate || flags & ForcePoint);
+ bool always_show_decpt = (flags & ForcePoint);
switch (form) {
case DFExponent: {
num_str = exponentForm(_zero, decimal, exponential, group, plus, minus,
@@ -2794,7 +2796,7 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
break;
}
case DFSignificantDigits: {
- PrecisionMode mode = (flags & Alternate) ?
+ PrecisionMode mode = (flags & AddTrailingZeroes) ?
PMSignificantDigits : PMChopTrailingZeros;
int cutoff = precision < 0 ? 6 : precision;
@@ -2899,7 +2901,7 @@ QString QLocaleData::longLongToString(const QChar zero, const QChar group,
for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
- if ((flags & Alternate || flags & ShowBase)
+ if ((flags & ShowBase)
&& base == 8
&& (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0')))
num_str.prepend(QLatin1Char('0'));
@@ -2920,10 +2922,10 @@ QString QLocaleData::longLongToString(const QChar zero, const QChar group,
--num_pad_chars;
// leave space for optional '0x' in hex form
- if (base == 16 && (flags & Alternate || flags & ShowBase))
+ if (base == 16 && (flags & ShowBase))
num_pad_chars -= 2;
// leave space for optional '0b' in binary form
- else if (base == 2 && (flags & Alternate || flags & ShowBase))
+ else if (base == 2 && (flags & ShowBase))
num_pad_chars -= 2;
for (int i = 0; i < num_pad_chars; ++i)
@@ -2933,9 +2935,9 @@ QString QLocaleData::longLongToString(const QChar zero, const QChar group,
if (flags & CapitalEorX)
num_str = num_str.toUpper();
- if (base == 16 && (flags & Alternate || flags & ShowBase))
+ if (base == 16 && (flags & ShowBase))
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
- if (base == 2 && (flags & Alternate || flags & ShowBase))
+ if (base == 2 && (flags & ShowBase))
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
// add sign
@@ -2984,7 +2986,7 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
if (zeroPadding > 0)
num_str.prepend(QString(zeroPadding, resultZero));
- if ((flags & Alternate || flags & ShowBase)
+ if ((flags & ShowBase)
&& base == 8
&& (num_str.isEmpty() || num_str.at(0).unicode() != QLatin1Char('0')))
num_str.prepend(QLatin1Char('0'));
@@ -2999,10 +3001,10 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
int num_pad_chars = width - num_str.length();
// leave space for optional '0x' in hex form
- if (base == 16 && flags & Alternate)
+ if (base == 16 && flags & ShowBase)
num_pad_chars -= 2;
// leave space for optional '0b' in binary form
- else if (base == 2 && flags & Alternate)
+ else if (base == 2 && flags & ShowBase)
num_pad_chars -= 2;
if (num_pad_chars > 0)
@@ -3012,9 +3014,9 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
if (flags & CapitalEorX)
num_str = num_str.toUpper();
- if (base == 16 && (flags & Alternate || flags & ShowBase))
+ if (base == 16 && flags & ShowBase)
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
- else if (base == 2 && (flags & Alternate || flags & ShowBase))
+ else if (base == 2 && flags & ShowBase)
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
// add sign
@@ -3075,25 +3077,37 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOpti
out = in.toLatin1();
else
break;
+ } else if (out == '.') {
+ // Fail if more than one decimal point or point after e
+ if (decpt_idx != -1 || exponent_idx != -1)
+ return false;
+ decpt_idx = idx;
+ } else if (out == 'e' || out == 'E') {
+ exponent_idx = idx;
}
if (number_options & QLocale::RejectLeadingZeroInExponent) {
- if (out == 'e' || out == 'E') {
- exponent_idx = idx;
- } else if (exponent_idx != -1) {
- if (out >= '1' && out <= '9')
- exponent_idx = -1; // leading digit is not 0, forget exponent_idx
- else if (out == '0' && idx < l - 1)
+ if (exponent_idx != -1 && out == '0' && idx < l - 1) {
+ // After the exponent there can only be '+', '-' or digits.
+ // If we find a '0' directly after some non-digit, then that is a leading zero.
+ if (result->last() < '0' || result->last() > '9')
return false;
}
}
+ if (number_options & QLocale::RejectTrailingZeroesAfterDot) {
+ // If we've seen a decimal point and the last character after the exponent is 0, then
+ // that is a trailing zero.
+ if (decpt_idx >= 0 && idx == exponent_idx && result->last() == '0')
+ return false;
+ }
+
if (!(number_options & QLocale::RejectGroupSeparator)) {
if (start_of_digits_idx == -1 && out >= '0' && out <= '9') {
start_of_digits_idx = idx;
} else if (out == ',') {
- // Don't allow group chars after the decimal point
- if (decpt_idx != -1)
+ // Don't allow group chars after the decimal point or exponent
+ if (decpt_idx != -1 || exponent_idx != -1)
return false;
// check distance from the last separator or from the beginning of the digits
@@ -3110,12 +3124,6 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOpti
++idx;
continue;
} else if (out == '.' || out == 'e' || out == 'E') {
- // Fail if more than one decimal point
- if (out == '.' && decpt_idx != -1)
- return false;
- if (decpt_idx == -1)
- decpt_idx = idx;
-
// check distance from the last separator
// ### FIXME: Some locales allow other groupings! See https://en.wikipedia.org/wiki/Thousands_separator
if (last_separator_idx != -1 && idx - last_separator_idx != 4)
@@ -3141,6 +3149,12 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOpti
return false;
}
+ if (number_options & QLocale::RejectTrailingZeroesAfterDot) {
+ // In decimal form, the last character can be a trailing zero if we've seen a decpt.
+ if (decpt_idx != -1 && exponent_idx == -1 && result->last() == '0')
+ return false;
+ }
+
result->append('\0');
return idx == l;
}
diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h
index 657fce9fa1..bd89e48234 100644
--- a/src/corelib/tools/qlocale.h
+++ b/src/corelib/tools/qlocale.h
@@ -897,7 +897,9 @@ public:
OmitGroupSeparator = 0x01,
RejectGroupSeparator = 0x02,
OmitLeadingZeroInExponent = 0x04,
- RejectLeadingZeroInExponent = 0x08
+ RejectLeadingZeroInExponent = 0x08,
+ IncludeTrailingZeroesAfterDot = 0x10,
+ RejectTrailingZeroesAfterDot = 0x20
};
Q_DECLARE_FLAGS(NumberOptions, NumberOption)
diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc
index 8c5711fb5e..d419172356 100644
--- a/src/corelib/tools/qlocale.qdoc
+++ b/src/corelib/tools/qlocale.qdoc
@@ -949,7 +949,8 @@
setNumberOptions().
\value DefaultNumberOptions This option represents the default behavior, with
- group separators and with one leading zero in single digit exponents.
+ group separators, with one leading zero in single digit exponents, and
+ without trailing zeroes after the decimal dot.
\value OmitGroupSeparator If this option is set, the number-to-string functions
will not insert group separators in their return values. The default
is to insert group separators.
@@ -964,6 +965,14 @@
functions will fail if they encounter an exponent padded with zeroes when
parsing a floating point number in scientific notation. The default is to
accept such padding.
+ \value IncludeTrailingZeroesAfterDot If this option is set, the number-to-string
+ functions will pad numbers with zeroes to the requested precision in "g"
+ or "most concise" mode, even if the number of significant digits is lower
+ than the requested precision. The default is to omit trailing zeroes.
+ \value RejectTrailingZeroesAfterDot If this option is set, the string-to-number
+ functions will fail if they encounter trailing zeroes after the decimal
+ dot when parsing a number in scientific or decimal representation. The
+ default is to accept trailing zeroes.
\sa setNumberOptions(), numberOptions()
*/
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index 20eff8fd64..7749f66b8e 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -193,7 +193,7 @@ public:
enum Flags {
NoFlags = 0,
- Alternate = 0x01,
+ AddTrailingZeroes = 0x01,
ZeroPadded = 0x02,
LeftAdjusted = 0x04,
BlankBeforePositive = 0x08,
@@ -204,7 +204,7 @@ public:
ShowBase = 0x80,
UppercaseBase = 0x100,
ZeroPadExponent = 0x200,
- ForcePoint = Alternate
+ ForcePoint = 0x400
};
enum NumberMode { IntegerMode, DoubleStandardMode, DoubleScientificMode };
diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp
index 4a30daa72c..791a4970f0 100644
--- a/src/corelib/tools/qregularexpression.cpp
+++ b/src/corelib/tools/qregularexpression.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2015 Giuseppe D'Angelo <dangelog@gmail.com>.
-** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Copyright (C) 2016 Giuseppe D'Angelo <dangelog@gmail.com>.
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
@@ -45,7 +45,7 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qhashfunctions.h>
-#include <QtCore/qmutex.h>
+#include <QtCore/qreadwritelock.h>
#include <QtCore/qvector.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdebug.h>
@@ -54,7 +54,7 @@
#include <QtCore/qatomic.h>
#include <QtCore/qdatastream.h>
-#include <pcre.h>
+#include <pcre2.h>
QT_BEGIN_NAMESPACE
@@ -548,7 +548,7 @@ QT_BEGIN_NAMESPACE
\inmodule QtCore
\reentrant
- \brief The QRegularExpressionMatch class provides the results of matching
+ \brief The QRegularExpressionMatch class provides the results of a matching
a QRegularExpression against a string.
\since 5.0
@@ -789,19 +789,19 @@ static int convertToPcreOptions(QRegularExpression::PatternOptions patternOption
int options = 0;
if (patternOptions & QRegularExpression::CaseInsensitiveOption)
- options |= PCRE_CASELESS;
+ options |= PCRE2_CASELESS;
if (patternOptions & QRegularExpression::DotMatchesEverythingOption)
- options |= PCRE_DOTALL;
+ options |= PCRE2_DOTALL;
if (patternOptions & QRegularExpression::MultilineOption)
- options |= PCRE_MULTILINE;
+ options |= PCRE2_MULTILINE;
if (patternOptions & QRegularExpression::ExtendedPatternSyntaxOption)
- options |= PCRE_EXTENDED;
+ options |= PCRE2_EXTENDED;
if (patternOptions & QRegularExpression::InvertedGreedinessOption)
- options |= PCRE_UNGREEDY;
+ options |= PCRE2_UNGREEDY;
if (patternOptions & QRegularExpression::DontCaptureOption)
- options |= PCRE_NO_AUTO_CAPTURE;
+ options |= PCRE2_NO_AUTO_CAPTURE;
if (patternOptions & QRegularExpression::UseUnicodePropertiesOption)
- options |= PCRE_UCP;
+ options |= PCRE2_UCP;
return options;
}
@@ -814,7 +814,9 @@ static int convertToPcreOptions(QRegularExpression::MatchOptions matchOptions)
int options = 0;
if (matchOptions & QRegularExpression::AnchoredMatchOption)
- options |= PCRE_ANCHORED;
+ options |= PCRE2_ANCHORED;
+ if (matchOptions & QRegularExpression::DontCheckSubjectStringMatchOption)
+ options |= PCRE2_NO_UTF_CHECK;
return options;
}
@@ -856,20 +858,16 @@ struct QRegularExpressionPrivate : QSharedData
QRegularExpression::PatternOptions patternOptions;
QString pattern;
- // *All* of the following members are set managed while holding this mutex,
+ // *All* of the following members are 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;
+ mutable QReadWriteLock mutex;
- // The PCRE pointers are reference-counted by the QRegularExpressionPrivate
+ // The PCRE code pointer is reference-counted by the QRegularExpressionPrivate
// objects themselves; when the private is copied (i.e. a detach happened)
// they are set to 0
- pcre16 *compiledPattern;
- QAtomicPointer<pcre16_extra> studyData;
- const char *errorString;
+ pcre2_code_16 *compiledPattern;
+ int errorCode;
int errorOffset;
int capturingCount;
unsigned int usedCount;
@@ -884,8 +882,7 @@ struct QRegularExpressionMatchPrivate : QSharedData
int subjectStart,
int subjectLength,
QRegularExpression::MatchType matchType,
- QRegularExpression::MatchOptions matchOptions,
- int capturingCount = 0);
+ QRegularExpression::MatchOptions matchOptions);
QRegularExpressionMatch nextMatch() const;
@@ -934,10 +931,13 @@ QRegularExpression::QRegularExpression(QRegularExpressionPrivate &dd)
\internal
*/
QRegularExpressionPrivate::QRegularExpressionPrivate()
- : patternOptions(0), pattern(),
+ : QSharedData(),
+ patternOptions(0),
+ pattern(),
mutex(),
- compiledPattern(0), studyData(0),
- errorString(0), errorOffset(-1),
+ compiledPattern(0),
+ errorCode(0),
+ errorOffset(-1),
capturingCount(0),
usedCount(0),
usingCrLfNewlines(false),
@@ -964,13 +964,16 @@ QRegularExpressionPrivate::~QRegularExpressionPrivate()
*/
QRegularExpressionPrivate::QRegularExpressionPrivate(const QRegularExpressionPrivate &other)
: QSharedData(other),
- patternOptions(other.patternOptions), pattern(other.pattern),
+ patternOptions(other.patternOptions),
+ pattern(other.pattern),
mutex(),
- compiledPattern(0), studyData(0),
- errorString(0),
- errorOffset(-1), capturingCount(0),
+ compiledPattern(0),
+ errorCode(0),
+ errorOffset(-1),
+ capturingCount(0),
usedCount(0),
- usingCrLfNewlines(false), isDirty(true)
+ usingCrLfNewlines(false),
+ isDirty(true)
{
}
@@ -979,14 +982,13 @@ QRegularExpressionPrivate::QRegularExpressionPrivate(const QRegularExpressionPri
*/
void QRegularExpressionPrivate::cleanCompiledPattern()
{
- pcre16_free(compiledPattern);
- pcre16_free_study(studyData.load());
- usedCount = 0;
+ pcre2_code_free_16(compiledPattern);
compiledPattern = 0;
- studyData.store(0);
- usingCrLfNewlines = false;
+ errorCode = 0;
errorOffset = -1;
capturingCount = 0;
+ usedCount = 0;
+ usingCrLfNewlines = false;
}
/*!
@@ -994,7 +996,7 @@ void QRegularExpressionPrivate::cleanCompiledPattern()
*/
void QRegularExpressionPrivate::compilePattern()
{
- QMutexLocker lock(&mutex);
+ const QWriteLocker lock(&mutex);
if (!isDirty)
return;
@@ -1003,18 +1005,23 @@ void QRegularExpressionPrivate::compilePattern()
cleanCompiledPattern();
int options = convertToPcreOptions(patternOptions);
- options |= PCRE_UTF16;
+ options |= PCRE2_UTF;
- int errorCode;
- compiledPattern = pcre16_compile2(pattern.utf16(), options,
- &errorCode, &errorString, &errorOffset, 0);
+ PCRE2_SIZE patternErrorOffset;
+ compiledPattern = pcre2_compile_16(pattern.utf16(),
+ pattern.length(),
+ options,
+ &errorCode,
+ &patternErrorOffset,
+ NULL);
- if (!compiledPattern)
+ if (!compiledPattern) {
+ errorOffset = static_cast<int>(patternErrorOffset);
return;
-
- Q_ASSERT(errorCode == 0);
- Q_ASSERT(studyData.load() == 0); // studying (=>optimizing) is always done later
- errorOffset = -1;
+ } else {
+ // ignore whatever PCRE2 wrote into errorCode -- leave it to 0 to mean "no error"
+ errorCode = 0;
+ }
getPatternInfo();
}
@@ -1025,53 +1032,31 @@ void QRegularExpressionPrivate::compilePattern()
void QRegularExpressionPrivate::getPatternInfo()
{
Q_ASSERT(compiledPattern);
- Q_ASSERT(studyData.load() == 0);
- pcre16_fullinfo(compiledPattern, 0, PCRE_INFO_CAPTURECOUNT, &capturingCount);
+ pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_CAPTURECOUNT, &capturingCount);
// detect the settings for the newline
- unsigned long int patternNewlineSetting;
- pcre16_fullinfo(compiledPattern, 0, PCRE_INFO_OPTIONS, &patternNewlineSetting);
- patternNewlineSetting &= PCRE_NEWLINE_CR | PCRE_NEWLINE_LF | PCRE_NEWLINE_CRLF
- | PCRE_NEWLINE_ANY | PCRE_NEWLINE_ANYCRLF;
- if (patternNewlineSetting == 0) {
+ unsigned int patternNewlineSetting;
+ if (pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_NEWLINE, &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;
- }
+ pcre2_config_16(PCRE2_CONFIG_NEWLINE, &patternNewlineSetting);
}
- usingCrLfNewlines = (patternNewlineSetting == PCRE_NEWLINE_CRLF) ||
- (patternNewlineSetting == PCRE_NEWLINE_ANY) ||
- (patternNewlineSetting == PCRE_NEWLINE_ANYCRLF);
+ usingCrLfNewlines = (patternNewlineSetting == PCRE2_NEWLINE_CRLF) ||
+ (patternNewlineSetting == PCRE2_NEWLINE_ANY) ||
+ (patternNewlineSetting == PCRE2_NEWLINE_ANYCRLF);
- int hasJOptionChanged;
- pcre16_fullinfo(compiledPattern, 0, PCRE_INFO_JCHANGED, &hasJOptionChanged);
- if (hasJOptionChanged) {
- qWarning("QRegularExpressionPrivate::getPatternInfo(): the pattern '%s'\n"
- " is using the (?J) option; duplicate capturing group names are not supported by Qt",
+ unsigned int hasJOptionChanged;
+ pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_JCHANGED, &hasJOptionChanged);
+ if (Q_UNLIKELY(hasJOptionChanged)) {
+ qWarning("QRegularExpressionPrivate::getPatternInfo(): the pattern '%s'\n is using the (?J) option; duplicate capturing group names are not supported by Qt",
qPrintable(pattern));
}
}
/*
- Simple "smartpointer" wrapper around a pcre_jit_stack, to be used with
+ Simple "smartpointer" wrapper around a pcre2_jit_stack_16, to be used with
QThreadStorage.
*/
class QPcreJitStackPointer
@@ -1086,7 +1071,7 @@ public:
{
// The default JIT stack size in PCRE is 32K,
// we allocate from 32K up to 512K.
- stack = pcre16_jit_stack_alloc(32*1024, 512*1024);
+ stack = pcre2_jit_stack_create_16(32 * 1024, 512 * 1024, NULL);
}
/*!
\internal
@@ -1094,10 +1079,10 @@ public:
~QPcreJitStackPointer()
{
if (stack)
- pcre16_jit_stack_free(stack);
+ pcre2_jit_stack_free_16(stack);
}
- pcre16_jit_stack *stack;
+ pcre2_jit_stack_16 *stack;
};
Q_GLOBAL_STATIC(QThreadStorage<QPcreJitStackPointer *>, jitStacks)
@@ -1105,7 +1090,7 @@ Q_GLOBAL_STATIC(QThreadStorage<QPcreJitStackPointer *>, jitStacks)
/*!
\internal
*/
-static pcre16_jit_stack *qtPcreCallback(void *)
+static pcre2_jit_stack_16 *qtPcreCallback(void *)
{
if (jitStacks()->hasLocalData())
return jitStacks()->localData()->stack;
@@ -1135,53 +1120,32 @@ 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 qt_qregularexpression_optimize_after_use_count constant) unless
- the DontAutomaticallyOptimizeOption option is set on the QRegularExpression
- object, or anyhow by calling optimize() (which will pass
- ImmediateOptimizeOption).
+ The purpose of the function is to call pcre2_jit_compile_16, which
+ JIT-compiles the pattern.
+
+ It gets called by doMatch() every time a match is performed.
- 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, we work on a local copy
- (localStudyData) before using storeRelease on studyData. In doMatch there's
- the corresponding loadAcquire.
+ As of now, the optimizations on the pattern are performed after a certain
+ number of usages (i.e. the qt_qregularexpression_optimize_after_use_count
+ constant) unless the DontAutomaticallyOptimizeOption option is set on the
+ QRegularExpression object, or anyhow by calling optimize() (which will pass
+ ImmediateOptimizeOption).
*/
void QRegularExpressionPrivate::optimizePattern(OptimizePatternOption option)
{
Q_ASSERT(compiledPattern);
- QMutexLocker lock(&mutex);
+ static const bool enableJit = isJitEnabled();
- if (studyData.load()) // already optimized
+ if (!enableJit)
return;
+ const QWriteLocker lock(&mutex);
+
if ((option == LazyOptimizeOption) && (++usedCount != qt_qregularexpression_optimize_after_use_count))
return;
- static const bool enableJit = isJitEnabled();
-
- int studyOptions = 0;
- if (enableJit)
- studyOptions |= (PCRE_STUDY_JIT_COMPILE | PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE | PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE);
-
- const char *err;
- pcre16_extra * const localStudyData = pcre16_study(compiledPattern, studyOptions, &err);
-
- if (localStudyData && localStudyData->flags & PCRE_EXTRA_EXECUTABLE_JIT)
- pcre16_assign_jit_stack(localStudyData, qtPcreCallback, 0);
-
- if (!localStudyData && err)
- qWarning("QRegularExpressionPrivate::optimizePattern(): pcre_study failed: %s", err);
-
- studyData.storeRelease(localStudyData);
+ pcre2_jit_compile_16(compiledPattern, PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_PARTIAL_HARD);
}
/*!
@@ -1197,7 +1161,7 @@ int QRegularExpressionPrivate::captureIndexForName(const QString &name) const
if (!compiledPattern)
return -1;
- int index = pcre16_get_stringnumber(compiledPattern, name.utf16());
+ int index = pcre2_substring_number_from_name_16(compiledPattern, name.utf16());
if (index >= 0)
return index;
@@ -1207,24 +1171,25 @@ int QRegularExpressionPrivate::captureIndexForName(const QString &name) const
/*!
\internal
- This is a simple wrapper for pcre16_exec for handling the case in which the
+ This is a simple wrapper for pcre2_match_16 for handling the case in which the
JIT runs out of memory. In that case, we allocate a thread-local JIT stack
- and re-run pcre16_exec.
+ and re-run pcre2_match_16.
*/
-static int pcre16SafeExec(const pcre16 *code, const pcre16_extra *extra,
- const unsigned short *subject, int length,
- int startOffset, int options,
- int *ovector, int ovecsize)
+static int safe_pcre2_match_16(const pcre2_code_16 *code,
+ const unsigned short *subject, int length,
+ int startOffset, int options,
+ pcre2_match_data_16 *matchData,
+ pcre2_match_context_16 *matchContext)
{
- int result = pcre16_exec(code, extra, subject, length,
- startOffset, options, ovector, ovecsize);
+ int result = pcre2_match_16(code, subject, length,
+ startOffset, options, matchData, matchContext);
- if (result == PCRE_ERROR_JIT_STACKLIMIT && !jitStacks()->hasLocalData()) {
+ if (result == PCRE2_ERROR_JIT_STACKLIMIT && !jitStacks()->hasLocalData()) {
QPcreJitStackPointer *p = new QPcreJitStackPointer;
jitStacks()->setLocalData(p);
- result = pcre16_exec(code, extra, subject, length,
- startOffset, options, ovector, ovecsize);
+ result = pcre2_match_16(code, subject, length,
+ startOffset, options, matchData, matchContext);
}
return result;
@@ -1273,29 +1238,24 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
QRegularExpression re(*const_cast<QRegularExpressionPrivate *>(this));
+ QRegularExpressionMatchPrivate *priv = new QRegularExpressionMatchPrivate(re, subject,
+ subjectStart, subjectLength,
+ matchType, matchOptions);
+
if (offset < 0 || offset > subjectLength)
- return new QRegularExpressionMatchPrivate(re, subject, subjectStart, subjectLength, matchType, matchOptions);
+ return priv;
- if (!compiledPattern) {
+ if (Q_UNLIKELY(!compiledPattern)) {
qWarning("QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
- return new QRegularExpressionMatchPrivate(re, subject, subjectStart, subjectLength, matchType, matchOptions);
+ return priv;
}
// skip optimizing and doing the actual matching if NoMatch type was requested
if (matchType == QRegularExpression::NoMatch) {
- QRegularExpressionMatchPrivate *priv = new QRegularExpressionMatchPrivate(re, subject,
- subjectStart, subjectLength,
- matchType, matchOptions);
priv->isValid = true;
return priv;
}
- // capturingCount doesn't include the implicit "0" capturing group
- QRegularExpressionMatchPrivate *priv = new QRegularExpressionMatchPrivate(re, subject,
- subjectStart, subjectLength,
- matchType, matchOptions,
- capturingCount + 1);
-
if (!(patternOptions & QRegularExpression::DontAutomaticallyOptimizeOption)) {
const OptimizePatternOption optimizePatternOption =
(patternOptions & QRegularExpression::OptimizeOnFirstUsageOption)
@@ -1306,22 +1266,15 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
const_cast<QRegularExpressionPrivate *>(this)->optimizePattern(optimizePatternOption);
}
- // work with a local copy of the study data, as we are running pcre_exec
- // potentially more than once, and we don't want to run call it
- // with different study data
- const pcre16_extra * const currentStudyData = studyData.loadAcquire();
-
int pcreOptions = convertToPcreOptions(matchOptions);
if (matchType == QRegularExpression::PartialPreferCompleteMatch)
- pcreOptions |= PCRE_PARTIAL_SOFT;
+ pcreOptions |= PCRE2_PARTIAL_SOFT;
else if (matchType == QRegularExpression::PartialPreferFirstMatch)
- pcreOptions |= PCRE_PARTIAL_HARD;
+ pcreOptions |= PCRE2_PARTIAL_HARD;
- if (checkSubjectStringOption == DontCheckSubjectString
- || matchOptions & QRegularExpression::DontCheckSubjectStringMatchOption) {
- pcreOptions |= PCRE_NO_UTF16_CHECK;
- }
+ if (checkSubjectStringOption == DontCheckSubjectString)
+ pcreOptions |= PCRE2_NO_UTF_CHECK;
bool previousMatchWasEmpty = false;
if (previous && previous->hasMatch &&
@@ -1329,25 +1282,28 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
previousMatchWasEmpty = true;
}
- int * const captureOffsets = priv->capturedOffsets.data();
- const int captureOffsetsCount = priv->capturedOffsets.size();
+ pcre2_match_context_16 *matchContext = pcre2_match_context_create_16(NULL);
+ pcre2_jit_stack_assign_16(matchContext, &qtPcreCallback, NULL);
+ pcre2_match_data_16 *matchData = pcre2_match_data_create_from_pattern_16(compiledPattern, NULL);
const unsigned short * const subjectUtf16 = subject.utf16() + subjectStart;
int result;
+ QReadLocker lock(&mutex);
+
if (!previousMatchWasEmpty) {
- result = pcre16SafeExec(compiledPattern, currentStudyData,
- subjectUtf16, subjectLength,
- offset, pcreOptions,
- captureOffsets, captureOffsetsCount);
+ result = safe_pcre2_match_16(compiledPattern,
+ subjectUtf16, subjectLength,
+ offset, pcreOptions,
+ matchData, matchContext);
} else {
- result = pcre16SafeExec(compiledPattern, currentStudyData,
- subjectUtf16, subjectLength,
- offset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED,
- captureOffsets, captureOffsetsCount);
+ result = safe_pcre2_match_16(compiledPattern,
+ subjectUtf16, subjectLength,
+ offset, pcreOptions | PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED,
+ matchData, matchContext);
- if (result == PCRE_ERROR_NOMATCH) {
+ if (result == PCRE2_ERROR_NOMATCH) {
++offset;
if (usingCrLfNewlines
@@ -1360,13 +1316,15 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
++offset;
}
- result = pcre16SafeExec(compiledPattern, currentStudyData,
- subjectUtf16, subjectLength,
- offset, pcreOptions,
- captureOffsets, captureOffsetsCount);
+ result = safe_pcre2_match_16(compiledPattern,
+ subjectUtf16, subjectLength,
+ offset, pcreOptions,
+ matchData, matchContext);
}
}
+ lock.unlock();
+
#ifdef QREGULAREXPRESSION_DEBUG
qDebug() << "Matching" << pattern << "against" << subject
<< "starting at" << subjectStart << "len" << subjectLength
@@ -1386,10 +1344,10 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
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);
+ priv->hasPartialMatch = (result == PCRE2_ERROR_PARTIAL);
+ priv->isValid = (result == PCRE2_ERROR_NOMATCH || result == PCRE2_ERROR_PARTIAL);
- if (result == PCRE_ERROR_PARTIAL) {
+ if (result == PCRE2_ERROR_PARTIAL) {
// partial match:
// leave the start and end capture offsets (i.e. cap(0))
priv->capturedCount = 1;
@@ -1401,6 +1359,35 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
}
}
+ // copy the captured substrings offsets, if any
+ if (priv->capturedCount) {
+ PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_16(matchData);
+ int * const capturedOffsets = priv->capturedOffsets.data();
+
+ for (int i = 0; i < priv->capturedCount * 2; ++i)
+ capturedOffsets[i] = static_cast<int>(ovector[i]);
+
+ // For partial matches, PCRE2 and PCRE1 differ in behavior when lookbehinds
+ // are involved. PCRE2 reports the real begin of the match and the maximum
+ // used lookbehind as distinct information; PCRE1 instead automatically
+ // adjusted ovector[0] to include the maximum lookbehind.
+ //
+ // For instance, given the pattern "\bstring\b", and the subject "a str":
+ // * PCRE1 reports partial, capturing " str"
+ // * PCRE2 reports partial, capturing "str" with a lookbehind of 1
+ //
+ // To keep behavior, emulate PCRE1 here.
+ // (Eventually, we could expose the lookbehind info in a future patch.)
+ if (result == PCRE2_ERROR_PARTIAL) {
+ unsigned int maximumLookBehind;
+ pcre2_pattern_info_16(compiledPattern, PCRE2_INFO_MAXLOOKBEHIND, &maximumLookBehind);
+ capturedOffsets[0] -= maximumLookBehind;
+ }
+ }
+
+ pcre2_match_data_free_16(matchData);
+ pcre2_match_context_free_16(matchContext);
+
return priv;
}
@@ -1412,19 +1399,13 @@ QRegularExpressionMatchPrivate::QRegularExpressionMatchPrivate(const QRegularExp
int subjectStart,
int subjectLength,
QRegularExpression::MatchType matchType,
- QRegularExpression::MatchOptions matchOptions,
- int capturingCount)
+ QRegularExpression::MatchOptions matchOptions)
: regularExpression(re), subject(subject),
subjectStart(subjectStart), subjectLength(subjectLength),
matchType(matchType), matchOptions(matchOptions),
capturedCount(0),
hasMatch(false), hasPartialMatch(false), isValid(false)
{
- Q_ASSERT(capturingCount >= 0);
- if (capturingCount > 0) {
- const int captureOffsetsCount = capturingCount * 3;
- capturedOffsets.resize(captureOffsetsCount);
- }
}
@@ -1632,13 +1613,13 @@ QStringList QRegularExpression::namedCaptureGroups() const
// contains one ushort followed by the name, NUL terminated.
// The ushort is the numerical index of the name in the pattern.
// The length of each entry is namedCapturingTableEntrySize.
- ushort *namedCapturingTable;
- int namedCapturingTableEntryCount;
- int namedCapturingTableEntrySize;
+ PCRE2_SPTR16 *namedCapturingTable;
+ unsigned int namedCapturingTableEntryCount;
+ unsigned int namedCapturingTableEntrySize;
- pcre16_fullinfo(d->compiledPattern, 0, PCRE_INFO_NAMETABLE, &namedCapturingTable);
- pcre16_fullinfo(d->compiledPattern, 0, PCRE_INFO_NAMECOUNT, &namedCapturingTableEntryCount);
- pcre16_fullinfo(d->compiledPattern, 0, PCRE_INFO_NAMEENTRYSIZE, &namedCapturingTableEntrySize);
+ pcre2_pattern_info_16(d->compiledPattern, PCRE2_INFO_NAMETABLE, &namedCapturingTable);
+ pcre2_pattern_info_16(d->compiledPattern, PCRE2_INFO_NAMECOUNT, &namedCapturingTableEntryCount);
+ pcre2_pattern_info_16(d->compiledPattern, PCRE2_INFO_NAMEENTRYSIZE, &namedCapturingTableEntrySize);
QStringList result;
@@ -1647,9 +1628,9 @@ QStringList QRegularExpression::namedCaptureGroups() const
for (int i = 0; i < d->capturingCount + 1; ++i)
result.append(QString());
- for (int i = 0; i < namedCapturingTableEntryCount; ++i) {
- const ushort * const currentNamedCapturingTableRow = namedCapturingTable +
- namedCapturingTableEntrySize * i;
+ for (unsigned int i = 0; i < namedCapturingTableEntryCount; ++i) {
+ const ushort * const currentNamedCapturingTableRow =
+ reinterpret_cast<const ushort *>(namedCapturingTable) + namedCapturingTableEntrySize * i;
const int index = *currentNamedCapturingTableRow;
result[index] = QString::fromUtf16(currentNamedCapturingTableRow + 1);
@@ -1680,8 +1661,19 @@ bool QRegularExpression::isValid() const
QString QRegularExpression::errorString() const
{
d.data()->compilePattern();
- if (d->errorString)
- return QCoreApplication::translate("QRegularExpression", d->errorString);
+ if (d->errorCode) {
+ QString errorString;
+ int errorStringLength;
+ do {
+ errorString.resize(errorString.length() + 64);
+ errorStringLength = pcre2_get_error_message_16(d->errorCode,
+ reinterpret_cast<ushort *>(errorString.data()),
+ errorString.length());
+ } while (errorStringLength < 0);
+ errorString.resize(errorStringLength);
+
+ return QCoreApplication::translate("QRegularExpression", errorString.toLatin1().constData());
+ }
return QCoreApplication::translate("QRegularExpression", "no error");
}
@@ -2583,7 +2575,8 @@ QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match)
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
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2015 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -2625,80 +2618,149 @@ static const char *pcreCompileErrorCodes[] =
QT_TRANSLATE_NOOP("QRegularExpression", "missing terminating ] for character class"),
QT_TRANSLATE_NOOP("QRegularExpression", "invalid escape sequence in character class"),
QT_TRANSLATE_NOOP("QRegularExpression", "range out of order in character class"),
- QT_TRANSLATE_NOOP("QRegularExpression", "nothing to repeat"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "quantifier does not follow a repeatable item"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unexpected repeat"),
QT_TRANSLATE_NOOP("QRegularExpression", "unrecognized character after (? or (?-"),
QT_TRANSLATE_NOOP("QRegularExpression", "POSIX named classes are supported only within a class"),
- QT_TRANSLATE_NOOP("QRegularExpression", "missing )"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "POSIX collating elements are not supported"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "missing closing parenthesis"),
QT_TRANSLATE_NOOP("QRegularExpression", "reference to non-existent subpattern"),
- QT_TRANSLATE_NOOP("QRegularExpression", "erroffset passed as NULL"),
- QT_TRANSLATE_NOOP("QRegularExpression", "unknown option bit(s) set"),
- QT_TRANSLATE_NOOP("QRegularExpression", "missing ) after comment"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "pattern passed as NULL"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "unrecognised compile-time option bit(s)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "missing ) after (?# comment"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "parentheses are too deeply nested"),
QT_TRANSLATE_NOOP("QRegularExpression", "regular expression is too large"),
- QT_TRANSLATE_NOOP("QRegularExpression", "failed to get memory"),
- QT_TRANSLATE_NOOP("QRegularExpression", "unmatched parentheses"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "failed to allocate heap memory"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "unmatched closing parenthesis"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error: code overflow"),
- QT_TRANSLATE_NOOP("QRegularExpression", "unrecognized character after (?<"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "letter or underscore expected after (?< or (?'"),
QT_TRANSLATE_NOOP("QRegularExpression", "lookbehind assertion is not fixed length"),
QT_TRANSLATE_NOOP("QRegularExpression", "malformed number or name after (?("),
QT_TRANSLATE_NOOP("QRegularExpression", "conditional group contains more than two branches"),
- QT_TRANSLATE_NOOP("QRegularExpression", "assertion expected after (?("),
+ QT_TRANSLATE_NOOP("QRegularExpression", "assertion expected after (?( or (?(?C)"),
QT_TRANSLATE_NOOP("QRegularExpression", "(?R or (?[+-]digits must be followed by )"),
QT_TRANSLATE_NOOP("QRegularExpression", "unknown POSIX class name"),
- QT_TRANSLATE_NOOP("QRegularExpression", "POSIX collating elements are not supported"),
- QT_TRANSLATE_NOOP("QRegularExpression", "this version of PCRE is not compiled with PCRE_UTF8 support"),
- QT_TRANSLATE_NOOP("QRegularExpression", "character value in \\x{...} sequence is too large"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "internal error in pcre2_study(): should not occur"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "this version of PCRE2 does not have Unicode support"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "parentheses are too deeply nested (stack check)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "character code point value in \\x{} or \\o{} is too large"),
QT_TRANSLATE_NOOP("QRegularExpression", "invalid condition (?(0)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "\\C not allowed in lookbehind assertion"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "\\C is not allowed in a lookbehind assertion"),
QT_TRANSLATE_NOOP("QRegularExpression", "PCRE does not support \\L, \\l, \\N{name}, \\U, or \\u"),
- QT_TRANSLATE_NOOP("QRegularExpression", "number after (?C is > 255"),
- QT_TRANSLATE_NOOP("QRegularExpression", "closing ) for (?C expected"),
- QT_TRANSLATE_NOOP("QRegularExpression", "recursive call could loop indefinitely"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "number after (?C is greater than 255"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "closing parenthesis for (?C expected"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "invalid escape sequence in (*VERB) name"),
QT_TRANSLATE_NOOP("QRegularExpression", "unrecognized character after (?P"),
QT_TRANSLATE_NOOP("QRegularExpression", "syntax error in subpattern name (missing terminator)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "two named subpatterns have the same name"),
- QT_TRANSLATE_NOOP("QRegularExpression", "invalid UTF-8 string"),
- QT_TRANSLATE_NOOP("QRegularExpression", "support for \\P, \\p, and \\X has not been compiled"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "two named subpatterns have the same name (PCRE2_DUPNAMES not set)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "group name must start with a non-digit"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "this version of PCRE2 does not have support for \\P, \\p, or \\X"),
QT_TRANSLATE_NOOP("QRegularExpression", "malformed \\P or \\p sequence"),
QT_TRANSLATE_NOOP("QRegularExpression", "unknown property name after \\P or \\p"),
- QT_TRANSLATE_NOOP("QRegularExpression", "subpattern name is too long (maximum 32 characters)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "too many named subpatterns (maximum 10000)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "octal value is greater than \\377 (not in UTF-8 mode)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "subpattern name is too long (maximum " "10000" " characters)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "too many named subpatterns (maximum " "256" ")"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "invalid range in character class"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "octal value is greater than \\377 in 8-bit non-UTF-8 mode"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error: overran compiling workspace"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error: previously-checked referenced subpattern not found"),
QT_TRANSLATE_NOOP("QRegularExpression", "DEFINE group contains more than one branch"),
- QT_TRANSLATE_NOOP("QRegularExpression", "repeating a DEFINE group is not allowed"),
- QT_TRANSLATE_NOOP("QRegularExpression", "inconsistent NEWLINE options"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "missing opening brace after \\o"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unknown newline setting"),
QT_TRANSLATE_NOOP("QRegularExpression", "\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number"),
QT_TRANSLATE_NOOP("QRegularExpression", "a numbered reference must not be zero"),
QT_TRANSLATE_NOOP("QRegularExpression", "an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "(*VERB) not recognized"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "(*VERB) not recognized or malformed"),
QT_TRANSLATE_NOOP("QRegularExpression", "number is too big"),
QT_TRANSLATE_NOOP("QRegularExpression", "subpattern name expected"),
QT_TRANSLATE_NOOP("QRegularExpression", "digit expected after (?+"),
- QT_TRANSLATE_NOOP("QRegularExpression", "] is an invalid data character in JavaScript compatibility mode"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "non-octal character in \\o{} (closing brace missing?)"),
QT_TRANSLATE_NOOP("QRegularExpression", "different names for subpatterns of the same number are not allowed"),
QT_TRANSLATE_NOOP("QRegularExpression", "(*MARK) must have an argument"),
- QT_TRANSLATE_NOOP("QRegularExpression", "this version of PCRE is not compiled with PCRE_UCP support"),
- QT_TRANSLATE_NOOP("QRegularExpression", "\\c must be followed by an ASCII character"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "non-hex character in \\x{} (closing brace missing?)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "\\c must be followed by a printable ASCII character"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "\\c must be followed by a letter or one of [\\]^_?"),
QT_TRANSLATE_NOOP("QRegularExpression", "\\k is not followed by a braced, angle-bracketed, or quoted name"),
QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unknown opcode in find_fixedlength()"),
QT_TRANSLATE_NOOP("QRegularExpression", "\\N is not supported in a class"),
- QT_TRANSLATE_NOOP("QRegularExpression", "too many forward references"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "SPARE ERROR"),
QT_TRANSLATE_NOOP("QRegularExpression", "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "invalid UTF-16 string"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "using UTF is disabled by the application"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "using UCP is disabled by the application"),
QT_TRANSLATE_NOOP("QRegularExpression", "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "character value in \\u.... sequence is too large"),
- QT_TRANSLATE_NOOP("QRegularExpression", "invalid UTF-32 string"),
- QT_TRANSLATE_NOOP("QRegularExpression", "setting UTF is disabled by the application"),
- QT_TRANSLATE_NOOP("QRegularExpression", "non-hex character in \\x{} (closing brace missing?)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "non-octal character in \\o{} (closing brace missing?)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "missing opening brace after \\o"),
- QT_TRANSLATE_NOOP("QRegularExpression", "parentheses are too deeply nested"),
- QT_TRANSLATE_NOOP("QRegularExpression", "invalid range in character class"),
- QT_TRANSLATE_NOOP("QRegularExpression", "group name must start with a non-digit"),
- QT_TRANSLATE_NOOP("QRegularExpression", "parentheses are too deeply nested (stack check)"),
- QT_TRANSLATE_NOOP("QRegularExpression", "digits missing in \\x{} or \\o{}")
+ QT_TRANSLATE_NOOP("QRegularExpression", "character code point value in \\u.... sequence is too large"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "digits missing in \\x{} or \\o{}"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "syntax error in (?(VERSION condition"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "internal error: unknown opcode in auto_possessify()"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "missing terminating delimiter for callout with string argument"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "unrecognized string delimiter follows (?C"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "using \\C is disabled by the application"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "(?| and/or (?J: or (?x: parentheses are too deeply nested"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "using \\C is disabled in this PCRE2 library"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "regular expression is too complicated"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "lookbehind assertion is too long"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "pattern string is longer than the limit set by the application"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "no error"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "no match"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "partial match"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 1 byte missing at end"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 2 bytes missing at end"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 3 bytes missing at end"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 4 bytes missing at end"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 5 bytes missing at end"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: byte 2 top bits not 0x80"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: byte 3 top bits not 0x80"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: byte 4 top bits not 0x80"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: byte 5 top bits not 0x80"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: byte 6 top bits not 0x80"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 5-byte character is not allowed (RFC 3629)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: 6-byte character is not allowed (RFC 3629)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: code points greater than 0x10ffff are not defined"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: code points 0xd800-0xdfff are not defined"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: overlong 2-byte sequence"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: overlong 3-byte sequence"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: overlong 4-byte sequence"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: overlong 5-byte sequence"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: overlong 6-byte sequence"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: isolated byte with 0x80 bit set"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-8 error: illegal byte (0xfe or 0xff)"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-16 error: missing low surrogate at end"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-16 error: invalid low surrogate"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-16 error: isolated low surrogate"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-32 error: code points 0xd800-0xdfff are not defined"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "UTF-32 error: code points greater than 0x10ffff are not defined"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "bad data value"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "patterns do not all use the same character tables"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "magic number missing"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "pattern compiled in wrong mode: 8/16/32-bit error"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "bad offset value"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "bad option value"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "invalid replacement string"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "bad offset into UTF string"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "callout error code"), /* Never returned by PCRE2 itself */
+ QT_TRANSLATE_NOOP("QRegularExpression", "invalid data in workspace for DFA restart"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "too much recursion for DFA matching"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "backreference condition or recursion test is not supported for DFA matching"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "function is not supported for DFA matching"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "pattern contains an item that is not supported for DFA matching"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "workspace size exceeded in DFA matching"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "internal error - pattern overwritten?"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "bad JIT option"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "JIT stack limit reached"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "match limit exceeded"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "no more memory"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "unknown substring"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "non-unique substring name"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "NULL argument passed"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "nested recursion at the same subject position"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "recursion limit exceeded"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "requested value is not available"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "requested value is not set"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "offset limit set without PCRE2_USE_OFFSET_LIMIT"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "bad escape sequence in replacement string"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "expected closing curly bracket in replacement string"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "bad substitution in replacement string"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "match with end before start is not supported"),
+ QT_TRANSLATE_NOOP("QRegularExpression", "too many replacements (more than INT_MAX)")
};
#endif // #if 0
diff --git a/src/corelib/tools/qringbuffer.cpp b/src/corelib/tools/qringbuffer.cpp
index cb11e72435..8fa378e935 100644
--- a/src/corelib/tools/qringbuffer.cpp
+++ b/src/corelib/tools/qringbuffer.cpp
@@ -132,7 +132,6 @@ char *QRingBuffer::reserve(qint64 bytes)
char *writePtr = buffers.last().data() + tail;
bufferSize += bytes;
- Q_ASSERT(bytes < MaxByteArraySize);
tail += int(bytes);
return writePtr;
}
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 8888eced87..8cf058f035 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -491,6 +491,30 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l)
return UnrollTailLoop<7>::exec(l, 0, lambda, lambda);
# endif
#endif
+#if defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64
+ if (l >= 8) {
+ const QChar *end = a + l;
+ const uint16x8_t mask = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 };
+ while (a + 8 < end) {
+ uint16x8_t da = vld1q_u16(reinterpret_cast<const uint16_t *>(a));
+ uint16x8_t db = vld1q_u16(reinterpret_cast<const uint16_t *>(b));
+
+ uint8_t r = ~(uint8_t)vaddvq_u16(vandq_u16(vceqq_u16(da, db), mask));
+ if (r) {
+ // found a different QChar
+ uint idx = qCountTrailingZeroBits(r);
+ return (int)a[idx].unicode() - (int)b[idx].unicode();
+ }
+ a += 8;
+ b += 8;
+ }
+ l &= 7;
+ }
+ const auto &lambda = [=](int i) -> int {
+ return a[i].unicode() - b[i].unicode();
+ };
+ return UnrollTailLoop<7>::exec(l, 0, lambda, lambda);
+#endif // __ARM_NEON__
if (!l)
return 0;
@@ -1617,7 +1641,7 @@ QString::QString(QChar ch)
\internal
*/
-/*! \fn QString &QString::operator=(const Null &)
+/*! \fn QString &QString::operator=(const QString::Null &)
\internal
*/
@@ -1767,17 +1791,11 @@ void QString::resize(int size, QChar fillChar)
void QString::reallocData(uint alloc, bool grow)
{
- size_t blockSize;
- if (grow) {
- auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data));
- blockSize = r.size;
- alloc = uint(r.elementCount);
- } else {
- blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data));
- }
+ auto allocOptions = d->detachFlags();
+ if (grow)
+ allocOptions |= QArrayData::Grow;
if (d->ref.isShared() || IS_RAW_DATA(d)) {
- Data::AllocationOptions allocOptions(d->capacityReserved ? Data::CapacityReserved : 0);
Data *x = Data::allocate(alloc, allocOptions);
Q_CHECK_PTR(x);
x->size = qMin(int(alloc) - 1, d->size);
@@ -1787,11 +1805,9 @@ void QString::reallocData(uint alloc, bool grow)
Data::deallocate(d);
d = x;
} else {
- Data *p = static_cast<Data *>(::realloc(d, blockSize));
+ Data *p = Data::reallocateUnaligned(d, alloc, allocOptions);
Q_CHECK_PTR(p);
d = p;
- d->alloc = alloc;
- d->offset = sizeof(QStringData);
}
}
@@ -4466,11 +4482,11 @@ bool QString::startsWith(const QStringRef &s, Qt::CaseSensitivity cs) const
\sa startsWith()
*/
-bool QString::endsWith(const QString& s, Qt::CaseSensitivity cs) const
+bool QString::endsWith(const QString &s, Qt::CaseSensitivity cs) const
{
return qt_ends_with(isNull() ? 0 : unicode(), size(),
s.isNull() ? 0 : s.unicode(), s.size(), cs);
- }
+}
/*!
\since 4.8
@@ -4887,6 +4903,7 @@ QString QString::fromUcs4(const uint *unicode, int size)
return QUtf32::convertToUnicode((const char *)unicode, size*4, 0);
}
+
/*!
Resizes the string to \a size characters and copies \a unicode
into the string.
@@ -5981,7 +5998,10 @@ static uint parse_flag_characters(const char * &c) Q_DECL_NOTHROW
uint flags = QLocaleData::ZeroPadExponent;
while (true) {
switch (*c) {
- case '#': flags |= QLocaleData::Alternate; break;
+ case '#':
+ flags |= QLocaleData::ShowBase | QLocaleData::AddTrailingZeroes
+ | QLocaleData::ForcePoint;
+ break;
case '0': flags |= QLocaleData::ZeroPadded; break;
case '-': flags |= QLocaleData::LeftAdjusted; break;
case ' ': flags |= QLocaleData::BlankBeforePositive; break;
@@ -6239,7 +6259,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
case 'p': {
void *arg = va_arg(ap, void*);
const quint64 i = reinterpret_cast<quintptr>(arg);
- flags |= QLocaleData::Alternate;
+ flags |= QLocaleData::ShowBase;
subst = QLocaleData::c()->unsLongLongToString(i, precision, 16, width, flags);
++c;
break;
@@ -7814,10 +7834,13 @@ QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillCha
if (d.locale_occurrences > 0) {
QLocale locale;
- if (!(locale.numberOptions() & QLocale::OmitGroupSeparator))
+ const QLocale::NumberOptions numberOptions = locale.numberOptions();
+ if (!(numberOptions & QLocale::OmitGroupSeparator))
flags |= QLocaleData::ThousandsGroup;
- if (!(locale.numberOptions() & QLocale::OmitLeadingZeroInExponent))
+ if (!(numberOptions & QLocale::OmitLeadingZeroInExponent))
flags |= QLocaleData::ZeroPadExponent;
+ if (numberOptions & QLocale::IncludeTrailingZeroesAfterDot)
+ flags |= QLocaleData::AddTrailingZeroes;
locale_arg = locale.d->m_data->doubleToString(a, prec, form, fieldWidth, flags);
}
@@ -8025,33 +8048,12 @@ bool QString::isSimpleText() const
/*! \fn bool QString::isRightToLeft() const
Returns \c true if the string is read right to left.
+
+ \sa QStringRef::isRightToLeft()
*/
bool QString::isRightToLeft() const
{
- const ushort *p = d->data();
- const ushort * const end = p + d->size;
- while (p < end) {
- uint ucs4 = *p;
- if (QChar::isHighSurrogate(ucs4) && p < end - 1) {
- ushort low = p[1];
- if (QChar::isLowSurrogate(low)) {
- ucs4 = QChar::surrogateToUcs4(ucs4, low);
- ++p;
- }
- }
- switch (QChar::direction(ucs4))
- {
- case QChar::DirL:
- return false;
- case QChar::DirR:
- case QChar::DirAL:
- return true;
- default:
- break;
- }
- ++p;
- }
- return false;
+ return QStringRef(this).isRightToLeft();
}
/*! \fn QChar *QString::data()
@@ -9007,7 +9009,7 @@ ownership of it, no memory is freed when instances are destroyed.
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character in
the string.
- \sa cbegin(), end(), rbegin(), rend()
+ \sa cbegin(), constBegin(), end(), constEnd(), rbegin(), rend()
*/
/*!
@@ -9016,7 +9018,16 @@ ownership of it, no memory is freed when instances are destroyed.
Same as begin().
- \sa begin(), cend(), rbegin(), rend()
+ \sa begin(), constBegin(), cend(), constEnd(), rbegin(), rend()
+*/
+
+/*!
+ \fn QStringRef::const_iterator QStringRef::constBegin() const
+ \since 5.9
+
+ Same as begin().
+
+ \sa begin(), cend(), constEnd(), rbegin(), rend()
*/
/*!
@@ -9026,7 +9037,7 @@ ownership of it, no memory is freed when instances are destroyed.
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
character after the last character in the list.
- \sa cbegin(), end(), rbegin(), rend()
+ \sa cbegin(), constBegin(), end(), constEnd(), rbegin(), rend()
*/
/*! \fn QStringRef::const_iterator QStringRef::cend() const
@@ -9034,7 +9045,15 @@ ownership of it, no memory is freed when instances are destroyed.
Same as end().
- \sa end(), cbegin(), rbegin(), rend()
+ \sa end(), constEnd(), cbegin(), constBegin(), rbegin(), rend()
+*/
+
+/*! \fn QStringRef::const_iterator QStringRef::constEnd() const
+ \since 5.9
+
+ Same as end().
+
+ \sa end(), cend(), cbegin(), constBegin(), rbegin(), rend()
*/
/*!
@@ -9944,6 +9963,41 @@ int QStringRef::count(const QStringRef &str, Qt::CaseSensitivity cs) const
}
/*!
+ \since 5.9
+
+ Returns \c true if the string is read right to left.
+
+ \sa QString::isRightToLeft()
+*/
+bool QStringRef::isRightToLeft() const
+{
+ const ushort *p = reinterpret_cast<const ushort*>(unicode());
+ const ushort * const end = p + size();
+ while (p < end) {
+ uint ucs4 = *p;
+ if (QChar::isHighSurrogate(ucs4) && p < end - 1) {
+ ushort low = p[1];
+ if (QChar::isLowSurrogate(low)) {
+ ucs4 = QChar::surrogateToUcs4(ucs4, low);
+ ++p;
+ }
+ }
+ switch (QChar::direction(ucs4))
+ {
+ case QChar::DirL:
+ return false;
+ case QChar::DirR:
+ case QChar::DirAL:
+ return true;
+ default:
+ break;
+ }
+ ++p;
+ }
+ return false;
+}
+
+/*!
\since 4.8
Returns \c true if the string reference starts with \a str; otherwise
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index b50b2ee4e5..08242bff11 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -397,7 +397,7 @@ public:
QString leftJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const Q_REQUIRED_RESULT;
QString rightJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const Q_REQUIRED_RESULT;
-#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP)
+#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) && !defined(Q_CLANG_QDOC)
# if defined(Q_CC_GNU)
// required due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61941
# pragma push_macro("Q_REQUIRED_RESULT")
@@ -522,7 +522,7 @@ public:
const ushort *utf16() const;
-#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP)
+#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) && !defined(Q_CLANG_QDOC)
QByteArray toLatin1() const & Q_REQUIRED_RESULT
{ return toLatin1_helper(*this); }
QByteArray toLatin1() && Q_REQUIRED_RESULT
@@ -1400,7 +1400,8 @@ public:
QStringRef(QStringRef &&other) Q_DECL_NOTHROW : m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {}
QStringRef &operator=(QStringRef &&other) Q_DECL_NOTHROW { return *this = other; }
#endif
- QStringRef &operator=(const QStringRef &other) Q_DECL_NOTHROW {
+ QStringRef &operator=(const QStringRef &other) Q_DECL_NOTHROW
+ {
m_string = other.m_string; m_position = other.m_position;
m_size = other.m_size; return *this;
}
@@ -1449,6 +1450,8 @@ public:
m_size -= n;
}
+ bool isRightToLeft() const;
+
bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@@ -1461,7 +1464,8 @@ public:
inline QStringRef &operator=(const QString *string);
- inline const QChar *unicode() const {
+ inline const QChar *unicode() const
+ {
if (!m_string)
return reinterpret_cast<const QChar *>(QString::Data::sharedNull()->data());
return m_string->unicode() + m_position;
@@ -1471,8 +1475,10 @@ public:
inline const_iterator begin() const { return unicode(); }
inline const_iterator cbegin() const { return unicode(); }
+ inline const_iterator constBegin() const { return unicode(); }
inline const_iterator end() const { return unicode() + size(); }
inline const_iterator cend() const { return unicode() + size(); }
+ inline const_iterator constEnd() const { return unicode() + size(); }
inline const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
inline const_reverse_iterator crbegin() const { return rbegin(); }
inline const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp
index 2ff03eddec..ea8f6d1438 100644
--- a/src/corelib/tools/qtimezoneprivate.cpp
+++ b/src/corelib/tools/qtimezoneprivate.cpp
@@ -49,10 +49,6 @@
QT_BEGIN_NAMESPACE
-enum {
- MSECS_TRAN_WINDOW = 21600000 // 6 hour window for possible recent transitions
-};
-
/*
Static utilities for looking up Windows ID tables
*/
@@ -248,67 +244,206 @@ QTimeZonePrivate::Data QTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
}
// Private only method for use by QDateTime to convert local msecs to epoch msecs
-// TODO Could be platform optimised if needed
-QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs) const
+QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, int hint) const
{
- if (!hasDaylightTime() ||!hasTransitions()) {
- // No DST means same offset for all local msecs
- // Having DST but no transitions means we can't calculate, so use nearest
- return data(forLocalMSecs - (standardTimeOffset(forLocalMSecs) * 1000));
- }
+ if (!hasDaylightTime()) // No DST means same offset for all local msecs
+ return data(forLocalMSecs - standardTimeOffset(forLocalMSecs) * 1000);
- // Get the transition for the local msecs which most of the time should be the right one
- // Only around the transition times might it not be the right one
- Data tran = previousTransition(forLocalMSecs);
- Data nextTran;
-
- // If the local msecs is less than the real local time of the transition
- // then get the previous transition to use instead
- if (forLocalMSecs < tran.atMSecsSinceEpoch + (tran.offsetFromUtc * 1000)) {
- while (tran.atMSecsSinceEpoch != invalidMSecs()
- && forLocalMSecs < tran.atMSecsSinceEpoch + (tran.offsetFromUtc * 1000)) {
- nextTran = tran;
- tran = previousTransition(tran.atMSecsSinceEpoch);
- }
- } else {
- // The zone msecs is after the transition, so check it is before the next tran
- // If not try use the next transition instead
- nextTran = nextTransition(tran.atMSecsSinceEpoch);
+ /*
+ We need a UTC time at which to ask for the offset, in order to be able to
+ add that offset to forLocalMSecs, to get the UTC time we
+ need. Fortunately, no time-zone offset is more than 14 hours; and DST
+ transitions happen (much) more than thirty-two hours apart. So sampling
+ offset sixteen hours each side gives us information we can be sure
+ brackets the correct time and at most one DST transition.
+ */
+ const qint64 sixteenHoursInMSecs(16 * 3600 * 1000);
+ /*
+ Offsets are Local - UTC, positive to the east of Greenwich, negative to
+ the west; DST offset always exceeds standard offset, when DST applies.
+ When we have offsets on either side of a transition, the lower one is
+ standard, the higher is DST.
+
+ Non-DST transitions (jurisdictions changing time-zone and time-zones
+ changing their standard offset, typically) are described below as if they
+ were DST transitions (since these are more usual and familiar); the code
+ mostly concerns itself with offsets from UTC, described in terms of the
+ common case for changes in that. If there is no actual change in offset
+ (e.g. a DST transition cancelled by a standard offset change), this code
+ should handle it gracefully; without transitions, it'll see early == late
+ and take the easy path; with transitions, tran and nextTran get the
+ correct UTC time as atMSecsSinceEpoch so comparing to nextStart selects
+ the right one. In all other cases, the transition changes offset and the
+ reasoning that applies to DST applies just the same. Aside from hinting,
+ the only thing that looks at DST-ness at all, other than inferred from
+ offset changes, is the case without transition data handling an invalid
+ time in the gap that a transition passed over.
+
+ The handling of hint (see below) is apt to go wrong in non-DST
+ transitions. There isn't really a great deal we can hope to do about that
+ without adding yet more unreliable complexity to the heuristics in use for
+ already obscure corner-cases.
+ */
+
+ /*
+ The hint (really a QDateTimePrivate::DaylightStatus) is > 0 if caller
+ thinks we're in DST, 0 if in standard. A value of -2 means never-DST, so
+ should have been handled above; if it slips through, it's wrong but we
+ should probably treat it as standard anyway (never-DST means
+ always-standard, after all). If the hint turns out to be wrong, fall back
+ on trying the other possibility: which makes it harmless to treat -1
+ (meaning unknown) as standard (i.e. try standard first, then try DST). In
+ practice, away from a transition, the only difference hint makes is to
+ which candidate we try first: if the hint is wrong (or unknown and
+ standard fails), we'll try the other candidate and it'll work.
+
+ For the obscure (and invalid) case where forLocalMSecs falls in a
+ spring-forward's missing hour, a common case is that we started with a
+ date/time for which the hint was valid and adjusted it naively; for that
+ case, we should correct the adjustment by shunting across the transition
+ into where hint is wrong. So half-way through the gap, arrived at from
+ the DST side, should be read as an hour earlier, in standard time; but, if
+ arrived at from the standard side, should be read as an hour later, in
+ DST. (This shall be wrong in some cases; for example, when a country
+ changes its transition dates and changing a date/time by more than six
+ months lands it on a transition. However, these cases are even more
+ obscure than those where the heuristic is good.)
+ */
+
+ if (hasTransitions()) {
+ /*
+ We have transitions.
+
+ Each transition gives the offsets to use until the next; so we need the
+ most recent transition before the time forLocalMSecs describes. If it
+ describes a time *in* a transition, we'll need both that transition and
+ the one before it. So find one transition that's probably after (and not
+ much before, otherwise) and another that's definitely before, then work
+ out which one to use. When both or neither work on forLocalMSecs, use
+ hint to disambiguate.
+ */
+
+ // Get a transition definitely before the local MSecs; usually all we need.
+ // Only around the transition times might we need another.
+ Data tran = previousTransition(forLocalMSecs - sixteenHoursInMSecs);
+ Q_ASSERT(forLocalMSecs < 0 || // Pre-epoch TZ info may be unavailable
+ forLocalMSecs >= tran.atMSecsSinceEpoch + tran.offsetFromUtc * 1000);
+ Data nextTran = nextTransition(tran.atMSecsSinceEpoch);
+ /*
+ Now walk those forward until they bracket forLocalMSecs with transitions.
+
+ One of the transitions should then be telling us the right offset to use.
+ In a transition, we need the transition before it (to describe the run-up
+ to the transition) and the transition itself; so we need to stop when
+ nextTran is that transition.
+ */
while (nextTran.atMSecsSinceEpoch != invalidMSecs()
- && forLocalMSecs >= nextTran.atMSecsSinceEpoch + (nextTran.offsetFromUtc * 1000)) {
+ && forLocalMSecs > nextTran.atMSecsSinceEpoch + nextTran.offsetFromUtc * 1000) {
+ Data newTran = nextTransition(nextTran.atMSecsSinceEpoch);
+ if (newTran.atMSecsSinceEpoch == invalidMSecs()
+ || newTran.atMSecsSinceEpoch + newTran.offsetFromUtc * 1000
+ > forLocalMSecs + sixteenHoursInMSecs) {
+ // Definitely not a relevant tansition: too far in the future.
+ break;
+ }
tran = nextTran;
- nextTran = nextTransition(tran.atMSecsSinceEpoch);
+ nextTran = newTran;
}
+
+ // Check we do *really* have transitions for this zone:
+ if (tran.atMSecsSinceEpoch != invalidMSecs()) {
+
+ /*
+ So now tran is definitely before and nextTran is either after or only
+ slightly before. The one with the larger offset is in DST; the other in
+ standard time. Our hint tells us which of those to use (defaulting to
+ standard if no hint): try it first; if that fails, try the other; if both
+ fail life's tricky.
+ */
+ Q_ASSERT(forLocalMSecs < 0
+ || forLocalMSecs > tran.atMSecsSinceEpoch + tran.offsetFromUtc * 1000);
+ const qint64 nextStart = nextTran.atMSecsSinceEpoch;
+ // Work out the UTC values it might make sense to return:
+ nextTran.atMSecsSinceEpoch = forLocalMSecs - nextTran.offsetFromUtc * 1000;
+ tran.atMSecsSinceEpoch = forLocalMSecs - tran.offsetFromUtc * 1000;
+
+ const bool nextIsDst = tran.offsetFromUtc < nextTran.offsetFromUtc;
+ // If that agrees with hint > 0, our first guess is to use nextTran; else tran.
+ const bool nextFirst = nextIsDst == (hint > 0) && nextStart != invalidMSecs();
+ for (int i = 0; i < 2; i++) {
+ /*
+ On the first pass, the case we consider is what hint told us to expect
+ (except when hint was -1 and didn't actually tell us what to expect),
+ so it's likely right. We only get a second pass if the first failed,
+ by which time the second case, that we're trying, is likely right. If
+ an overwhelming majority of calls have hint == -1, the Q_LIKELY here
+ shall be wrong half the time; otherwise, its errors shall be rarer
+ than that.
+ */
+ if (nextFirst ? i == 0 : i) {
+ Q_ASSERT(nextStart != invalidMSecs());
+ if (Q_LIKELY(nextStart <= nextTran.atMSecsSinceEpoch))
+ return nextTran;
+ } else {
+ // If next is invalid, nextFirst is false, to route us here first:
+ if (nextStart == invalidMSecs() || Q_LIKELY(nextStart > tran.atMSecsSinceEpoch))
+ return tran;
+ }
+ }
+
+ /*
+ Neither is valid (e.g. in a spring-forward's gap) and
+ nextTran.atMSecsSinceEpoch < nextStart <= tran.atMSecsSinceEpoch, so
+ 0 < tran.atMSecsSinceEpoch - nextTran.atMSecsSinceEpoch
+ = (nextTran.offsetFromUtc - tran.offsetFromUtc) * 1000
+ */
+ int dstStep = nextTran.offsetFromUtc - tran.offsetFromUtc;
+ Q_ASSERT(dstStep > 0); // How else could we get here ?
+ if (nextFirst) { // hint thought we needed nextTran, so use tran
+ tran.atMSecsSinceEpoch -= dstStep;
+ return tran;
+ }
+ nextTran.atMSecsSinceEpoch += dstStep;
+ return nextTran;
+ }
+ // System has transitions but not for this zone.
+ // Try falling back to offsetFromUtc
}
- if (tran.daylightTimeOffset == 0) {
- // If tran is in StandardTime, then need to check if falls close to either DST transition.
- // If it does, then it may need adjusting for missing hour or for second occurrence
- qint64 diffPrevTran = forLocalMSecs
- - (tran.atMSecsSinceEpoch + (tran.offsetFromUtc * 1000));
- qint64 diffNextTran = nextTran.atMSecsSinceEpoch + (nextTran.offsetFromUtc * 1000)
- - forLocalMSecs;
- if (diffPrevTran >= 0 && diffPrevTran < MSECS_TRAN_WINDOW) {
- // If tran picked is for standard time check if changed from DST in last 6 hours,
- // as the local msecs may be ambiguous and represent two valid utc msecs.
- // If in last 6 hours then get prev tran and if diff falls within the DST offset
- // then use the prev tran as we default to the FirstOccurrence
- // TODO Check if faster to just always get prev tran, or if faster using 6 hour check.
- Data dstTran = previousTransition(tran.atMSecsSinceEpoch);
- if (dstTran.atMSecsSinceEpoch != invalidMSecs()
- && dstTran.daylightTimeOffset > 0 && diffPrevTran < (dstTran.daylightTimeOffset * 1000))
- tran = dstTran;
- } else if (diffNextTran >= 0 && diffNextTran <= (nextTran.daylightTimeOffset * 1000)) {
- // If time falls within last hour of standard time then is actually the missing hour
- // So return the next tran instead and adjust the local time to be valid
- tran = nextTran;
- forLocalMSecs = forLocalMSecs + (nextTran.daylightTimeOffset * 1000);
+ /* Bracket and refine to discover offset. */
+ qint64 utcEpochMSecs;
+
+ int early = offsetFromUtc(forLocalMSecs - sixteenHoursInMSecs);
+ int late = offsetFromUtc(forLocalMSecs + sixteenHoursInMSecs);
+ if (Q_LIKELY(early == late)) { // > 99% of the time
+ utcEpochMSecs = forLocalMSecs - early * 1000;
+ } else {
+ // Close to a DST transition: early > late is near a fall-back,
+ // early < late is near a spring-forward.
+ const int offsetInDst = qMax(early, late);
+ const int offsetInStd = qMin(early, late);
+ // Candidate values for utcEpochMSecs (if forLocalMSecs is valid):
+ const qint64 forDst = forLocalMSecs - offsetInDst * 1000;
+ const qint64 forStd = forLocalMSecs - offsetInStd * 1000;
+ // Best guess at the answer:
+ const qint64 hinted = hint > 0 ? forDst : forStd;
+ if (Q_LIKELY(offsetFromUtc(hinted) == (hint > 0 ? offsetInDst : offsetInStd))) {
+ utcEpochMSecs = hinted;
+ } else if (hint <= 0 && offsetFromUtc(forDst) == offsetInDst) {
+ utcEpochMSecs = forDst;
+ } else if (hint > 0 && offsetFromUtc(forStd) == offsetInStd) {
+ utcEpochMSecs = forStd;
+ } else {
+ // Invalid forLocalMSecs: in spring-forward gap.
+ const int dstStep = daylightTimeOffset(early < late ?
+ forLocalMSecs + sixteenHoursInMSecs :
+ forLocalMSecs - sixteenHoursInMSecs);
+ Q_ASSERT(dstStep); // There can't be a transition without it !
+ utcEpochMSecs = (hint > 0) ? forStd - dstStep : forDst + dstStep;
}
}
- // tran should now hold the right transition offset to use
- tran.atMSecsSinceEpoch = forLocalMSecs - (tran.offsetFromUtc * 1000);
- return tran;
+ return data(utcEpochMSecs);
}
bool QTimeZonePrivate::hasTransitions() const
diff --git a/src/corelib/tools/qtimezoneprivate_android.cpp b/src/corelib/tools/qtimezoneprivate_android.cpp
index 53bf90f01d..e079fa0d63 100644
--- a/src/corelib/tools/qtimezoneprivate_android.cpp
+++ b/src/corelib/tools/qtimezoneprivate_android.cpp
@@ -207,58 +207,6 @@ QTimeZonePrivate::Data QAndroidTimeZonePrivate::previousTransition(qint64 before
return invalidData();
}
-// Since Android does not provide an API to access transitions,
-// dataForLocalTime needs to be reimplemented without direct use of transitions
-QTimeZonePrivate::Data QAndroidTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs) const
-{
- if (!androidTimeZone.isValid()) {
- return invalidData();
- } else {
- qint64 UTCepochMSecs;
-
- // compare the UTC time with standard offset against normal DST offset of one hour
- qint64 standardUTCMSecs(forLocalMSecs - (standardTimeOffset(forLocalMSecs) * 1000));
- qint64 daylightUTCMsecs;
-
- // Check if daylight-saving time applies,
- // checking also for DST boundaries
- if (isDaylightTime(standardUTCMSecs)) {
- // If DST does apply, then standardUTCMSecs will be an hour or so ahead of the real epoch time
- // so check that time
- daylightUTCMsecs = standardUTCMSecs - daylightTimeOffset(standardUTCMSecs)*1000;
- if (isDaylightTime(daylightUTCMsecs)) {
- // DST confirmed
- UTCepochMSecs = daylightUTCMsecs;
- } else {
- // DST has just finished
- UTCepochMSecs = standardUTCMSecs;
- }
- } else {
- // Standard time indicated, but check for a false negative.
- // Would a standard one-hour DST offset indicate DST?
- daylightUTCMsecs = standardUTCMSecs - 3600000; // 3600000 MSECS_PER_HOUR
- if (isDaylightTime(daylightUTCMsecs)) {
- // DST may have just started,
- // but double check against timezone's own DST offset
- // (don't necessarily assume a one-hour offset)
- daylightUTCMsecs = standardUTCMSecs - daylightTimeOffset(daylightUTCMsecs)*1000;
- if (isDaylightTime(daylightUTCMsecs)) {
- // DST confirmed
- UTCepochMSecs = daylightUTCMsecs;
- } else {
- // false positive, apply standard time after all
- UTCepochMSecs = standardUTCMSecs;
- }
- } else {
- // confirmed standard time
- UTCepochMSecs = standardUTCMSecs;
- }
- }
-
- return data(UTCepochMSecs);
- }
-}
-
QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const
{
QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;");
diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/tools/qtimezoneprivate_p.h
index d06784b0f9..c397c18aac 100644
--- a/src/corelib/tools/qtimezoneprivate_p.h
+++ b/src/corelib/tools/qtimezoneprivate_p.h
@@ -123,7 +123,7 @@ public:
virtual bool isDaylightTime(qint64 atMSecsSinceEpoch) const;
virtual Data data(qint64 forMSecsSinceEpoch) const;
- virtual Data dataForLocalTime(qint64 forLocalMSecs) const;
+ Data dataForLocalTime(qint64 forLocalMSecs, int hint) const;
virtual bool hasTransitions() const;
virtual Data nextTransition(qint64 afterMSecsSinceEpoch) const;
@@ -475,8 +475,6 @@ public:
Data nextTransition(qint64 afterMSecsSinceEpoch) const Q_DECL_OVERRIDE;
Data previousTransition(qint64 beforeMSecsSinceEpoch) const Q_DECL_OVERRIDE;
- Data dataForLocalTime(qint64 forLocalMSecs) const Q_DECL_OVERRIDE;
-
QByteArray systemTimeZoneId() const Q_DECL_OVERRIDE;
QList<QByteArray> availableTimeZoneIds() const Q_DECL_OVERRIDE;
diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp
index 10b61c3a40..38dff88919 100644
--- a/src/corelib/tools/qtimezoneprivate_tz.cpp
+++ b/src/corelib/tools/qtimezoneprivate_tz.cpp
@@ -199,7 +199,7 @@ static QVector<QTzTransition> parseTzTransitions(QDataStream &ds, int tzh_timecn
}
} else {
// Parse tzh_timecnt x 4-byte transition times
- int val;
+ qint32 val;
for (int i = 0; i < tzh_timecnt && ds.status() == QDataStream::Ok; ++i) {
ds >> val;
transitions[i].tz_time = val;
@@ -725,19 +725,61 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId)
}
}
- // Now for each transition time calculate our rule and save them
- m_tranTimes.reserve(tranList.count());
- for (const QTzTransition &tz_tran : qAsConst(tranList)) {
+ // Now for each transition time calculate and store our rule:
+ const int tranCount = tranList.count();;
+ m_tranTimes.reserve(tranCount);
+ // The DST offset when in effect: usually stable, usually an hour:
+ int lastDstOff = 3600;
+ for (int i = 0; i < tranCount; i++) {
+ const QTzTransition &tz_tran = tranList.at(i);
QTzTransitionTime tran;
QTzTransitionRule rule;
const QTzType tz_type = typeList.at(tz_tran.tz_typeind);
// Calculate the associated Rule
- if (!tz_type.tz_isdst)
+ if (!tz_type.tz_isdst) {
utcOffset = tz_type.tz_gmtoff;
+ } else if (Q_UNLIKELY(tz_type.tz_gmtoff != utcOffset + lastDstOff)) {
+ /*
+ This might be a genuine change in DST offset, but could also be
+ DST starting at the same time as the standard offset changed. See
+ if DST's end gives a more plausible utcOffset (i.e. one closer to
+ the last we saw, or a simple whole hour):
+ */
+ // Standard offset inferred from net offset and expected DST offset:
+ const int inferStd = tz_type.tz_gmtoff - lastDstOff; // != utcOffset
+ for (int j = i + 1; j < tranCount; j++) {
+ const QTzType new_type = typeList.at(tranList.at(j).tz_typeind);
+ if (!new_type.tz_isdst) {
+ const int newUtc = new_type.tz_gmtoff;
+ if (newUtc == utcOffset) {
+ // DST-end can't help us, avoid lots of messy checks.
+ // else: See if the end matches the familiar DST offset:
+ } else if (newUtc == inferStd) {
+ utcOffset = newUtc;
+ // else: let either end shift us to one hour as DST offset:
+ } else if (tz_type.tz_gmtoff - 3600 == utcOffset) {
+ // Start does it
+ } else if (tz_type.tz_gmtoff - 3600 == newUtc) {
+ utcOffset = newUtc; // End does it
+ // else: prefer whichever end gives DST offset closer to
+ // last, but consider any offset > 0 "closer" than any <= 0:
+ } else if (newUtc < tz_type.tz_gmtoff
+ ? (utcOffset >= tz_type.tz_gmtoff
+ || qAbs(newUtc - inferStd) < qAbs(utcOffset - inferStd))
+ : (utcOffset >= tz_type.tz_gmtoff
+ && qAbs(newUtc - inferStd) < qAbs(utcOffset - inferStd))) {
+ utcOffset = newUtc;
+ }
+ break;
+ }
+ }
+ lastDstOff = tz_type.tz_gmtoff - utcOffset;
+ }
rule.stdOffset = utcOffset;
rule.dstOffset = tz_type.tz_gmtoff - utcOffset;
rule.abbreviationIndex = tz_type.tz_abbrind;
+
// If the rule already exist then use that, otherwise add it
int ruleIndex = m_tranRules.indexOf(rule);
if (ruleIndex == -1) {
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index fa8e07abbc..ab5997635a 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -173,7 +173,7 @@ qtConfig(timezone) {
}
qtConfig(regularexpression) {
- QMAKE_USE_PRIVATE += pcre
+ QMAKE_USE_PRIVATE += pcre2
HEADERS += tools/qregularexpression.h
SOURCES += tools/qregularexpression.cpp
diff --git a/src/dbus/qdbusutil_p.h b/src/dbus/qdbusutil_p.h
index 931a374ad9..2f187687b8 100644
--- a/src/dbus/qdbusutil_p.h
+++ b/src/dbus/qdbusutil_p.h
@@ -69,17 +69,17 @@ namespace Q_DBUS_NO_EXPORT QDBusUtil
Q_DBUS_EXPORT bool isValidInterfaceName(const QString &ifaceName);
Q_DBUS_EXPORT bool isValidUniqueConnectionName(const QStringRef &busName);
- bool inline isValidUniqueConnectionName(const QString &busName) { return isValidUniqueConnectionName(QStringRef(&busName)); }
+ inline bool isValidUniqueConnectionName(const QString &busName) { return isValidUniqueConnectionName(QStringRef(&busName)); }
Q_DBUS_EXPORT bool isValidBusName(const QString &busName);
Q_DBUS_EXPORT bool isValidMemberName(const QStringRef &memberName);
- bool inline isValidMemberName(const QString &memberName) { return isValidMemberName(QStringRef(&memberName)); }
+ inline bool isValidMemberName(const QString &memberName) { return isValidMemberName(QStringRef(&memberName)); }
Q_DBUS_EXPORT bool isValidErrorName(const QString &errorName);
Q_DBUS_EXPORT bool isValidPartOfObjectPath(const QStringRef &path);
- bool inline isValidPartOfObjectPath(const QString &path) { return isValidPartOfObjectPath(QStringRef(&path)); }
+ inline bool isValidPartOfObjectPath(const QString &path) { return isValidPartOfObjectPath(QStringRef(&path)); }
Q_DBUS_EXPORT bool isValidObjectPath(const QString &path);
diff --git a/src/gui/configure.json b/src/gui/configure.json
index f4171a8e9f..7efaaff505 100644
--- a/src/gui/configure.json
+++ b/src/gui/configure.json
@@ -32,6 +32,7 @@
"opengl": { "type": "optionalString", "values": [ "no", "yes", "desktop", "es2", "dynamic" ] },
"opengl-es-2": { "type": "void", "name": "opengl", "value": "es2" },
"opengles3": "boolean",
+ "openvg": "boolean",
"qpa": { "type": "string", "name": "qpa_default_platform" },
"qpa-platform-guard": "boolean",
"sm": { "type": "boolean", "name": "sessionmanager" },
@@ -193,6 +194,14 @@
{ "type": "makeSpec", "spec": "OPENGL_ES2" }
]
},
+ "openvg": {
+ "label": "OpenVG",
+ "test": "unix/openvg",
+ "sources": [
+ { "type": "pkgConfig", "args": "vg" },
+ { "type": "makeSpec", "spec": "OPENVG" }
+ ]
+ },
"tslib": {
"label": "tslib",
"test": "unix/tslib",
@@ -499,7 +508,7 @@
"kms": {
"label": "KMS",
"condition": "libs.drm",
- "output": [ "publicQtConfig" ]
+ "output": [ "publicQtConfig", "privateFeature" ]
},
"libinput": {
"label": "libinput",
@@ -582,9 +591,14 @@
"condition": "features.opengl-desktop || features.opengl-dynamic || features.opengles2",
"output": [ "publicFeature", "feature" ]
},
+ "openvg": {
+ "label": "OpenVG",
+ "condition": "libs.openvg",
+ "output": [ "publicFeature" ]
+ },
"egl": {
"label": "EGL",
- "condition": "features.opengl && (features.angle || libs.egl)",
+ "condition": "(features.opengl || features.openvg) && (features.angle || libs.egl)",
"output": [ "privateFeature", "feature" ]
},
"egl_x11": {
@@ -1037,6 +1051,8 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla
"gif", "ico", "jpeg", "system-jpeg", "png", "system-png"
]
},
+ "egl",
+ "openvg",
{
"section": "OpenGL",
"entries": [
@@ -1045,7 +1061,6 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla
"args": "angle",
"condition": "config.win32"
},
- "egl",
"opengl-desktop",
{
"type": "feature",
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 0d2f55b1c2..e8f2c878c8 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -137,8 +137,8 @@ static qreal qt_effective_device_pixel_ratio(QWindow *window = 0)
return qApp->devicePixelRatio(); // Don't know which window to target.
}
-QIconPrivate::QIconPrivate()
- : engine(0), ref(1),
+QIconPrivate::QIconPrivate(QIconEngine *e)
+ : engine(e), ref(1),
serialNum(serialNumCounter.fetchAndAddRelaxed(1)),
detach_no(0),
is_mask(false)
@@ -673,9 +673,8 @@ QIcon::QIcon(const QString &fileName)
ownership of the engine.
*/
QIcon::QIcon(QIconEngine *engine)
- :d(new QIconPrivate)
+ :d(new QIconPrivate(engine))
{
- d->engine = engine;
}
/*!
@@ -950,8 +949,7 @@ void QIcon::detach()
d = 0;
return;
} else if (d->ref.load() != 1) {
- QIconPrivate *x = new QIconPrivate;
- x->engine = d->engine->clone();
+ QIconPrivate *x = new QIconPrivate(d->engine->clone());
if (!d->ref.deref())
delete d;
d = x;
@@ -974,10 +972,8 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state)
if (pixmap.isNull())
return;
detach();
- if (!d) {
- d = new QIconPrivate;
- d->engine = new QPixmapIconEngine;
- }
+ if (!d)
+ d = new QIconPrivate(new QPixmapIconEngine);
d->engine->addPixmap(pixmap, mode, state);
}
@@ -1037,8 +1033,7 @@ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State
if (!engine)
engine = iconEngineFromSuffix(fileName, QMimeDatabase().mimeTypeForFile(info).preferredSuffix());
#endif // !QT_NO_MIMETYPE
- d = new QIconPrivate;
- d->engine = engine ? engine : new QPixmapIconEngine;
+ d = new QIconPrivate(engine ? engine : new QPixmapIconEngine);
}
d->engine->addFile(fileName, size, mode, state);
@@ -1240,12 +1235,10 @@ bool QIcon::hasThemeIcon(const QString &name)
*/
void QIcon::setIsMask(bool isMask)
{
- if (!d) {
- d = new QIconPrivate;
- d->engine = new QPixmapIconEngine;
- } else {
+ if (!d)
+ d = new QIconPrivate(new QPixmapIconEngine);
+ else
detach();
- }
d->is_mask = isMask;
}
@@ -1326,22 +1319,17 @@ QDataStream &operator>>(QDataStream &s, QIcon &icon)
QString key;
s >> key;
if (key == QLatin1String("QPixmapIconEngine")) {
- icon.d = new QIconPrivate;
- QIconEngine *engine = new QPixmapIconEngine;
- icon.d->engine = engine;
- engine->read(s);
+ icon.d = new QIconPrivate(new QPixmapIconEngine);
+ icon.d->engine->read(s);
} else if (key == QLatin1String("QIconLoaderEngine")) {
- icon.d = new QIconPrivate;
- QIconEngine *engine = new QIconLoaderEngine();
- icon.d->engine = engine;
- engine->read(s);
+ icon.d = new QIconPrivate(new QIconLoaderEngine());
+ icon.d->engine->read(s);
} else {
const int index = loader()->indexOf(key);
if (index != -1) {
if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(loader()->instance(index))) {
if (QIconEngine *engine= factory->create()) {
- icon.d = new QIconPrivate;
- icon.d->engine = engine;
+ icon.d = new QIconPrivate(engine);
engine->read(s);
} // factory
} // instance
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
index a978a72192..aa358e88af 100644
--- a/src/gui/image/qicon_p.h
+++ b/src/gui/image/qicon_p.h
@@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE
class QIconPrivate
{
public:
- QIconPrivate();
+ explicit QIconPrivate(QIconEngine *e);
~QIconPrivate() {
delete engine;
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 9e911bdcea..7e0922a90a 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -4489,7 +4489,8 @@ QImage QImage::smoothScaled(int w, int h) const {
return src;
}
-static QImage rotated90(const QImage &image) {
+static QImage rotated90(const QImage &image)
+{
QImage out(image.height(), image.width(), image.format());
out.setDotsPerMeterX(image.dotsPerMeterY());
out.setDotsPerMeterY(image.dotsPerMeterX());
@@ -4497,49 +4498,10 @@ static QImage rotated90(const QImage &image) {
out.setColorTable(image.colorTable());
int w = image.width();
int h = image.height();
- switch (image.format()) {
- case QImage::Format_RGB32:
- case QImage::Format_ARGB32:
- case QImage::Format_ARGB32_Premultiplied:
- case QImage::Format_RGBX8888:
- case QImage::Format_RGBA8888:
- case QImage::Format_RGBA8888_Premultiplied:
- case QImage::Format_BGR30:
- case QImage::Format_A2BGR30_Premultiplied:
- case QImage::Format_RGB30:
- case QImage::Format_A2RGB30_Premultiplied:
- qt_memrotate270(reinterpret_cast<const quint32*>(image.bits()),
- w, h, image.bytesPerLine(),
- reinterpret_cast<quint32*>(out.bits()),
- out.bytesPerLine());
- break;
- case QImage::Format_RGB666:
- case QImage::Format_ARGB6666_Premultiplied:
- case QImage::Format_ARGB8565_Premultiplied:
- case QImage::Format_ARGB8555_Premultiplied:
- case QImage::Format_RGB888:
- qt_memrotate270(reinterpret_cast<const quint24*>(image.bits()),
- w, h, image.bytesPerLine(),
- reinterpret_cast<quint24*>(out.bits()),
- out.bytesPerLine());
- break;
- case QImage::Format_RGB555:
- case QImage::Format_RGB16:
- case QImage::Format_ARGB4444_Premultiplied:
- qt_memrotate270(reinterpret_cast<const quint16*>(image.bits()),
- w, h, image.bytesPerLine(),
- reinterpret_cast<quint16*>(out.bits()),
- out.bytesPerLine());
- break;
- case QImage::Format_Alpha8:
- case QImage::Format_Grayscale8:
- case QImage::Format_Indexed8:
- qt_memrotate270(reinterpret_cast<const quint8*>(image.bits()),
- w, h, image.bytesPerLine(),
- reinterpret_cast<quint8*>(out.bits()),
- out.bytesPerLine());
- break;
- default:
+ const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][2];
+ if (memrotate) {
+ memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
+ } else {
for (int y=0; y<h; ++y) {
if (image.colorCount())
for (int x=0; x<w; ++x)
@@ -4548,18 +4510,29 @@ static QImage rotated90(const QImage &image) {
for (int x=0; x<w; ++x)
out.setPixel(h-y-1, x, image.pixel(x, y));
}
- break;
}
return out;
}
+static QImage rotated180(const QImage &image)
+{
+ const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][1];
+ if (!memrotate)
+ return image.mirrored(true, true);
-static QImage rotated180(const QImage &image) {
- return image.mirrored(true, true);
+ QImage out(image.width(), image.height(), image.format());
+ out.setDotsPerMeterX(image.dotsPerMeterY());
+ out.setDotsPerMeterY(image.dotsPerMeterX());
+ if (image.colorCount() > 0)
+ out.setColorTable(image.colorTable());
+ int w = image.width();
+ int h = image.height();
+ memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
+ return out;
}
-
-static QImage rotated270(const QImage &image) {
+static QImage rotated270(const QImage &image)
+{
QImage out(image.height(), image.width(), image.format());
out.setDotsPerMeterX(image.dotsPerMeterY());
out.setDotsPerMeterY(image.dotsPerMeterX());
@@ -4567,49 +4540,10 @@ static QImage rotated270(const QImage &image) {
out.setColorTable(image.colorTable());
int w = image.width();
int h = image.height();
- switch (image.format()) {
- case QImage::Format_RGB32:
- case QImage::Format_ARGB32:
- case QImage::Format_ARGB32_Premultiplied:
- case QImage::Format_RGBX8888:
- case QImage::Format_RGBA8888:
- case QImage::Format_RGBA8888_Premultiplied:
- case QImage::Format_BGR30:
- case QImage::Format_A2BGR30_Premultiplied:
- case QImage::Format_RGB30:
- case QImage::Format_A2RGB30_Premultiplied:
- qt_memrotate90(reinterpret_cast<const quint32*>(image.bits()),
- w, h, image.bytesPerLine(),
- reinterpret_cast<quint32*>(out.bits()),
- out.bytesPerLine());
- break;
- case QImage::Format_RGB666:
- case QImage::Format_ARGB6666_Premultiplied:
- case QImage::Format_ARGB8565_Premultiplied:
- case QImage::Format_ARGB8555_Premultiplied:
- case QImage::Format_RGB888:
- qt_memrotate90(reinterpret_cast<const quint24*>(image.bits()),
- w, h, image.bytesPerLine(),
- reinterpret_cast<quint24*>(out.bits()),
- out.bytesPerLine());
- break;
- case QImage::Format_RGB555:
- case QImage::Format_RGB16:
- case QImage::Format_ARGB4444_Premultiplied:
- qt_memrotate90(reinterpret_cast<const quint16*>(image.bits()),
- w, h, image.bytesPerLine(),
- reinterpret_cast<quint16*>(out.bits()),
- out.bytesPerLine());
- break;
- case QImage::Format_Alpha8:
- case QImage::Format_Grayscale8:
- case QImage::Format_Indexed8:
- qt_memrotate90(reinterpret_cast<const quint8*>(image.bits()),
- w, h, image.bytesPerLine(),
- reinterpret_cast<quint8*>(out.bits()),
- out.bytesPerLine());
- break;
- default:
+ const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][0];
+ if (memrotate) {
+ memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
+ } else {
for (int y=0; y<h; ++y) {
if (image.colorCount())
for (int x=0; x<w; ++x)
@@ -4618,7 +4552,6 @@ static QImage rotated270(const QImage &image) {
for (int x=0; x<w; ++x)
out.setPixel(y, w-x-1, image.pixel(x, y));
}
- break;
}
return out;
}
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index c646ee96b4..d685d50d49 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -39,6 +39,7 @@
#include <private/qdrawhelper_p.h>
#include <private/qguiapplication_p.h>
+#include <private/qcolorprofile_p.h>
#include <private/qsimd_p.h>
#include <private/qimage_p.h>
#include <qendian.h>
@@ -82,23 +83,17 @@ const uchar *qt_get_bitflip_array()
void qGamma_correct_back_to_linear_cs(QImage *image)
{
- const QDrawHelperGammaTables *tables = QGuiApplicationPrivate::instance()->gammaTables();
- if (!tables)
+ const QColorProfile *cp = QGuiApplicationPrivate::instance()->colorProfileForA32Text();
+ if (!cp)
return;
- const uchar *gamma = tables->qt_pow_rgb_gamma;
// gamma correct the pixels back to linear color space...
int h = image->height();
int w = image->width();
for (int y=0; y<h; ++y) {
- uint *pixels = (uint *) image->scanLine(y);
- for (int x=0; x<w; ++x) {
- uint p = pixels[x];
- uint r = gamma[qRed(p)];
- uint g = gamma[qGreen(p)];
- uint b = gamma[qBlue(p)];
- pixels[x] = (r << 16) | (g << 8) | b | 0xff000000;
- }
+ QRgb *pixels = reinterpret_cast<QRgb *>(image->scanLine(y));
+ for (int x=0; x<w; ++x)
+ pixels[x] = cp->toLinear(pixels[x]);
}
}
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 254b8926c8..468523ab9c 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -3887,7 +3887,7 @@ QDebug operator<<(QDebug dbg, const QTouchEvent::TouchPoint &tp)
{
QDebugStateSaver saver(dbg);
dbg.nospace();
- dbg << "TouchPoint(" << tp.id() << " (";
+ dbg << "TouchPoint(" << hex << tp.id() << dec << " (";
QtDebugUtils::formatQRect(dbg, tp.rect());
dbg << ") ";
QtDebugUtils::formatQEnum(dbg, tp.state());
@@ -4417,6 +4417,8 @@ QTouchEvent::~QTouchEvent()
\brief The TouchPoint class provides information about a touch point in a QTouchEvent.
\since 4.6
\inmodule QtGui
+
+ \image touchpoint-metrics.png
*/
/*! \enum TouchPoint::InfoFlag
@@ -4502,7 +4504,7 @@ Qt::TouchPointState QTouchEvent::TouchPoint::state() const
*/
QPointF QTouchEvent::TouchPoint::pos() const
{
- return d->rect.center();
+ return d->pos;
}
/*!
@@ -4517,7 +4519,7 @@ QPointF QTouchEvent::TouchPoint::pos() const
*/
QPointF QTouchEvent::TouchPoint::scenePos() const
{
- return d->sceneRect.center();
+ return d->scenePos;
}
/*!
@@ -4527,7 +4529,7 @@ QPointF QTouchEvent::TouchPoint::scenePos() const
*/
QPointF QTouchEvent::TouchPoint::screenPos() const
{
- return d->screenRect.center();
+ return d->screenPos;
}
/*!
@@ -4650,10 +4652,19 @@ QPointF QTouchEvent::TouchPoint::lastNormalizedPos() const
around the point returned by pos().
\note This function returns an empty rect if the device does not report touch point sizes.
+
+ \obsolete This function is deprecated in 5.9 because it returns the outer bounds
+ of the touchpoint regardless of rotation, whereas a touchpoint is more correctly
+ modeled as an ellipse at position pos() with ellipseDiameters()
+ which are independent of rotation().
+
+ \sa scenePos(), ellipseDiameters()
*/
QRectF QTouchEvent::TouchPoint::rect() const
{
- return d->rect;
+ QRectF ret(QPointF(), d->ellipseDiameters);
+ ret.moveCenter(d->pos);
+ return ret;
}
/*!
@@ -4661,11 +4672,18 @@ QRectF QTouchEvent::TouchPoint::rect() const
\note This function returns an empty rect if the device does not report touch point sizes.
- \sa scenePos(), rect()
+ \obsolete This function is deprecated in 5.9 because it returns the outer bounds
+ of the touchpoint regardless of rotation, whereas a touchpoint is more correctly
+ modeled as an ellipse at position scenePos() with ellipseDiameters()
+ which are independent of rotation().
+
+ \sa scenePos(), ellipseDiameters()
*/
QRectF QTouchEvent::TouchPoint::sceneRect() const
{
- return d->sceneRect;
+ QRectF ret(QPointF(), d->ellipseDiameters);
+ ret.moveCenter(d->scenePos);
+ return ret;
}
/*!
@@ -4673,11 +4691,18 @@ QRectF QTouchEvent::TouchPoint::sceneRect() const
\note This function returns an empty rect if the device does not report touch point sizes.
- \sa screenPos(), rect()
+ \obsolete This function is deprecated because it returns the outer bounds of the
+ touchpoint regardless of rotation, whereas a touchpoint is more correctly
+ modeled as an ellipse at position screenPos() with ellipseDiameters()
+ which are independent of rotation().
+
+ \sa screenPos(), ellipseDiameters()
*/
QRectF QTouchEvent::TouchPoint::screenRect() const
{
- return d->screenRect;
+ QRectF ret(QPointF(), d->ellipseDiameters);
+ ret.moveCenter(d->screenPos);
+ return ret;
}
/*!
@@ -4703,6 +4728,19 @@ qreal QTouchEvent::TouchPoint::rotation() const
}
/*!
+ \since 5.9
+ Returns the width and height of the bounding ellipse of this touch point.
+ The return value is in logical pixels. Most touchscreens do not detect the
+ shape of the contact point, so a null size is the most common value.
+ In other cases the diameters may be nonzero and equal (the ellipse is
+ approximated as a circle).
+*/
+QSizeF QTouchEvent::TouchPoint::ellipseDiameters() const
+{
+ return d->ellipseDiameters;
+}
+
+/*!
Returns a velocity vector for this touch point.
The vector is in the screen's coordinate system, using pixels per seconds for the magnitude.
@@ -4773,7 +4811,7 @@ void QTouchEvent::TouchPoint::setPos(const QPointF &pos)
{
if (d->ref.load() != 1)
d = d->detach();
- d->rect.moveCenter(pos);
+ d->pos = pos;
}
/*! \internal */
@@ -4781,7 +4819,7 @@ void QTouchEvent::TouchPoint::setScenePos(const QPointF &scenePos)
{
if (d->ref.load() != 1)
d = d->detach();
- d->sceneRect.moveCenter(scenePos);
+ d->scenePos = scenePos;
}
/*! \internal */
@@ -4789,7 +4827,7 @@ void QTouchEvent::TouchPoint::setScreenPos(const QPointF &screenPos)
{
if (d->ref.load() != 1)
d = d->detach();
- d->screenRect.moveCenter(screenPos);
+ d->screenPos = screenPos;
}
/*! \internal */
@@ -4864,28 +4902,32 @@ void QTouchEvent::TouchPoint::setLastNormalizedPos(const QPointF &lastNormalized
d->lastNormalizedPos = lastNormalizedPos;
}
-/*! \internal */
+// ### remove the following 3 setRect functions and their usages soon
+/*! \internal \obsolete */
void QTouchEvent::TouchPoint::setRect(const QRectF &rect)
{
if (d->ref.load() != 1)
d = d->detach();
- d->rect = rect;
+ d->pos = rect.center();
+ d->ellipseDiameters = rect.size();
}
-/*! \internal */
+/*! \internal \obsolete */
void QTouchEvent::TouchPoint::setSceneRect(const QRectF &sceneRect)
{
if (d->ref.load() != 1)
d = d->detach();
- d->sceneRect = sceneRect;
+ d->scenePos = sceneRect.center();
+ d->ellipseDiameters = sceneRect.size();
}
-/*! \internal */
+/*! \internal \obsolete */
void QTouchEvent::TouchPoint::setScreenRect(const QRectF &screenRect)
{
if (d->ref.load() != 1)
d = d->detach();
- d->screenRect = screenRect;
+ d->screenPos = screenRect.center();
+ d->ellipseDiameters = screenRect.size();
}
/*! \internal */
@@ -4905,6 +4947,14 @@ void QTouchEvent::TouchPoint::setRotation(qreal angle)
}
/*! \internal */
+void QTouchEvent::TouchPoint::setEllipseDiameters(const QSizeF &dia)
+{
+ if (d->ref.load() != 1)
+ d = d->detach();
+ d->ellipseDiameters = dia;
+}
+
+/*! \internal */
void QTouchEvent::TouchPoint::setVelocity(const QVector2D &v)
{
if (d->ref.load() != 1)
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index a062331bd8..d7b7b636b2 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -870,6 +870,8 @@ public:
qreal pressure() const;
qreal rotation() const;
+ QSizeF ellipseDiameters() const;
+
QVector2D velocity() const;
InfoFlags flags() const;
QVector<QPointF> rawScreenPositions() const;
@@ -890,11 +892,12 @@ public:
void setLastScenePos(const QPointF &lastScenePos);
void setLastScreenPos(const QPointF &lastScreenPos);
void setLastNormalizedPos(const QPointF &lastNormalizedPos);
- void setRect(const QRectF &rect);
- void setSceneRect(const QRectF &sceneRect);
- void setScreenRect(const QRectF &screenRect);
+ void setRect(const QRectF &rect); // deprecated
+ void setSceneRect(const QRectF &sceneRect); // deprecated
+ void setScreenRect(const QRectF &screenRect); // deprecated
void setPressure(qreal pressure);
void setRotation(qreal angle);
+ void setEllipseDiameters(const QSizeF &dia);
void setVelocity(const QVector2D &v);
void setFlags(InfoFlags flags);
void setRawScreenPositions(const QVector<QPointF> &positions);
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index 7e82b9c654..f67284eebb 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -65,8 +65,9 @@ public:
: ref(1),
id(id),
state(Qt::TouchPointReleased),
- pressure(qreal(-1.)),
- rotation(qreal(0.))
+ pressure(-1),
+ rotation(0),
+ ellipseDiameters(0, 0)
{ }
inline QTouchEventTouchPointPrivate *detach()
@@ -82,12 +83,12 @@ public:
int id;
QPointerUniqueId uniqueId;
Qt::TouchPointStates state;
- QRectF rect, sceneRect, screenRect;
- QPointF normalizedPos,
+ QPointF pos, scenePos, screenPos, normalizedPos,
startPos, startScenePos, startScreenPos, startNormalizedPos,
lastPos, lastScenePos, lastScreenPos, lastNormalizedPos;
qreal pressure;
qreal rotation;
+ QSizeF ellipseDiameters;
QVector2D velocity;
QTouchEvent::TouchPoint::InfoFlags flags;
QVector<QPointF> rawScreenPositions;
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index c189c5b068..d3f3827d6e 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -68,8 +68,8 @@
#include <qpalette.h>
#include <qscreen.h>
#include "qsessionmanager.h"
+#include <private/qcolorprofile_p.h>
#include <private/qscreen_p.h>
-#include <private/qdrawhelper_p.h>
#include <QtGui/qgenericpluginfactory.h>
#include <QtGui/qstylehints.h>
@@ -84,6 +84,7 @@
#include "private/qcursor_p.h"
#include "private/qopenglcontext_p.h"
#include "private/qinputdevicemanager_p.h"
+#include "private/qtouchdevice_p.h"
#include "private/qdnd_p.h"
#include <qpa/qplatformthemefactory_p.h>
@@ -817,19 +818,11 @@ bool QGuiApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blocking
for (int i = 0; i < modalWindowList.count(); ++i) {
QWindow *modalWindow = modalWindowList.at(i);
- {
- // check if the modal window is our window or a (transient) parent of our window
- QWindow *w = window;
- while (w) {
- if (w == modalWindow) {
- *blockingWindow = 0;
- return false;
- }
- QWindow *p = w->parent();
- if (!p)
- p = w->transientParent();
- w = p;
- }
+ // A window is not blocked by another modal window if the two are
+ // the same, or if the window is a child of the modal window.
+ if (window == modalWindow || modalWindow->isAncestorOf(window, QWindow::IncludeTransients)) {
+ *blockingWindow = 0;
+ return false;
}
Qt::WindowModality windowModality = modalWindow->modality();
@@ -936,15 +929,25 @@ QWindowList QGuiApplication::topLevelWindows()
{
const QWindowList &list = QGuiApplicationPrivate::window_list;
QWindowList topLevelWindows;
- for (int i = 0; i < list.size(); i++) {
- if (!list.at(i)->parent() && list.at(i)->type() != Qt::Desktop) {
- // Top windows of embedded QAxServers do not have QWindow parents,
- // but they are not true top level windows, so do not include them.
- const bool embedded = list.at(i)->handle() && list.at(i)->handle()->isEmbedded();
- if (!embedded)
- topLevelWindows.prepend(list.at(i));
- }
+ for (int i = 0; i < list.size(); ++i) {
+ QWindow *window = list.at(i);
+ if (!window->isTopLevel())
+ continue;
+
+ // Desktop windows are special, as each individual desktop window
+ // will report that it's a top level window, but we don't want to
+ // include them in the application wide list of top level windows.
+ if (window->type() == Qt::Desktop)
+ continue;
+
+ // Windows embedded in native windows do not have QWindow parents,
+ // but they are not true top level windows, so do not include them.
+ if (window->handle() && window->handle()->isEmbedded())
+ continue;
+
+ topLevelWindows.prepend(window);
}
+
return topLevelWindows;
}
@@ -1519,7 +1522,8 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate()
platform_theme = 0;
delete platform_integration;
platform_integration = 0;
- delete m_gammaTables.load();
+ delete m_a8ColorProfile.load();
+ delete m_a32ColorProfile.load();
window_list.clear();
}
@@ -1954,7 +1958,8 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
points << point;
QEvent::Type type;
- QList<QTouchEvent::TouchPoint> touchPoints = QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, window, &type);
+ QList<QTouchEvent::TouchPoint> touchPoints =
+ QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, window, QTouchDevicePrivate::get(m_fakeTouchDevice)->id, &type);
QWindowSystemInterfacePrivate::TouchEvent fake(window, e->timestamp, type, m_fakeTouchDevice, touchPoints, e->modifiers);
fake.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
@@ -2191,10 +2196,10 @@ void QGuiApplicationPrivate::processThemeChanged(QWindowSystemInterfacePrivate::
void QGuiApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e)
{
- if (e->tlw.isNull())
+ if (e->window.isNull())
return;
- QWindow *window = e->tlw.data();
+ QWindow *window = e->window.data();
if (!window)
return;
@@ -2559,7 +2564,10 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
Q_ASSERT(w.data() != 0);
// make the *scene* functions return the same as the *screen* functions
- touchPoint.d->sceneRect = touchPoint.screenRect();
+ // Note: touchPoint is a reference to the one from activeTouchPoints,
+ // so we can modify it as long as we're careful NOT to call setters and
+ // otherwise NOT to cause the d-pointer to be detached.
+ touchPoint.d->scenePos = touchPoint.screenPos();
touchPoint.d->startScenePos = touchPoint.startScreenPos();
touchPoint.d->lastScenePos = touchPoint.lastScreenPos();
@@ -2615,8 +2623,8 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
QTouchEvent touchEvent(eventType,
e->device,
e->modifiers,
- it.value().first,
- it.value().second);
+ it.value().first, // state flags
+ it.value().second); // list of touchpoints
touchEvent.setTimestamp(e->timestamp);
touchEvent.setWindow(w);
@@ -2625,13 +2633,14 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
QTouchEvent::TouchPoint &touchPoint = touchEvent._touchPoints[i];
// preserve the sub-pixel resolution
- QRectF rect = touchPoint.screenRect();
- const QPointF screenPos = rect.center();
+ const QPointF screenPos = touchPoint.screenPos();
const QPointF delta = screenPos - screenPos.toPoint();
- rect.moveCenter(w->mapFromGlobal(screenPos.toPoint()) + delta);
- touchPoint.d->rect = rect;
+ touchPoint.d->pos = w->mapFromGlobal(screenPos.toPoint()) + delta;
if (touchPoint.state() == Qt::TouchPointPressed) {
+ // touchPoint is actually a reference to one that is stored in activeTouchPoints,
+ // and we are now going to store the startPos and lastPos there, for the benefit
+ // of future moves and releases. It's important that the d-pointer is NOT detached.
touchPoint.d->startPos = w->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta;
touchPoint.d->lastPos = w->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta;
}
@@ -3671,14 +3680,30 @@ void QGuiApplicationPrivate::notifyDragStarted(const QDrag *drag)
}
#endif
-const QDrawHelperGammaTables *QGuiApplicationPrivate::gammaTables()
+const QColorProfile *QGuiApplicationPrivate::colorProfileForA8Text()
+{
+#ifdef Q_OS_WIN
+ QColorProfile *result = m_a8ColorProfile.load();
+ if (!result){
+ QColorProfile *cs = QColorProfile::fromGamma(2.31); // This is a hard-coded thing for Windows text rendering
+ if (!m_a8ColorProfile.testAndSetRelease(0, cs))
+ delete cs;
+ result = m_a8ColorProfile.load();
+ }
+ return result;
+#else
+ return colorProfileForA32Text();
+#endif
+}
+
+const QColorProfile *QGuiApplicationPrivate::colorProfileForA32Text()
{
- QDrawHelperGammaTables *result = m_gammaTables.load();
+ QColorProfile *result = m_a32ColorProfile.load();
if (!result){
- QDrawHelperGammaTables *tables = new QDrawHelperGammaTables(fontSmoothingGamma);
- if (!m_gammaTables.testAndSetRelease(0, tables))
- delete tables;
- result = m_gammaTables.load();
+ QColorProfile *cs = QColorProfile::fromGamma(fontSmoothingGamma);
+ if (!m_a32ColorProfile.testAndSetRelease(0, cs))
+ delete cs;
+ result = m_a32ColorProfile.load();
}
return result;
}
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 0d62490c75..3804667ef3 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -66,10 +66,10 @@
QT_BEGIN_NAMESPACE
+class QColorProfile;
class QPlatformIntegration;
class QPlatformTheme;
class QPlatformDragQtResponse;
-struct QDrawHelperGammaTables;
#ifndef QT_NO_DRAGANDDROP
class QDrag;
#endif // QT_NO_DRAGANDDROP
@@ -293,7 +293,8 @@ public:
static QInputDeviceManager *inputDeviceManager();
- const QDrawHelperGammaTables *gammaTables();
+ const QColorProfile *colorProfileForA8Text();
+ const QColorProfile *colorProfileForA32Text();
// hook reimplemented in QApplication to apply the QStyle function on the QIcon
virtual QPixmap applyQIconStyleHelper(QIcon::Mode, const QPixmap &basePixmap) const { return basePixmap; }
@@ -317,7 +318,8 @@ private:
static QGuiApplicationPrivate *self;
static QTouchDevice *m_fakeTouchDevice;
static int m_fakeMouseSourcePointId;
- QAtomicPointer<QDrawHelperGammaTables> m_gammaTables;
+ QAtomicPointer<QColorProfile> m_a8ColorProfile;
+ QAtomicPointer<QColorProfile> m_a32ColorProfile;
bool ownGlobalShareContext;
diff --git a/src/gui/kernel/qplatformscreen.h b/src/gui/kernel/qplatformscreen.h
index 030edea880..2d3cbaf170 100644
--- a/src/gui/kernel/qplatformscreen.h
+++ b/src/gui/kernel/qplatformscreen.h
@@ -66,7 +66,6 @@ QT_BEGIN_NAMESPACE
class QPlatformBackingStore;
-class QPlatformOpenGLContext;
class QPlatformScreenPrivate;
class QPlatformWindow;
class QPlatformCursor;
diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp
index 9c140f1d68..eef8b817fd 100644
--- a/src/gui/kernel/qplatformtheme.cpp
+++ b/src/gui/kernel/qplatformtheme.cpp
@@ -149,6 +149,11 @@ QT_BEGIN_NAMESPACE
\value ContextMenuOnMouseRelease (bool) Whether the context menu should be shown on mouse release.
+ \value TouchDoubleTapDistance (int) The maximum distance in logical pixels which a touchpoint can travel
+ between taps in order for the tap sequence to be handled as a double tap.
+ The default value is double the MouseDoubleClickDistance, or 10 logical pixels
+ if that is not specified.
+
\sa themeHint(), QStyle::pixelMetric()
*/
@@ -533,6 +538,14 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)
}
case WheelScrollLines:
return QVariant(3);
+ case TouchDoubleTapDistance:
+ {
+ bool ok = false;
+ int dist = qEnvironmentVariableIntValue("QT_DBL_TAP_DIST", &ok);
+ if (!ok)
+ dist = defaultThemeHint(MouseDoubleClickDistance).toInt(&ok) * 2;
+ return QVariant(ok ? dist : 10);
+ }
}
return QVariant();
}
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index 686dbed4b1..4135e31517 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -114,7 +114,8 @@ public:
ContextMenuOnMouseRelease,
MousePressAndHoldInterval,
MouseDoubleClickDistance,
- WheelScrollLines
+ WheelScrollLines,
+ TouchDoubleTapDistance
};
enum DialogType {
diff --git a/src/gui/kernel/qsurface.cpp b/src/gui/kernel/qsurface.cpp
index afe4cf93e1..3cdd11de8c 100644
--- a/src/gui/kernel/qsurface.cpp
+++ b/src/gui/kernel/qsurface.cpp
@@ -76,6 +76,8 @@ QT_BEGIN_NAMESPACE
\value RasterGLSurface The surface can be rendered to using a software rasterizer,
and also supports OpenGL. This surface type is intended for internal Qt use, and
requires the use of private API.
+ \value OpenVGSurface The surface is an OpenVG compatible surface and can be used
+ in conjunction with OpenVG contexts.
*/
diff --git a/src/gui/kernel/qsurface.h b/src/gui/kernel/qsurface.h
index d9ccdc096d..a96b7a6422 100644
--- a/src/gui/kernel/qsurface.h
+++ b/src/gui/kernel/qsurface.h
@@ -64,7 +64,8 @@ public:
enum SurfaceType {
RasterSurface,
OpenGLSurface,
- RasterGLSurface
+ RasterGLSurface,
+ OpenVGSurface,
};
virtual ~QSurface();
diff --git a/src/gui/kernel/qtouchdevice.h b/src/gui/kernel/qtouchdevice.h
index 0fb24e47bf..c98aa69236 100644
--- a/src/gui/kernel/qtouchdevice.h
+++ b/src/gui/kernel/qtouchdevice.h
@@ -87,6 +87,7 @@ public:
private:
QTouchDevicePrivate *d;
+ friend class QTouchDevicePrivate;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QTouchDevice::Capabilities)
diff --git a/src/gui/kernel/qtouchdevice_p.h b/src/gui/kernel/qtouchdevice_p.h
index 203d9fca74..18d2af46a7 100644
--- a/src/gui/kernel/qtouchdevice_p.h
+++ b/src/gui/kernel/qtouchdevice_p.h
@@ -64,16 +64,21 @@ public:
: type(QTouchDevice::TouchScreen),
caps(QTouchDevice::Position),
maxTouchPoints(1)
- { }
+ {
+ static quint8 nextId = 2; // device 0 is not used, device 1 is for mouse device
+ id = nextId++;
+ }
QTouchDevice::DeviceType type;
QTouchDevice::Capabilities caps;
QString name;
int maxTouchPoints;
+ quint8 id;
static void registerDevice(const QTouchDevice *dev);
static void unregisterDevice(const QTouchDevice *dev);
static bool isRegistered(const QTouchDevice *dev);
+ static QTouchDevicePrivate *get(QTouchDevice *q) { return q->d; }
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 94a34b5c27..93edfe6331 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -343,6 +343,30 @@ void QWindowPrivate::updateVisibility()
emit q->visibilityChanged(visibility);
}
+void QWindowPrivate::updateSiblingPosition(SiblingPosition position)
+{
+ Q_Q(QWindow);
+
+ if (!q->parent())
+ return;
+
+ QObjectList &siblings = q->parent()->d_ptr->children;
+
+ const int siblingCount = siblings.size() - 1;
+ if (siblingCount == 0)
+ return;
+
+ const int currentPosition = siblings.indexOf(q);
+ Q_ASSERT(currentPosition >= 0);
+
+ const int targetPosition = position == PositionTop ? siblingCount : 0;
+
+ if (currentPosition == targetPosition)
+ return;
+
+ siblings.move(currentPosition, targetPosition);
+}
+
inline bool QWindowPrivate::windowRecreationRequired(QScreen *newScreen) const
{
Q_Q(const QWindow);
@@ -605,6 +629,22 @@ WId QWindow::winId() const
return d->platformWindow->winId();
}
+ /*!
+ Returns the parent window, if any.
+
+ If \a mode is IncludeTransients, then the transient parent is returned
+ if there is no parent.
+
+ A window without a parent is known as a top level window.
+
+ \since 5.9
+*/
+QWindow *QWindow::parent(AncestorMode mode) const
+{
+ Q_D(const QWindow);
+ return d->parentWindow ? d->parentWindow : (mode == IncludeTransients ? transientParent() : nullptr);
+}
+
/*!
Returns the parent window, if any.
@@ -797,10 +837,15 @@ QSurfaceFormat QWindow::format() const
The actual window flags might differ from the flags set with setFlags()
if the requested flags could not be fulfilled.
+
+ \sa setFlag()
*/
void QWindow::setFlags(Qt::WindowFlags flags)
{
Q_D(QWindow);
+ if (d->windowFlags == flags)
+ return;
+
if (d->platformWindow)
d->platformWindow->setWindowFlags(flags);
d->windowFlags = flags;
@@ -813,6 +858,23 @@ Qt::WindowFlags QWindow::flags() const
}
/*!
+ \since 5.9
+
+ Sets the window flag \a flag on this window if \a on is true;
+ otherwise clears the flag.
+
+ \sa setFlags(), flags(), type()
+*/
+void QWindow::setFlag(Qt::WindowType flag, bool on)
+{
+ Q_D(QWindow);
+ if (on)
+ setFlags(d->windowFlags | flag);
+ else
+ setFlags(d->windowFlags & ~flag);
+}
+
+/*!
Returns the type of the window.
This returns the part of the window flags that represents
@@ -920,6 +982,9 @@ QIcon QWindow::icon() const
void QWindow::raise()
{
Q_D(QWindow);
+
+ d->updateSiblingPosition(QWindowPrivate::PositionTop);
+
if (d->platformWindow)
d->platformWindow->raise();
}
@@ -932,6 +997,9 @@ void QWindow::raise()
void QWindow::lower()
{
Q_D(QWindow);
+
+ d->updateSiblingPosition(QWindowPrivate::PositionBottom);
+
if (d->platformWindow)
d->platformWindow->lower();
}
@@ -1065,11 +1133,10 @@ bool QWindow::isActive() const
if (focus == this)
return true;
- if (!parent() && !transientParent()) {
+ if (QWindow *p = parent(IncludeTransients))
+ return p->isActive();
+ else
return isAncestorOf(focus);
- } else {
- return (parent() && parent()->isActive()) || (transientParent() && transientParent()->isActive());
- }
}
/*!
@@ -1233,8 +1300,10 @@ bool QWindow::isAncestorOf(const QWindow *child, AncestorMode mode) const
if (child->parent() == this || (mode == IncludeTransients && child->transientParent() == this))
return true;
- return (child->parent() && isAncestorOf(child->parent(), mode))
- || (mode == IncludeTransients && child->transientParent() && isAncestorOf(child->transientParent(), mode));
+ if (child->parent(mode) && isAncestorOf(child->parent(mode), mode))
+ return true;
+
+ return false;
}
/*!
@@ -1455,6 +1524,8 @@ void QWindow::setSizeIncrement(const QSize &size)
Sets the geometry of the window, excluding its window frame, to a
rectangle constructed from \a posx, \a posy, \a w and \a h.
+ The geometry is in relation to the virtualGeometry() of its screen.
+
\sa geometry()
*/
void QWindow::setGeometry(int posx, int posy, int w, int h)
@@ -1465,6 +1536,8 @@ void QWindow::setGeometry(int posx, int posy, int w, int h)
/*!
\brief Sets the geometry of the window, excluding its window frame, to \a rect.
+ The geometry is in relation to the virtualGeometry() of its screen.
+
\sa geometry()
*/
void QWindow::setGeometry(const QRect &rect)
@@ -1526,6 +1599,8 @@ QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry)
/*!
Returns the geometry of the window, excluding its window frame.
+ The geometry is in relation to the virtualGeometry() of its screen.
+
\sa frameMargins(), frameGeometry()
*/
QRect QWindow::geometry() const
@@ -1552,6 +1627,8 @@ QMargins QWindow::frameMargins() const
/*!
Returns the geometry of the window, including its window frame.
+ The geometry is in relation to the virtualGeometry() of its screen.
+
\sa geometry(), frameMargins()
*/
QRect QWindow::frameGeometry() const
@@ -1584,6 +1661,8 @@ QPoint QWindow::framePosition() const
/*!
Sets the upper left position of the window (\a point) including its window frame.
+ The position is in relation to the virtualGeometry() of its screen.
+
\sa setGeometry(), frameGeometry()
*/
void QWindow::setFramePosition(const QPoint &point)
@@ -1601,6 +1680,8 @@ void QWindow::setFramePosition(const QPoint &point)
/*!
\brief set the position of the window on the desktop to \a pt
+ The position is in relation to the virtualGeometry() of its screen.
+
\sa position()
*/
void QWindow::setPosition(const QPoint &pt)
@@ -1611,6 +1692,8 @@ void QWindow::setPosition(const QPoint &pt)
/*!
\brief set the position of the window on the desktop to \a posx, \a posy
+ The position is in relation to the virtualGeometry() of its screen.
+
\sa position()
*/
void QWindow::setPosition(int posx, int posy)
@@ -1787,8 +1870,9 @@ QScreen *QWindow::screen() const
If the window has been created, it will be recreated on the \a newScreen.
- Note that if the screen is part of a virtual desktop of multiple screens,
- the window can appear on any of the screens returned by QScreen::virtualSiblings().
+ \note If the screen is part of a virtual desktop of multiple screens,
+ the window will not move automatically to \a newScreen. To place the
+ window relative to the screen, use the screen's topLeft() position.
This function only works for top level windows.
@@ -2377,6 +2461,20 @@ QPoint QWindow::mapFromGlobal(const QPoint &pos) const
return pos - d->globalPosition();
}
+QPoint QWindowPrivate::globalPosition() const
+{
+ Q_Q(const QWindow);
+ QPoint offset = q->position();
+ for (const QWindow *p = q->parent(); p; p = p->parent()) {
+ if (p->type() != Qt::ForeignWindow) {
+ offset += p->position();
+ } else { // Use mapToGlobal() for foreign windows
+ offset += p->mapToGlobal(QPoint(0, 0));
+ break;
+ }
+ }
+ return offset;
+}
Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window)
{
@@ -2416,10 +2514,7 @@ QWindow *QWindowPrivate::topLevelWindow() const
QWindow *window = const_cast<QWindow *>(q);
while (window) {
- QWindow *parent = window->parent();
- if (!parent)
- parent = window->transientParent();
-
+ QWindow *parent = window->parent(QWindow::IncludeTransients);
if (!parent)
break;
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index bf25cf64c9..2883749d2e 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -132,6 +132,12 @@ public:
};
Q_ENUM(Visibility)
+ enum AncestorMode {
+ ExcludeTransients,
+ IncludeTransients
+ };
+ Q_ENUM(AncestorMode)
+
explicit QWindow(QScreen *screen = Q_NULLPTR);
explicit QWindow(QWindow *parent);
virtual ~QWindow();
@@ -148,7 +154,8 @@ public:
WId winId() const;
- QWindow *parent() const;
+ QWindow *parent(AncestorMode mode) const;
+ QWindow *parent() const; // ### Qt6: Merge with above
void setParent(QWindow *parent);
bool isTopLevel() const;
@@ -163,6 +170,7 @@ public:
void setFlags(Qt::WindowFlags flags);
Qt::WindowFlags flags() const;
+ void setFlag(Qt::WindowType, bool on = true);
Qt::WindowType type() const;
QString title() const;
@@ -186,11 +194,6 @@ public:
void setTransientParent(QWindow *parent);
QWindow *transientParent() const;
- enum AncestorMode {
- ExcludeTransients,
- IncludeTransients
- };
-
bool isAncestorOf(const QWindow *child, AncestorMode mode = IncludeTransients) const;
bool isExposed() const;
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index b8a9f5d3de..95c6abf428 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -123,19 +123,7 @@ public:
void deliverUpdateRequest();
- QPoint globalPosition() const {
- Q_Q(const QWindow);
- QPoint offset = q->position();
- for (const QWindow *p = q->parent(); p; p = p->parent()) {
- if (p->type() != Qt::ForeignWindow) {
- offset += p->position();
- } else { // QTBUG-43252, mapToGlobal() for foreign children.
- offset += p->mapToGlobal(QPoint(0, 0));
- break;
- }
- }
- return offset;
- }
+ QPoint globalPosition() const;
QWindow *topLevelWindow() const;
@@ -144,6 +132,9 @@ public:
void updateVisibility();
void _q_clearAlert();
+ enum SiblingPosition { PositionTop, PositionBottom };
+ void updateSiblingPosition(SiblingPosition);
+
bool windowRecreationRequired(QScreen *newScreen) const;
void create(bool recursive);
void setTopLevelScreen(QScreen *newScreen, bool recreate);
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 667304859e..813b0f72bb 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -59,41 +59,57 @@ QWaitCondition QWindowSystemInterfacePrivate::eventsFlushed;
QMutex QWindowSystemInterfacePrivate::flushEventMutex;
QAtomicInt QWindowSystemInterfacePrivate::eventAccepted;
QWindowSystemEventHandler *QWindowSystemInterfacePrivate::eventHandler;
-
-//------------------------------------------------------------
-//
-// Callback functions for plugins:
-//
-
QWindowSystemInterfacePrivate::WindowSystemEventList QWindowSystemInterfacePrivate::windowSystemEventQueue;
extern QPointer<QWindow> qt_last_mouse_receiver;
+
+// ------------------- QWindowSystemInterfacePrivate -------------------
+
/*!
Handles a window system event asynchronously by posting the event to Qt Gui.
- \sa postWindowSystemEvent()
+ This function posts the event on the window system event queue and wakes the
+ Gui event dispatcher. Qt Gui will then handle the event asynchonously at a
+ later point.
*/
template<>
bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(WindowSystemEvent *ev)
{
- QWindowSystemInterfacePrivate::postWindowSystemEvent(ev);
+ windowSystemEventQueue.append(ev);
+ if (QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher())
+ dispatcher->wakeUp();
return true;
}
/*!
Handles a window system event synchronously.
+ Qt Gui will process the event immediately. The return value indicates if Qt
+ accepted the event.
+
If the event is delivered from another thread than the Qt main thread the
window system event queue is flushed, which may deliver other events as
well.
-
- \sa processWindowSystemEvent()
*/
template<>
bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::SynchronousDelivery>(WindowSystemEvent *ev)
{
- return QWindowSystemInterfacePrivate::processWindowSystemEvent(ev);
+ bool accepted = true;
+ if (QThread::currentThread() == QGuiApplication::instance()->thread()) {
+ // Process the event immediately on the current thread and return the accepted state.
+ QGuiApplicationPrivate::processWindowSystemEvent(ev);
+ accepted = ev->eventAccepted;
+ delete ev;
+ } else {
+ // Post the event on the Qt main thread queue and flush the queue.
+ // This will wake up the Gui thread which will process the event.
+ // Return the accepted state for the last event on the queue,
+ // which is the event posted by this function.
+ handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(ev);
+ accepted = QWindowSystemInterface::flushWindowSystemEvents();
+ }
+ return accepted;
}
/*!
@@ -109,7 +125,7 @@ bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterfa
than the Qt main thread the window system event queue is flushed, which may deliver
other events as well.
- \sa flushWindowSystemEvents(), processWindowSystemEvent(), setSynchronousWindowSystemEvents()
+ \sa flushWindowSystemEvents(), setSynchronousWindowSystemEvents()
*/
template<>
bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::DefaultDelivery>(QWindowSystemInterfacePrivate::WindowSystemEvent *ev)
@@ -120,6 +136,59 @@ bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterfa
return handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(ev);
}
+int QWindowSystemInterfacePrivate::windowSystemEventsQueued()
+{
+ return windowSystemEventQueue.count();
+}
+
+QWindowSystemInterfacePrivate::WindowSystemEvent * QWindowSystemInterfacePrivate::getWindowSystemEvent()
+{
+ return windowSystemEventQueue.takeFirstOrReturnNull();
+}
+
+QWindowSystemInterfacePrivate::WindowSystemEvent *QWindowSystemInterfacePrivate::getNonUserInputWindowSystemEvent()
+{
+ return windowSystemEventQueue.takeFirstNonUserInputOrReturnNull();
+}
+
+QWindowSystemInterfacePrivate::WindowSystemEvent *QWindowSystemInterfacePrivate::peekWindowSystemEvent(EventType t)
+{
+ return windowSystemEventQueue.peekAtFirstOfType(t);
+}
+
+void QWindowSystemInterfacePrivate::removeWindowSystemEvent(WindowSystemEvent *event)
+{
+ windowSystemEventQueue.remove(event);
+}
+
+void QWindowSystemInterfacePrivate::installWindowSystemEventHandler(QWindowSystemEventHandler *handler)
+{
+ if (!eventHandler)
+ eventHandler = handler;
+}
+
+void QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(QWindowSystemEventHandler *handler)
+{
+ if (eventHandler == handler)
+ eventHandler = 0;
+}
+
+QWindowSystemEventHandler::~QWindowSystemEventHandler()
+{
+ QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(this);
+}
+
+bool QWindowSystemEventHandler::sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
+{
+ QGuiApplicationPrivate::processWindowSystemEvent(e);
+ return true;
+}
+
+//------------------------------------------------------------
+//
+// Callback functions for plugins:
+//
+
#define QT_DEFINE_QPA_EVENT_HANDLER(ReturnType, HandlerName, ...) \
template Q_GUI_EXPORT ReturnType QWindowSystemInterface::HandlerName<QWindowSystemInterface::DefaultDelivery>(__VA_ARGS__); \
template Q_GUI_EXPORT ReturnType QWindowSystemInterface::HandlerName<QWindowSystemInterface::SynchronousDelivery>(__VA_ARGS__); \
@@ -138,17 +207,17 @@ bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterfa
until sendWindowSystemEvents() is called by the event dispatcher.
*/
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleEnterEvent, QWindow *tlw, const QPointF &local, const QPointF &global)
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleEnterEvent, QWindow *window, const QPointF &local, const QPointF &global)
{
- if (tlw) {
- QWindowSystemInterfacePrivate::EnterEvent *e = new QWindowSystemInterfacePrivate::EnterEvent(tlw, local, global);
+ if (window) {
+ QWindowSystemInterfacePrivate::EnterEvent *e = new QWindowSystemInterfacePrivate::EnterEvent(window, local, global);
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
}
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleLeaveEvent, QWindow *tlw)
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleLeaveEvent, QWindow *window)
{
- QWindowSystemInterfacePrivate::LeaveEvent *e = new QWindowSystemInterfacePrivate::LeaveEvent(tlw);
+ QWindowSystemInterfacePrivate::LeaveEvent *e = new QWindowSystemInterfacePrivate::LeaveEvent(window);
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
@@ -165,24 +234,24 @@ void QWindowSystemInterface::handleEnterLeaveEvent(QWindow *enter, QWindow *leav
handleEnterEvent(enter, local, global);
}
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowActivated, QWindow *tlw, Qt::FocusReason r)
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowActivated, QWindow *window, Qt::FocusReason r)
{
QWindowSystemInterfacePrivate::ActivatedWindowEvent *e =
- new QWindowSystemInterfacePrivate::ActivatedWindowEvent(tlw, r);
+ new QWindowSystemInterfacePrivate::ActivatedWindowEvent(window, r);
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
-void QWindowSystemInterface::handleWindowStateChanged(QWindow *tlw, Qt::WindowState newState)
+void QWindowSystemInterface::handleWindowStateChanged(QWindow *window, Qt::WindowState newState)
{
QWindowSystemInterfacePrivate::WindowStateChangedEvent *e =
- new QWindowSystemInterfacePrivate::WindowStateChangedEvent(tlw, newState);
+ new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
-void QWindowSystemInterface::handleWindowScreenChanged(QWindow *tlw, QScreen *screen)
+void QWindowSystemInterface::handleWindowScreenChanged(QWindow *window, QScreen *screen)
{
QWindowSystemInterfacePrivate::WindowScreenChangedEvent *e =
- new QWindowSystemInterfacePrivate::WindowScreenChangedEvent(tlw, screen);
+ new QWindowSystemInterfacePrivate::WindowScreenChangedEvent(window, screen);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
@@ -197,9 +266,9 @@ void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState
/*!
If \a oldRect is null, Qt will use the previously reported geometry instead.
*/
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *tlw, const QRect &newRect, const QRect &oldRect)
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect, const QRect &oldRect)
{
- QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(tlw, QHighDpi::fromNativePixels(newRect, tlw), QHighDpi::fromNativePixels(oldRect, tlw));
+ QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, QHighDpi::fromNativePixels(newRect, window), QHighDpi::fromNativePixels(oldRect, window));
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
@@ -211,18 +280,18 @@ QWindowSystemInterfacePrivate::ExposeEvent::ExposeEvent(QWindow *window, const Q
{
}
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleExposeEvent, QWindow *tlw, const QRegion &region)
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleExposeEvent, QWindow *window, const QRegion &region)
{
QWindowSystemInterfacePrivate::ExposeEvent *e =
- new QWindowSystemInterfacePrivate::ExposeEvent(tlw, QHighDpi::fromNativeLocalExposedRegion(region, tlw));
+ new QWindowSystemInterfacePrivate::ExposeEvent(window, QHighDpi::fromNativeLocalExposedRegion(region, window));
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
-void QWindowSystemInterface::handleCloseEvent(QWindow *tlw, bool *accepted)
+void QWindowSystemInterface::handleCloseEvent(QWindow *window, bool *accepted)
{
- if (tlw) {
+ if (window) {
QWindowSystemInterfacePrivate::CloseEvent *e =
- new QWindowSystemInterfacePrivate::CloseEvent(tlw, accepted);
+ new QWindowSystemInterfacePrivate::CloseEvent(window, accepted);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
}
@@ -232,35 +301,35 @@ void QWindowSystemInterface::handleCloseEvent(QWindow *tlw, bool *accepted)
\a w == 0 means that the event is in global coords only, \a local will be ignored in this case
*/
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleMouseEvent, QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleMouseEvent, QWindow *window, const QPointF &local, const QPointF &global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
{
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- handleMouseEvent<Delivery>(w, time, local, global, b, mods, source);
+ handleMouseEvent<Delivery>(window, time, local, global, b, mods, source);
}
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleMouseEvent, QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleMouseEvent, QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
{
QWindowSystemInterfacePrivate::MouseEvent * e =
- new QWindowSystemInterfacePrivate::MouseEvent(w, timestamp, QHighDpi::fromNativeLocalPosition(local, w), QHighDpi::fromNativePixels(global, w), b, mods, source);
+ new QWindowSystemInterfacePrivate::MouseEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), b, mods, source);
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
-void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
+void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, const QPointF &local, const QPointF &global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
{
const unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- handleFrameStrutMouseEvent(w, time, local, global, b, mods, source);
+ handleFrameStrutMouseEvent(window, time, local, global, b, mods, source);
}
-void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
+void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods, Qt::MouseEventSource source)
{
QWindowSystemInterfacePrivate::MouseEvent * e =
- new QWindowSystemInterfacePrivate::MouseEvent(w, timestamp,
+ new QWindowSystemInterfacePrivate::MouseEvent(window, timestamp,
QWindowSystemInterfacePrivate::FrameStrutMouse,
- QHighDpi::fromNativeLocalPosition(local, w), QHighDpi::fromNativePixels(global, w), b, mods, source);
+ QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), b, mods, source);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
@@ -309,35 +378,35 @@ bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestam
#endif
}
-QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) {
+QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *window, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) {
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- return handleKeyEvent<Delivery>(w, time, t, k, mods, text, autorep, count);
+ return handleKeyEvent<Delivery>(window, time, t, k, mods, text, autorep, count);
}
-QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count)
+QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *window, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count)
{
#if defined(Q_OS_OSX)
- if (t == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(tlw, timestamp, k, mods, 0, 0, 0, text, autorep, count))
+ if (t == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(window, timestamp, k, mods, 0, 0, 0, text, autorep, count))
return true;
#endif
QWindowSystemInterfacePrivate::KeyEvent * e =
- new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, t, k, mods, text, autorep, count);
+ new QWindowSystemInterfacePrivate::KeyEvent(window, timestamp, t, k, mods, text, autorep, count);
return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
-bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
+bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *window, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
const QString& text, bool autorep,
ushort count, bool tryShortcutOverride)
{
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- return handleExtendedKeyEvent(w, time, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers,
+ return handleExtendedKeyEvent(window, time, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers,
text, autorep, count, tryShortcutOverride);
}
-bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type type, int key,
+bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *window, ulong timestamp, QEvent::Type type, int key,
Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
@@ -345,7 +414,7 @@ bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestam
ushort count, bool tryShortcutOverride)
{
#if defined(Q_OS_OSX)
- if (tryShortcutOverride && type == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(tlw,
+ if (tryShortcutOverride && type == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(window,
timestamp, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count)) {
return true;
}
@@ -354,29 +423,36 @@ bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestam
#endif
QWindowSystemInterfacePrivate::KeyEvent * e =
- new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, type, key, modifiers,
+ new QWindowSystemInterfacePrivate::KeyEvent(window, timestamp, type, key, modifiers,
nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
-void QWindowSystemInterface::handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods) {
+QWindowSystemInterfacePrivate::WheelEvent::WheelEvent(QWindow *window, ulong time, const QPointF &local, const QPointF &global, QPoint pixelD,
+ QPoint angleD, int qt4D, Qt::Orientation qt4O, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource src, bool inverted)
+ : InputEvent(window, time, Wheel, mods), pixelDelta(pixelD), angleDelta(angleD), qt4Delta(qt4D),
+ qt4Orientation(qt4O), localPos(local), globalPos(global), phase(phase), source(src), inverted(inverted)
+{
+}
+
+void QWindowSystemInterface::handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods) {
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- handleWheelEvent(w, time, local, global, d, o, mods);
+ handleWheelEvent(window, time, local, global, d, o, mods);
}
-void QWindowSystemInterface::handleWheelEvent(QWindow *tlw, ulong timestamp, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods)
+void QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods)
{
QPoint point = (o == Qt::Vertical) ? QPoint(0, d) : QPoint(d, 0);
- handleWheelEvent(tlw, timestamp, local, global, QPoint(), point, mods);
+ handleWheelEvent(window, timestamp, local, global, QPoint(), point, mods);
}
-void QWindowSystemInterface::handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource source)
+void QWindowSystemInterface::handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource source)
{
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- handleWheelEvent(w, time, local, global, pixelDelta, angleDelta, mods, phase, source);
+ handleWheelEvent(window, time, local, global, pixelDelta, angleDelta, mods, phase, source);
}
-void QWindowSystemInterface::handleWheelEvent(QWindow *tlw, ulong timestamp, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase,
+void QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase,
Qt::MouseEventSource source, bool invertedScrolling)
{
// Qt 4 sends two separate wheel events for horizontal and vertical
@@ -395,7 +471,7 @@ void QWindowSystemInterface::handleWheelEvent(QWindow *tlw, ulong timestamp, con
// Simple case: vertical deltas only:
if (angleDelta.y() != 0 && angleDelta.x() == 0) {
- e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, QHighDpi::fromNativeLocalPosition(local, tlw), QHighDpi::fromNativePixels(global, tlw), pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical,
+ e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical,
mods, phase, source, invertedScrolling);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
return;
@@ -403,7 +479,7 @@ void QWindowSystemInterface::handleWheelEvent(QWindow *tlw, ulong timestamp, con
// Simple case: horizontal deltas only:
if (angleDelta.y() == 0 && angleDelta.x() != 0) {
- e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, QHighDpi::fromNativeLocalPosition(local, tlw), QHighDpi::fromNativePixels(global, tlw), pixelDelta, angleDelta, angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling);
+ e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), pixelDelta, angleDelta, angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
return;
}
@@ -411,106 +487,65 @@ void QWindowSystemInterface::handleWheelEvent(QWindow *tlw, ulong timestamp, con
// Both horizontal and vertical deltas: Send two wheel events.
// The first event contains the Qt 5 pixel and angle delta as points,
// and in addition the Qt 4 compatibility vertical angle delta.
- e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, QHighDpi::fromNativeLocalPosition(local, tlw), QHighDpi::fromNativePixels(global, tlw), pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source, invertedScrolling);
+ e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source, invertedScrolling);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
// The second event contains null pixel and angle points and the
// Qt 4 compatibility horizontal angle delta.
- e = new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, QHighDpi::fromNativeLocalPosition(local, tlw), QHighDpi::fromNativePixels(global, tlw), QPoint(), QPoint(), angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling);
+ e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativePixels(global, window), QPoint(), QPoint(), angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
-int QWindowSystemInterfacePrivate::windowSystemEventsQueued()
-{
- return windowSystemEventQueue.count();
-}
-
-QWindowSystemInterfacePrivate::WindowSystemEvent * QWindowSystemInterfacePrivate::getWindowSystemEvent()
+void QWindowSystemInterface::registerTouchDevice(const QTouchDevice *device)
{
- return windowSystemEventQueue.takeFirstOrReturnNull();
+ QTouchDevicePrivate::registerDevice(device);
}
-QWindowSystemInterfacePrivate::WindowSystemEvent *QWindowSystemInterfacePrivate::getNonUserInputWindowSystemEvent()
+void QWindowSystemInterface::unregisterTouchDevice(const QTouchDevice *device)
{
- return windowSystemEventQueue.takeFirstNonUserInputOrReturnNull();
+ QTouchDevicePrivate::unregisterDevice(device);
}
-QWindowSystemInterfacePrivate::WindowSystemEvent *QWindowSystemInterfacePrivate::peekWindowSystemEvent(EventType t)
+bool QWindowSystemInterface::isTouchDeviceRegistered(const QTouchDevice *device)
{
- return windowSystemEventQueue.peekAtFirstOfType(t);
+ return QTouchDevicePrivate::isRegistered(device);
}
-void QWindowSystemInterfacePrivate::removeWindowSystemEvent(WindowSystemEvent *event)
-{
- windowSystemEventQueue.remove(event);
-}
+static int g_nextPointId = 1;
-/*!
- Posts a window system event to be handled asynchronously by Qt Gui.
-
- This function posts the event on the window system event queue and wakes the
- Gui event dispatcher. Qt Gui will then handle the event asynchonously at a
- later point.
-
- \sa flushWindowSystemEvents(), processWindowSystemEvent(), handleWindowSystemEvent()
-*/
-void QWindowSystemInterfacePrivate::postWindowSystemEvent(WindowSystemEvent *ev)
-{
- windowSystemEventQueue.append(ev);
- QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher();
- if (dispatcher)
- dispatcher->wakeUp();
-}
+// map from device-independent point id (arbitrary) to "Qt point" ids
+typedef QMap<quint64, int> PointIdMap;
+Q_GLOBAL_STATIC(PointIdMap, g_pointIdMap)
/*!
- Processes a window system event synchronously.
-
- Qt Gui will process the event immediately. The return value indicates if Qt
- accepted the event.
-
- If the event is delivered from another thread than the Qt main thread the
- window system event queue is flushed, which may deliver other events as
- well.
-
- \sa flushWindowSystemEvents(), postWindowSystemEvent(), handleWindowSystemEvent()
+ \internal
+ This function maps potentially arbitrary point ids \a pointId in the 32 bit
+ value space to start from 1 and increase incrementally for each touch point
+ held down. If all touch points are released it will reset the id back to 1
+ for the following touch point.
+
+ We can then assume that the touch points ids will never become too large,
+ and it will then put the device identifier \a deviceId in the upper 8 bits.
+ This leaves us with max 255 devices, and 16.7M taps without full release
+ before we run out of value space.
*/
-bool QWindowSystemInterfacePrivate::processWindowSystemEvent(WindowSystemEvent *ev)
-{
- bool accepted = true;
- if (QThread::currentThread() == QGuiApplication::instance()->thread()) {
- // Process the event immediately on the current thread and return the accepted state.
- QGuiApplicationPrivate::processWindowSystemEvent(ev);
- accepted = ev->eventAccepted;
- delete ev;
+static int acquireCombinedPointId(quint8 deviceId, int pointId)
+{
+ quint64 combinedId64 = (quint64(deviceId) << 32) + pointId;
+ auto it = g_pointIdMap->constFind(combinedId64);
+ int uid;
+ if (it == g_pointIdMap->constEnd()) {
+ uid = g_nextPointId++;
+ g_pointIdMap->insert(combinedId64, uid);
} else {
- // Post the event on the Qt main thread queue and flush the queue.
- // This will wake up the Gui thread which will process the event.
- // Return the accepted state for the last event on the queue,
- // which is the event posted by this function.
- postWindowSystemEvent(ev);
- accepted = QWindowSystemInterface::flushWindowSystemEvents();
+ uid = *it;
}
- return accepted;
-}
-
-void QWindowSystemInterface::registerTouchDevice(const QTouchDevice *device)
-{
- QTouchDevicePrivate::registerDevice(device);
-}
-
-void QWindowSystemInterface::unregisterTouchDevice(const QTouchDevice *device)
-{
- QTouchDevicePrivate::unregisterDevice(device);
-}
-
-bool QWindowSystemInterface::isTouchDeviceRegistered(const QTouchDevice *device)
-{
- return QTouchDevicePrivate::isRegistered(device);
+ return (deviceId << 24) + uid;
}
QList<QTouchEvent::TouchPoint>
QWindowSystemInterfacePrivate::fromNativeTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points,
- const QWindow *window,
+ const QWindow *window, quint8 deviceId,
QEvent::Type *type)
{
QList<QTouchEvent::TouchPoint> touchPoints;
@@ -521,7 +556,7 @@ QList<QTouchEvent::TouchPoint>
QList<QWindowSystemInterface::TouchPoint>::const_iterator point = points.constBegin();
QList<QWindowSystemInterface::TouchPoint>::const_iterator end = points.constEnd();
while (point != end) {
- p.setId(point->id);
+ p.setId(acquireCombinedPointId(deviceId, point->id));
if (point->uniqueId >= 0)
p.setUniqueId(point->uniqueId);
p.setPressure(point->pressure);
@@ -554,6 +589,11 @@ QList<QTouchEvent::TouchPoint>
*type = QEvent::TouchEnd;
}
+ if (states == Qt::TouchPointReleased) {
+ g_nextPointId = 1;
+ g_pointIdMap->clear();
+ }
+
return touchPoints;
}
@@ -578,14 +618,14 @@ QList<QWindowSystemInterface::TouchPoint>
return newList;
}
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchEvent, QWindow *w, QTouchDevice *device,
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchEvent, QWindow *window, QTouchDevice *device,
const QList<TouchPoint> &points, Qt::KeyboardModifiers mods)
{
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- handleTouchEvent<Delivery>(w, time, device, points, mods);
+ handleTouchEvent<Delivery>(window, time, device, points, mods);
}
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchEvent, QWindow *tlw, ulong timestamp, QTouchDevice *device,
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchEvent, QWindow *window, ulong timestamp, QTouchDevice *device,
const QList<TouchPoint> &points, Qt::KeyboardModifiers mods)
{
if (!points.size()) // Touch events must have at least one point
@@ -595,25 +635,26 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchEvent, QWindow *tlw, ulong timestam
return;
QEvent::Type type;
- QList<QTouchEvent::TouchPoint> touchPoints = QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, tlw, &type);
+ QList<QTouchEvent::TouchPoint> touchPoints =
+ QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, window, QTouchDevicePrivate::get(device)->id, &type);
QWindowSystemInterfacePrivate::TouchEvent *e =
- new QWindowSystemInterfacePrivate::TouchEvent(tlw, timestamp, type, device, touchPoints, mods);
+ new QWindowSystemInterfacePrivate::TouchEvent(window, timestamp, type, device, touchPoints, mods);
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchCancelEvent, QWindow *w, QTouchDevice *device,
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchCancelEvent, QWindow *window, QTouchDevice *device,
Qt::KeyboardModifiers mods)
{
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- handleTouchCancelEvent<Delivery>(w, time, device, mods);
+ handleTouchCancelEvent<Delivery>(window, time, device, mods);
}
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchCancelEvent, QWindow *w, ulong timestamp, QTouchDevice *device,
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchCancelEvent, QWindow *window, ulong timestamp, QTouchDevice *device,
Qt::KeyboardModifiers mods)
{
QWindowSystemInterfacePrivate::TouchEvent *e =
- new QWindowSystemInterfacePrivate::TouchEvent(w, timestamp, QEvent::TouchCancel, device,
+ new QWindowSystemInterfacePrivate::TouchEvent(window, timestamp, QEvent::TouchCancel, device,
QList<QTouchEvent::TouchPoint>(), mods);
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
@@ -646,113 +687,21 @@ void QWindowSystemInterface::handleScreenRefreshRateChange(QScreen *screen, qrea
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
-void QWindowSystemInterface::handleThemeChange(QWindow *tlw)
+void QWindowSystemInterface::handleThemeChange(QWindow *window)
{
- QWindowSystemInterfacePrivate::ThemeChangeEvent *e = new QWindowSystemInterfacePrivate::ThemeChangeEvent(tlw);
+ QWindowSystemInterfacePrivate::ThemeChangeEvent *e = new QWindowSystemInterfacePrivate::ThemeChangeEvent(window);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
-void QWindowSystemInterface::deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
-{
- Q_ASSERT(QThread::currentThread() == QGuiApplication::instance()->thread());
-
- QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
- sendWindowSystemEvents(flags);
- QWindowSystemInterfacePrivate::eventsFlushed.wakeOne();
-}
-
-/*!
- Make Qt Gui process all events on the event queue immediately. Return the
- accepted state for the last event on the queue.
-*/
-bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
-{
- const int count = QWindowSystemInterfacePrivate::windowSystemEventQueue.count();
- if (!count)
- return false;
- if (!QGuiApplication::instance()) {
- qWarning().nospace()
- << "QWindowSystemInterface::flushWindowSystemEvents() invoked after "
- "QGuiApplication destruction, discarding " << count << " events.";
- QWindowSystemInterfacePrivate::windowSystemEventQueue.clear();
- return false;
- }
- if (QThread::currentThread() != QGuiApplication::instance()->thread()) {
- // Post a FlushEvents event which will trigger a call back to
- // deferredFlushWindowSystemEvents from the Gui thread.
- QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
- QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent(flags);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent<AsynchronousDelivery>(e);
- QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex);
- } else {
- sendWindowSystemEvents(flags);
- }
- return QWindowSystemInterfacePrivate::eventAccepted.load() > 0;
-}
-
-bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
-{
- int nevents = 0;
-
- while (QWindowSystemInterfacePrivate::windowSystemEventsQueued()) {
- QWindowSystemInterfacePrivate::WindowSystemEvent *event =
- (flags & QEventLoop::ExcludeUserInputEvents) ?
- QWindowSystemInterfacePrivate::getNonUserInputWindowSystemEvent() :
- QWindowSystemInterfacePrivate::getWindowSystemEvent();
- if (!event)
- break;
-
- if (QWindowSystemInterfacePrivate::eventHandler) {
- if (QWindowSystemInterfacePrivate::eventHandler->sendEvent(event))
- nevents++;
- } else {
- nevents++;
- QGuiApplicationPrivate::processWindowSystemEvent(event);
- }
-
- // Record the accepted state for the processed event
- // (excluding flush events). This state can then be
- // returned by flushWindowSystemEvents().
- if (event->type != QWindowSystemInterfacePrivate::FlushEvents)
- QWindowSystemInterfacePrivate::eventAccepted.store(event->eventAccepted);
-
- delete event;
- }
-
- return (nevents > 0);
-}
-
-void QWindowSystemInterfacePrivate::installWindowSystemEventHandler(QWindowSystemEventHandler *handler)
-{
- if (!eventHandler)
- eventHandler = handler;
-}
-
-void QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(QWindowSystemEventHandler *handler)
-{
- if (eventHandler == handler)
- eventHandler = 0;
-}
-
-void QWindowSystemInterface::setSynchronousWindowSystemEvents(bool enable)
-{
- QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = enable;
-}
-
-int QWindowSystemInterface::windowSystemEventsQueued()
-{
- return QWindowSystemInterfacePrivate::windowSystemEventsQueued();
-}
-
#ifndef QT_NO_DRAGANDDROP
-QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions)
+QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions)
{
- return QGuiApplicationPrivate::processDrag(w, dropData, QHighDpi::fromNativeLocalPosition(p, w) ,supportedActions);
+ return QGuiApplicationPrivate::processDrag(window, dropData, QHighDpi::fromNativeLocalPosition(p, window) ,supportedActions);
}
-QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions)
+QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions)
{
- return QGuiApplicationPrivate::processDrop(w, dropData, QHighDpi::fromNativeLocalPosition(p, w),supportedActions);
+ return QGuiApplicationPrivate::processDrop(window, dropData, QHighDpi::fromNativeLocalPosition(p, window),supportedActions);
}
#endif // QT_NO_DRAGANDDROP
@@ -780,45 +729,50 @@ void QWindowSystemInterface::handleFileOpenEvent(const QUrl &url)
QGuiApplicationPrivate::processWindowSystemEvent(&e);
}
-void QWindowSystemInterface::handleTabletEvent(QWindow *w, ulong timestamp, const QPointF &local, const QPointF &global,
+void QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(bool v)
+{
+ platformSynthesizesMouse = v;
+}
+
+void QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global,
int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qint64 uid,
Qt::KeyboardModifiers modifiers)
{
QWindowSystemInterfacePrivate::TabletEvent *e =
- new QWindowSystemInterfacePrivate::TabletEvent(w,timestamp,
- QHighDpi::fromNativeLocalPosition(local, w),
- QHighDpi::fromNativePixels(global, w),
+ new QWindowSystemInterfacePrivate::TabletEvent(window, timestamp,
+ QHighDpi::fromNativeLocalPosition(local, window),
+ QHighDpi::fromNativePixels(global, window),
device, pointerType, buttons, pressure,
xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
-void QWindowSystemInterface::handleTabletEvent(QWindow *w, const QPointF &local, const QPointF &global,
+void QWindowSystemInterface::handleTabletEvent(QWindow *window, const QPointF &local, const QPointF &global,
int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qint64 uid,
Qt::KeyboardModifiers modifiers)
{
ulong time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- handleTabletEvent(w, time, local, global, device, pointerType, buttons, pressure,
+ handleTabletEvent(window, time, local, global, device, pointerType, buttons, pressure,
xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
}
-void QWindowSystemInterface::handleTabletEvent(QWindow *w, ulong timestamp, bool down, const QPointF &local, const QPointF &global,
+void QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, bool down, const QPointF &local, const QPointF &global,
int device, int pointerType, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qint64 uid,
Qt::KeyboardModifiers modifiers)
{
- handleTabletEvent(w, timestamp, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure,
+ handleTabletEvent(window, timestamp, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure,
xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
}
-void QWindowSystemInterface::handleTabletEvent(QWindow *w, bool down, const QPointF &local, const QPointF &global,
+void QWindowSystemInterface::handleTabletEvent(QWindow *window, bool down, const QPointF &local, const QPointF &global,
int device, int pointerType, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qint64 uid,
Qt::KeyboardModifiers modifiers)
{
- handleTabletEvent(w, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure,
+ handleTabletEvent(window, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure,
xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
}
@@ -885,12 +839,12 @@ void QWindowSystemInterface::handlePlatformPanelEvent(QWindow *w)
}
#ifndef QT_NO_CONTEXTMENU
-void QWindowSystemInterface::handleContextMenuEvent(QWindow *w, bool mouseTriggered,
+void QWindowSystemInterface::handleContextMenuEvent(QWindow *window, bool mouseTriggered,
const QPoint &pos, const QPoint &globalPos,
Qt::KeyboardModifiers modifiers)
{
QWindowSystemInterfacePrivate::ContextMenuEvent *e =
- new QWindowSystemInterfacePrivate::ContextMenuEvent(w, mouseTriggered, pos,
+ new QWindowSystemInterfacePrivate::ContextMenuEvent(window, mouseTriggered, pos,
globalPos, modifiers);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
@@ -915,18 +869,102 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo
}
#endif
+// ------------------ Event dispatcher functionality ------------------
+
+/*!
+ Make Qt Gui process all events on the event queue immediately. Return the
+ accepted state for the last event on the queue.
+*/
+bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ const int count = QWindowSystemInterfacePrivate::windowSystemEventQueue.count();
+ if (!count)
+ return false;
+ if (!QGuiApplication::instance()) {
+ qWarning().nospace()
+ << "QWindowSystemInterface::flushWindowSystemEvents() invoked after "
+ "QGuiApplication destruction, discarding " << count << " events.";
+ QWindowSystemInterfacePrivate::windowSystemEventQueue.clear();
+ return false;
+ }
+ if (QThread::currentThread() != QGuiApplication::instance()->thread()) {
+ // Post a FlushEvents event which will trigger a call back to
+ // deferredFlushWindowSystemEvents from the Gui thread.
+ QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
+ QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent(flags);
+ QWindowSystemInterfacePrivate::handleWindowSystemEvent<AsynchronousDelivery>(e);
+ QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex);
+ } else {
+ sendWindowSystemEvents(flags);
+ }
+ return QWindowSystemInterfacePrivate::eventAccepted.load() > 0;
+}
+
+void QWindowSystemInterface::deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_ASSERT(QThread::currentThread() == QGuiApplication::instance()->thread());
+
+ QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
+ sendWindowSystemEvents(flags);
+ QWindowSystemInterfacePrivate::eventsFlushed.wakeOne();
+}
+
+bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ int nevents = 0;
+
+ while (QWindowSystemInterfacePrivate::windowSystemEventsQueued()) {
+ QWindowSystemInterfacePrivate::WindowSystemEvent *event =
+ (flags & QEventLoop::ExcludeUserInputEvents) ?
+ QWindowSystemInterfacePrivate::getNonUserInputWindowSystemEvent() :
+ QWindowSystemInterfacePrivate::getWindowSystemEvent();
+ if (!event)
+ break;
+
+ if (QWindowSystemInterfacePrivate::eventHandler) {
+ if (QWindowSystemInterfacePrivate::eventHandler->sendEvent(event))
+ nevents++;
+ } else {
+ nevents++;
+ QGuiApplicationPrivate::processWindowSystemEvent(event);
+ }
+
+ // Record the accepted state for the processed event
+ // (excluding flush events). This state can then be
+ // returned by flushWindowSystemEvents().
+ if (event->type != QWindowSystemInterfacePrivate::FlushEvents)
+ QWindowSystemInterfacePrivate::eventAccepted.store(event->eventAccepted);
+
+ delete event;
+ }
+
+ return (nevents > 0);
+}
+
+void QWindowSystemInterface::setSynchronousWindowSystemEvents(bool enable)
+{
+ QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = enable;
+}
+
+int QWindowSystemInterface::windowSystemEventsQueued()
+{
+ return QWindowSystemInterfacePrivate::windowSystemEventsQueued();
+}
+
+// --------------------- QtTestLib support ---------------------
+
// The following functions are used by testlib, and need to be synchronous to avoid
// race conditions with plugins delivering native events from secondary threads.
-Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp)
+Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *window, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods, int timestamp)
{
- const qreal factor = QHighDpiScaling::factor(w);
- QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(w, timestamp, local * factor, global * factor, b, mods);
+ const qreal factor = QHighDpiScaling::factor(window);
+ QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(window, timestamp, local * factor, global * factor, b, mods);
}
-Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1)
+Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *window, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1)
{
- QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(w, t, k, mods, text, autorep, count);
+ QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(window, t, k, mods, text, autorep, count);
}
Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1)
@@ -977,35 +1015,13 @@ namespace QTest
}
}
-Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, QTouchDevice *device,
+Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *window, QTouchDevice *device,
const QList<QTouchEvent::TouchPoint> &points,
Qt::KeyboardModifiers mods = Qt::NoModifier)
{
- QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(w, device,
- QWindowSystemInterfacePrivate::toNativeTouchPoints(points, w), mods);
-}
-
-QWindowSystemEventHandler::~QWindowSystemEventHandler()
-{
- QWindowSystemInterfacePrivate::removeWindowSystemEventhandler(this);
-}
-
-bool QWindowSystemEventHandler::sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
-{
- QGuiApplicationPrivate::processWindowSystemEvent(e);
- return true;
+ QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(window, device,
+ QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window), mods);
}
-QWindowSystemInterfacePrivate::WheelEvent::WheelEvent(QWindow *w, ulong time, const QPointF &local, const QPointF &global, QPoint pixelD,
- QPoint angleD, int qt4D, Qt::Orientation qt4O, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource src, bool inverted)
- : InputEvent(w, time, Wheel, mods), pixelDelta(pixelD), angleDelta(angleD), qt4Delta(qt4D),
- qt4Orientation(qt4O), localPos(local), globalPos(global), phase(phase), source(src), inverted(inverted)
-{
-}
-
-void QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(bool v)
-{
- platformSynthesizesMouse = v;
-}
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index 3be3c3188c..b6b57e01f5 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -77,44 +77,44 @@ public:
struct DefaultDelivery {};
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
+ static void handleMouseEvent(QWindow *window, const QPointF &local, const QPointF &global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods = Qt::NoModifier,
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
+ static void handleMouseEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods = Qt::NoModifier,
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
- static void handleFrameStrutMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
+ static void handleFrameStrutMouseEvent(QWindow *window, const QPointF &local, const QPointF &global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods = Qt::NoModifier,
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
- static void handleFrameStrutMouseEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, Qt::MouseButtons b,
+ static void handleFrameStrutMouseEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b,
Qt::KeyboardModifiers mods = Qt::NoModifier,
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
- static bool handleShortcutEvent(QWindow *w, ulong timestamp, int k, Qt::KeyboardModifiers mods, quint32 nativeScanCode,
+ static bool handleShortcutEvent(QWindow *window, ulong timestamp, int k, Qt::KeyboardModifiers mods, quint32 nativeScanCode,
quint32 nativeVirtualKey, quint32 nativeModifiers, const QString & text = QString(), bool autorep = false, ushort count = 1);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static bool handleKeyEvent(QWindow *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
+ static bool handleKeyEvent(QWindow *window, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static bool handleKeyEvent(QWindow *w, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
+ static bool handleKeyEvent(QWindow *window, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1);
- static bool handleExtendedKeyEvent(QWindow *w, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
+ static bool handleExtendedKeyEvent(QWindow *window, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
const QString& text = QString(), bool autorep = false,
ushort count = 1, bool tryShortcutOverride = true);
- static bool handleExtendedKeyEvent(QWindow *w, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
+ static bool handleExtendedKeyEvent(QWindow *window, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
const QString& text = QString(), bool autorep = false,
ushort count = 1, bool tryShortcutOverride = true);
- static void handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global,
+ static void handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global,
QPoint pixelDelta, QPoint angleDelta,
Qt::KeyboardModifiers mods = Qt::NoModifier,
Qt::ScrollPhase phase = Qt::NoScrollPhase,
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
- static void handleWheelEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global,
+ static void handleWheelEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global,
QPoint pixelDelta, QPoint angleDelta,
Qt::KeyboardModifiers mods = Qt::NoModifier,
Qt::ScrollPhase phase = Qt::NoScrollPhase,
@@ -122,8 +122,8 @@ public:
bool inverted = false);
// Wheel event compatibility functions. Will be removed: do not use.
- static void handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier);
- static void handleWheelEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier);
+ static void handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier);
+ static void handleWheelEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier);
struct TouchPoint {
TouchPoint() : id(0), uniqueId(-1), pressure(0), rotation(0), state(Qt::TouchPointStationary) { }
@@ -131,9 +131,11 @@ public:
qint64 uniqueId; // for TUIO: object/token ID; otherwise empty
// TODO for TUIO 2.0: add registerPointerUniqueID(QPointerUniqueId)
QPointF normalPosition; // touch device coordinates, (0 to 1, 0 to 1)
- QRectF area; // the touched area, centered at position in screen coordinates
+ QRectF area; // dimensions of the elliptical contact patch, unrotated, and centered at position in screen coordinates
+ // width is the horizontal diameter, height is the vertical diameter
qreal pressure; // 0 to 1
- qreal rotation; // 0 means pointing straight up; 0 if unknown (like QTabletEvent::rotation)
+ qreal rotation; // rotation applied to the elliptical contact patch
+ // 0 means pointing straight up; 0 if unknown (like QTabletEvent::rotation)
Qt::TouchPointState state; //Qt::TouchPoint{Pressed|Moved|Stationary|Released}
QVector2D velocity; // in screen coordinate system, pixels / seconds
QTouchEvent::TouchPoint::InfoFlags flags;
@@ -145,43 +147,43 @@ public:
static bool isTouchDeviceRegistered(const QTouchDevice *device);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleTouchEvent(QWindow *w, QTouchDevice *device,
+ static void handleTouchEvent(QWindow *window, QTouchDevice *device,
const QList<struct TouchPoint> &points, Qt::KeyboardModifiers mods = Qt::NoModifier);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleTouchEvent(QWindow *w, ulong timestamp, QTouchDevice *device,
+ static void handleTouchEvent(QWindow *window, ulong timestamp, QTouchDevice *device,
const QList<struct TouchPoint> &points, Qt::KeyboardModifiers mods = Qt::NoModifier);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleTouchCancelEvent(QWindow *w, QTouchDevice *device, Qt::KeyboardModifiers mods = Qt::NoModifier);
+ static void handleTouchCancelEvent(QWindow *window, QTouchDevice *device, Qt::KeyboardModifiers mods = Qt::NoModifier);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleTouchCancelEvent(QWindow *w, ulong timestamp, QTouchDevice *device, Qt::KeyboardModifiers mods = Qt::NoModifier);
+ static void handleTouchCancelEvent(QWindow *window, ulong timestamp, QTouchDevice *device, Qt::KeyboardModifiers mods = Qt::NoModifier);
// rect is relative to parent
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleGeometryChange(QWindow *w, const QRect &newRect, const QRect &oldRect = QRect());
+ static void handleGeometryChange(QWindow *window, const QRect &newRect, const QRect &oldRect = QRect());
// region is in local coordinates, do not confuse with geometry which is parent-relative
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleExposeEvent(QWindow *tlw, const QRegion &region);
+ static void handleExposeEvent(QWindow *window, const QRegion &region);
- static void handleCloseEvent(QWindow *w, bool *accepted = Q_NULLPTR);
+ static void handleCloseEvent(QWindow *window, bool *accepted = Q_NULLPTR);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleEnterEvent(QWindow *w, const QPointF &local = QPointF(), const QPointF& global = QPointF());
+ static void handleEnterEvent(QWindow *window, const QPointF &local = QPointF(), const QPointF& global = QPointF());
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleLeaveEvent(QWindow *w);
+ static void handleLeaveEvent(QWindow *window);
static void handleEnterLeaveEvent(QWindow *enter, QWindow *leave, const QPointF &local = QPointF(), const QPointF& global = QPointF());
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleWindowActivated(QWindow *w, Qt::FocusReason r = Qt::OtherFocusReason);
+ static void handleWindowActivated(QWindow *window, Qt::FocusReason r = Qt::OtherFocusReason);
- static void handleWindowStateChanged(QWindow *w, Qt::WindowState newState);
- static void handleWindowScreenChanged(QWindow *w, QScreen *newScreen);
+ static void handleWindowStateChanged(QWindow *window, Qt::WindowState newState);
+ static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen);
static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false);
#ifndef QT_NO_DRAGANDDROP
// Drag and drop. These events are sent immediately.
- 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 QPlatformDragQtResponse handleDrag(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions);
+ static QPlatformDropQtResponse handleDrop(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions);
#endif
static bool handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result);
@@ -192,24 +194,24 @@ public:
static void handleScreenLogicalDotsPerInchChange(QScreen *screen, qreal newDpiX, qreal newDpiY);
static void handleScreenRefreshRateChange(QScreen *screen, qreal newRefreshRate);
- static void handleThemeChange(QWindow *tlw);
+ static void handleThemeChange(QWindow *window);
static void handleFileOpenEvent(const QString& fileName);
static void handleFileOpenEvent(const QUrl &url);
- static void handleTabletEvent(QWindow *w, ulong timestamp, const QPointF &local, const QPointF &global,
+ static void handleTabletEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global,
int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qint64 uid,
Qt::KeyboardModifiers modifiers = Qt::NoModifier);
- static void handleTabletEvent(QWindow *w, const QPointF &local, const QPointF &global,
+ static void handleTabletEvent(QWindow *window, const QPointF &local, const QPointF &global,
int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qint64 uid,
Qt::KeyboardModifiers modifiers = Qt::NoModifier);
- static void handleTabletEvent(QWindow *w, ulong timestamp, bool down, const QPointF &local, const QPointF &global,
+ static void handleTabletEvent(QWindow *window, ulong timestamp, bool down, const QPointF &local, const QPointF &global,
int device, int pointerType, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qint64 uid,
Qt::KeyboardModifiers modifiers = Qt::NoModifier); // ### remove in Qt 6
- static void handleTabletEvent(QWindow *w, bool down, const QPointF &local, const QPointF &global,
+ static void handleTabletEvent(QWindow *window, bool down, const QPointF &local, const QPointF &global,
int device, int pointerType, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qint64 uid,
Qt::KeyboardModifiers modifiers = Qt::NoModifier); // ### remove in Qt 6
@@ -227,9 +229,9 @@ public:
ulong sequenceId, quint64 value, QPointF &local, QPointF &global);
#endif // QT_NO_GESTURES
- static void handlePlatformPanelEvent(QWindow *w);
+ static void handlePlatformPanelEvent(QWindow *window);
#ifndef QT_NO_CONTEXTMENU
- static void handleContextMenuEvent(QWindow *w, bool mouseTriggered,
+ static void handleContextMenuEvent(QWindow *window, bool mouseTriggered,
const QPoint &pos, const QPoint &globalPos,
Qt::KeyboardModifiers modifiers);
#endif
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
index 7c9b1f2852..1db60e8cb8 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -131,10 +131,10 @@ public:
class GeometryChangeEvent : public WindowSystemEvent {
public:
- GeometryChangeEvent(QWindow *tlw, const QRect &newGeometry, const QRect &oldGeometry)
- : WindowSystemEvent(GeometryChange), tlw(tlw), newGeometry(newGeometry), oldGeometry(oldGeometry)
+ GeometryChangeEvent(QWindow *window, const QRect &newGeometry, const QRect &oldGeometry)
+ : WindowSystemEvent(GeometryChange), window(window), newGeometry(newGeometry), oldGeometry(oldGeometry)
{ }
- QPointer<QWindow> tlw;
+ QPointer<QWindow> window;
QRect newGeometry;
QRect oldGeometry;
};
@@ -226,11 +226,11 @@ public:
class MouseEvent : public InputEvent {
public:
- MouseEvent(QWindow * w, ulong time, const QPointF & local, const QPointF & global,
+ MouseEvent(QWindow * w, ulong time, const QPointF &local, const QPointF &global,
Qt::MouseButtons b, Qt::KeyboardModifiers mods,
Qt::MouseEventSource src = Qt::MouseEventNotSynthesized)
: InputEvent(w, time, Mouse, mods), localPos(local), globalPos(global), buttons(b), source(src) { }
- MouseEvent(QWindow * w, ulong time, EventType t, const QPointF & local, const QPointF & global,
+ MouseEvent(QWindow * w, ulong time, EventType t, const QPointF &local, const QPointF &global,
Qt::MouseButtons b, Qt::KeyboardModifiers mods,
Qt::MouseEventSource src = Qt::MouseEventNotSynthesized)
: InputEvent(w, time, t, mods), localPos(local), globalPos(global), buttons(b), source(src) { }
@@ -242,7 +242,7 @@ public:
class WheelEvent : public InputEvent {
public:
- WheelEvent(QWindow *w, ulong time, const QPointF & local, const QPointF & global, QPoint pixelD, QPoint angleD, int qt4D, Qt::Orientation qt4O,
+ WheelEvent(QWindow *w, ulong time, const QPointF &local, const QPointF &global, QPoint pixelD, QPoint angleD, int qt4D, Qt::Orientation qt4O,
Qt::KeyboardModifiers mods, Qt::ScrollPhase phase = Qt::NoScrollPhase, Qt::MouseEventSource src = Qt::MouseEventNotSynthesized, bool inverted = false);
QPoint pixelDelta;
QPoint angleDelta;
@@ -494,10 +494,6 @@ public:
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
static bool handleWindowSystemEvent(WindowSystemEvent *ev);
-private:
- static void postWindowSystemEvent(WindowSystemEvent *ev);
- static bool processWindowSystemEvent(WindowSystemEvent *ev);
-
public:
static QElapsedTimer eventTime;
static bool synchronousWindowSystemEvents;
@@ -508,7 +504,7 @@ public:
static QList<QTouchEvent::TouchPoint>
fromNativeTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points,
- const QWindow *window, QEvent::Type *type = Q_NULLPTR);
+ const QWindow *window, quint8 deviceId, QEvent::Type *type = Q_NULLPTR);
static QList<QWindowSystemInterface::TouchPoint>
toNativeTouchPoints(const QList<QTouchEvent::TouchPoint>& pointList,
const QWindow *window);
diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri
index 1a1022b3a7..4c778b184e 100644
--- a/src/gui/opengl/opengl.pri
+++ b/src/gui/opengl/opengl.pri
@@ -33,7 +33,8 @@ qtConfig(opengl) {
opengl/qopengltexture_p.h \
opengl/qopengltexturehelper_p.h \
opengl/qopenglpixeltransferoptions.h \
- opengl/qopenglextrafunctions.h
+ opengl/qopenglextrafunctions.h \
+ opengl/qopenglprogrambinarycache_p.h
SOURCES += opengl/qopengl.cpp \
opengl/qopenglfunctions.cpp \
@@ -55,7 +56,8 @@ qtConfig(opengl) {
opengl/qopengltextureblitter.cpp \
opengl/qopengltexture.cpp \
opengl/qopengltexturehelper.cpp \
- opengl/qopenglpixeltransferoptions.cpp
+ opengl/qopenglpixeltransferoptions.cpp \
+ opengl/qopenglprogrambinarycache.cpp
!qtConfig(opengles2) {
HEADERS += opengl/qopenglfunctions_1_0.h \
diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp
index eb08492254..e61473cb7b 100644
--- a/src/gui/opengl/qopengl.cpp
+++ b/src/gui/opengl/qopengl.cpp
@@ -42,6 +42,7 @@
#include "qopenglcontext.h"
#include "qopenglfunctions.h"
+#include "qoperatingsystemversion.h"
#include "qoffscreensurface.h"
#include <QtCore/QDebug>
@@ -221,29 +222,25 @@ struct OsTypeTerm
static QString hostOsRelease() {
QString ver;
#ifdef Q_OS_WIN
- switch (QSysInfo::windowsVersion()) {
- case QSysInfo::WV_XP:
- case QSysInfo::WV_2003:
- ver = QStringLiteral("xp");
- break;
- case QSysInfo::WV_VISTA:
- ver = QStringLiteral("vista");
- break;
- case QSysInfo::WV_WINDOWS7:
+ const auto osver = QOperatingSystemVersion::current();
+#define Q_WINVER(major, minor) (major << 8 | minor)
+ switch (Q_WINVER(osver.majorVersion(), osver.minorVersion())) {
+ case Q_WINVER(6, 1):
ver = QStringLiteral("7");
break;
- case QSysInfo::WV_WINDOWS8:
+ case Q_WINVER(6, 2):
ver = QStringLiteral("8");
break;
- case QSysInfo::WV_WINDOWS8_1:
+ case Q_WINVER(6, 3):
ver = QStringLiteral("8.1");
break;
- case QSysInfo::WV_WINDOWS10:
+ case Q_WINVER(10, 0):
ver = QStringLiteral("10");
break;
default:
break;
}
+#undef Q_WINVER
#endif
return ver;
}
diff --git a/src/gui/opengl/qopengldebug.h b/src/gui/opengl/qopengldebug.h
index 74b2731f7e..6b10c36291 100644
--- a/src/gui/opengl/qopengldebug.h
+++ b/src/gui/opengl/qopengldebug.h
@@ -52,6 +52,11 @@
#include <QtCore/qdebug.h>
#include <QtGui/qopenglcontext.h>
+#if defined(Q_CLANG_QDOC)
+#undef GLuint
+typedef unsigned int GLuint;
+#endif
+
QT_BEGIN_NAMESPACE
class QOpenGLDebugLogger;
diff --git a/src/gui/opengl/qopenglengineshadermanager.cpp b/src/gui/opengl/qopenglengineshadermanager.cpp
index 1d3e47f93b..c7e457b364 100644
--- a/src/gui/opengl/qopenglengineshadermanager.cpp
+++ b/src/gui/opengl/qopenglengineshadermanager.cpp
@@ -208,8 +208,6 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context)
snippetsPopulated = true;
}
- QOpenGLShader* fragShader;
- QOpenGLShader* vertexShader;
QByteArray vertexSource;
QByteArray fragSource;
@@ -227,19 +225,11 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context)
bool inCache = simpleShaderCache.load(simpleShaderProg, context);
if (!inCache) {
- vertexShader = new QOpenGLShader(QOpenGLShader::Vertex);
- shaders.append(vertexShader);
- if (!vertexShader->compileSourceCode(vertexSource))
+ if (!simpleShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource))
qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile");
-
- fragShader = new QOpenGLShader(QOpenGLShader::Fragment);
- shaders.append(fragShader);
- if (!fragShader->compileSourceCode(fragSource))
+ if (!simpleShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource))
qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile");
- simpleShaderProg->addShader(vertexShader);
- simpleShaderProg->addShader(fragShader);
-
simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
@@ -271,19 +261,11 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context)
inCache = blitShaderCache.load(blitShaderProg, context);
if (!inCache) {
- vertexShader = new QOpenGLShader(QOpenGLShader::Vertex);
- shaders.append(vertexShader);
- if (!vertexShader->compileSourceCode(vertexSource))
+ if (!blitShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource))
qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile");
-
- fragShader = new QOpenGLShader(QOpenGLShader::Fragment);
- shaders.append(fragShader);
- if (!fragShader->compileSourceCode(fragSource))
+ if (!blitShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource))
qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile");
- blitShaderProg->addShader(vertexShader);
- blitShaderProg->addShader(fragShader);
-
blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
}
@@ -306,9 +288,6 @@ QOpenGLEngineSharedShaders::~QOpenGLEngineSharedShaders()
#ifdef QT_GL_SHARED_SHADER_DEBUG
qDebug(" -> ~QOpenGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread());
#endif
- qDeleteAll(shaders);
- shaders.clear();
-
qDeleteAll(cachedPrograms);
cachedPrograms.clear();
@@ -370,50 +349,37 @@ QOpenGLEngineShaderProg *QOpenGLEngineSharedShaders::findProgramInCache(const QO
bool inCache = shaderCache.load(shaderProgram.data(), QOpenGLContext::currentContext());
if (!inCache) {
-
- QScopedPointer<QOpenGLShader> fragShader(new QOpenGLShader(QOpenGLShader::Fragment));
- QByteArray description;
+ if (!shaderProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource)) {
+ QByteArray description;
#if defined(QT_DEBUG)
- // Name the shader for easier debugging
- description.append("Fragment shader: main=");
- description.append(snippetNameStr(prog.mainFragShader));
- description.append(", srcPixel=");
- description.append(snippetNameStr(prog.srcPixelFragShader));
- if (prog.compositionFragShader) {
- description.append(", composition=");
- description.append(snippetNameStr(prog.compositionFragShader));
- }
- if (prog.maskFragShader) {
- description.append(", mask=");
- description.append(snippetNameStr(prog.maskFragShader));
- }
- fragShader->setObjectName(QString::fromLatin1(description));
+ description.append("Vertex shader: main=");
+ description.append(snippetNameStr(prog.mainVertexShader));
+ description.append(", position=");
+ description.append(snippetNameStr(prog.positionVertexShader));
#endif
- if (!fragShader->compileSourceCode(fragSource)) {
qWarning("Warning: \"%s\" failed to compile!", description.constData());
break;
}
-
- QScopedPointer<QOpenGLShader> vertexShader(new QOpenGLShader(QOpenGLShader::Vertex));
+ if (!shaderProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource)) {
+ QByteArray description;
#if defined(QT_DEBUG)
- // Name the shader for easier debugging
- description.clear();
- description.append("Vertex shader: main=");
- description.append(snippetNameStr(prog.mainVertexShader));
- description.append(", position=");
- description.append(snippetNameStr(prog.positionVertexShader));
- vertexShader->setObjectName(QString::fromLatin1(description));
+ description.append("Fragment shader: main=");
+ description.append(snippetNameStr(prog.mainFragShader));
+ description.append(", srcPixel=");
+ description.append(snippetNameStr(prog.srcPixelFragShader));
+ if (prog.compositionFragShader) {
+ description.append(", composition=");
+ description.append(snippetNameStr(prog.compositionFragShader));
+ }
+ if (prog.maskFragShader) {
+ description.append(", mask=");
+ description.append(snippetNameStr(prog.maskFragShader));
+ }
#endif
- if (!vertexShader->compileSourceCode(vertexSource)) {
qWarning("Warning: \"%s\" failed to compile!", description.constData());
break;
}
- shaders.append(vertexShader.data());
- shaders.append(fragShader.data());
- shaderProgram->addShader(vertexShader.take());
- shaderProgram->addShader(fragShader.take());
-
// We have to bind the vertex attribute names before the program is linked:
shaderProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
if (prog.useTextureCoords)
@@ -436,18 +402,9 @@ QOpenGLEngineShaderProg *QOpenGLEngineSharedShaders::findProgramInCache(const QO
shaderCache.store(newProg->program, QOpenGLContext::currentContext());
} else {
QString error;
- error = QLatin1String("Shader program failed to link,");
-#if defined(QT_DEBUG)
- QLatin1String br("\n");
- error += QLatin1String("\n Shaders Used:\n");
- for (int i = 0; i < newProg->program->shaders().count(); ++i) {
- QOpenGLShader *shader = newProg->program->shaders().at(i);
- error += QLatin1String(" ") + shader->objectName() + QLatin1String(": \n")
- + QLatin1String(shader->sourceCode()) + br;
- }
-#endif
- error += QLatin1String(" Error Log:\n")
- + QLatin1String(" ") + newProg->program->log();
+ error = QLatin1String("Shader program failed to link")
+ + QLatin1String(" Error Log:\n")
+ + QLatin1String(" ") + newProg->program->log();
qWarning() << error;
break;
}
diff --git a/src/gui/opengl/qopenglengineshadermanager_p.h b/src/gui/opengl/qopenglengineshadermanager_p.h
index 23b2ccf486..377501457d 100644
--- a/src/gui/opengl/qopenglengineshadermanager_p.h
+++ b/src/gui/opengl/qopenglengineshadermanager_p.h
@@ -366,7 +366,6 @@ private:
QOpenGLShaderProgram *blitShaderProg;
QOpenGLShaderProgram *simpleShaderProg;
QList<QOpenGLEngineShaderProg*> cachedPrograms;
- QList<QOpenGLShader *> shaders;
static const char* qShaderSnippets[TotalSnippetCount];
};
diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h
index aad48571b3..f1a717f659 100644
--- a/src/gui/opengl/qopenglfunctions.h
+++ b/src/gui/opengl/qopenglfunctions.h
@@ -591,499 +591,319 @@ struct QOpenGLFunctionsPrivate
inline void QOpenGLFunctions::glBindTexture(GLenum target, GLuint texture)
{
-#ifdef QT_OPENGL_ES_2
- ::glBindTexture(target, texture);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.BindTexture(target, texture);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glBlendFunc(GLenum sfactor, GLenum dfactor)
{
-#ifdef QT_OPENGL_ES_2
- ::glBlendFunc(sfactor, dfactor);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.BlendFunc(sfactor, dfactor);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glClear(GLbitfield mask)
{
-#ifdef QT_OPENGL_ES_2
- ::glClear(mask);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Clear(mask);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
{
-#ifdef QT_OPENGL_ES_2
- ::glClearColor(red, green, blue, alpha);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.ClearColor(red, green, blue, alpha);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glClearStencil(GLint s)
{
-#ifdef QT_OPENGL_ES_2
- ::glClearStencil(s);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.ClearStencil(s);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
{
-#ifdef QT_OPENGL_ES_2
- ::glColorMask(red, green, blue, alpha);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.ColorMask(red, green, blue, alpha);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
{
-#ifdef QT_OPENGL_ES_2
- ::glCopyTexImage2D(target, level, internalformat, x, y, width,height, border);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.CopyTexImage2D(target, level, internalformat, x, y, width,height, border);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
{
-#ifdef QT_OPENGL_ES_2
- ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glCullFace(GLenum mode)
{
-#ifdef QT_OPENGL_ES_2
- ::glCullFace(mode);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.CullFace(mode);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDeleteTextures(GLsizei n, const GLuint* textures)
{
-#ifdef QT_OPENGL_ES_2
- ::glDeleteTextures(n, textures);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DeleteTextures(n, textures);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDepthFunc(GLenum func)
{
-#ifdef QT_OPENGL_ES_2
- ::glDepthFunc(func);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DepthFunc(func);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDepthMask(GLboolean flag)
{
-#ifdef QT_OPENGL_ES_2
- ::glDepthMask(flag);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DepthMask(flag);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDisable(GLenum cap)
{
-#ifdef QT_OPENGL_ES_2
- ::glDisable(cap);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Disable(cap);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDrawArrays(GLenum mode, GLint first, GLsizei count)
{
-#ifdef QT_OPENGL_ES_2
- ::glDrawArrays(mode, first, count);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DrawArrays(mode, first, count);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
{
-#ifdef QT_OPENGL_ES_2
- ::glDrawElements(mode, count, type, indices);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DrawElements(mode, count, type, indices);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glEnable(GLenum cap)
{
-#ifdef QT_OPENGL_ES_2
- ::glEnable(cap);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Enable(cap);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glFinish()
{
-#ifdef QT_OPENGL_ES_2
- ::glFinish();
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Finish();
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glFlush()
{
-#ifdef QT_OPENGL_ES_2
- ::glFlush();
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Flush();
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glFrontFace(GLenum mode)
{
-#ifdef QT_OPENGL_ES_2
- ::glFrontFace(mode);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.FrontFace(mode);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGenTextures(GLsizei n, GLuint* textures)
{
-#ifdef QT_OPENGL_ES_2
- ::glGenTextures(n, textures);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GenTextures(n, textures);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetBooleanv(GLenum pname, GLboolean* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetBooleanv(pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetBooleanv(pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline GLenum QOpenGLFunctions::glGetError()
{
-#ifdef QT_OPENGL_ES_2
- GLenum result = ::glGetError();
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLenum result = d_ptr->f.GetError();
-#endif
return result;
}
inline void QOpenGLFunctions::glGetFloatv(GLenum pname, GLfloat* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetFloatv(pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetFloatv(pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetIntegerv(GLenum pname, GLint* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetIntegerv(pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetIntegerv(pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline const GLubyte *QOpenGLFunctions::glGetString(GLenum name)
{
-#ifdef QT_OPENGL_ES_2
- const GLubyte *result = ::glGetString(name);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
const GLubyte *result = d_ptr->f.GetString(name);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline void QOpenGLFunctions::glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetTexParameterfv(target, pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetTexParameterfv(target, pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetTexParameteriv(target, pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetTexParameteriv(target, pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glHint(GLenum target, GLenum mode)
{
-#ifdef QT_OPENGL_ES_2
- ::glHint(target, mode);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Hint(target, mode);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline GLboolean QOpenGLFunctions::glIsEnabled(GLenum cap)
{
-#ifdef QT_OPENGL_ES_2
- GLboolean result = ::glIsEnabled(cap);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLboolean result = d_ptr->f.IsEnabled(cap);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline GLboolean QOpenGLFunctions::glIsTexture(GLuint texture)
{
-#ifdef QT_OPENGL_ES_2
- GLboolean result = ::glIsTexture(texture);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLboolean result = d_ptr->f.IsTexture(texture);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline void QOpenGLFunctions::glLineWidth(GLfloat width)
{
-#ifdef QT_OPENGL_ES_2
- ::glLineWidth(width);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.LineWidth(width);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glPixelStorei(GLenum pname, GLint param)
{
-#ifdef QT_OPENGL_ES_2
- ::glPixelStorei(pname, param);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.PixelStorei(pname, param);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glPolygonOffset(GLfloat factor, GLfloat units)
{
-#ifdef QT_OPENGL_ES_2
- ::glPolygonOffset(factor, units);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.PolygonOffset(factor, units);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
{
-#ifdef QT_OPENGL_ES_2
- ::glReadPixels(x, y, width, height, format, type, pixels);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.ReadPixels(x, y, width, height, format, type, pixels);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
{
-#ifdef QT_OPENGL_ES_2
- ::glScissor(x, y, width, height);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Scissor(x, y, width, height);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glStencilFunc(GLenum func, GLint ref, GLuint mask)
{
-#ifdef QT_OPENGL_ES_2
- ::glStencilFunc(func, ref, mask);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.StencilFunc(func, ref, mask);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glStencilMask(GLuint mask)
{
-#ifdef QT_OPENGL_ES_2
- ::glStencilMask(mask);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.StencilMask(mask);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
{
-#ifdef QT_OPENGL_ES_2
- ::glStencilOp(fail, zfail, zpass);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.StencilOp(fail, zfail, zpass);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
{
-#ifdef QT_OPENGL_ES_2
- ::glTexImage2D(target, level, internalformat, width,height, border, format, type, pixels);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.TexImage2D(target, level, internalformat, width,height, border, format, type, pixels);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glTexParameterf(GLenum target, GLenum pname, GLfloat param)
{
-#ifdef QT_OPENGL_ES_2
- ::glTexParameterf(target, pname, param);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.TexParameterf(target, pname, param);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glTexParameterfv(target, pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.TexParameterfv(target, pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glTexParameteri(GLenum target, GLenum pname, GLint param)
{
-#ifdef QT_OPENGL_ES_2
- ::glTexParameteri(target, pname, param);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.TexParameteri(target, pname, param);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glTexParameteriv(target, pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.TexParameteriv(target, pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels)
{
-#ifdef QT_OPENGL_ES_2
- ::glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
{
-#ifdef QT_OPENGL_ES_2
- ::glViewport(x, y, width, height);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Viewport(x, y, width, height);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
@@ -1091,45 +911,29 @@ inline void QOpenGLFunctions::glViewport(GLint x, GLint y, GLsizei width, GLsize
inline void QOpenGLFunctions::glActiveTexture(GLenum texture)
{
-#ifdef QT_OPENGL_ES_2
- ::glActiveTexture(texture);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.ActiveTexture(texture);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glAttachShader(GLuint program, GLuint shader)
{
-#ifdef QT_OPENGL_ES_2
- ::glAttachShader(program, shader);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.AttachShader(program, shader);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glBindAttribLocation(GLuint program, GLuint index, const char* name)
{
-#ifdef QT_OPENGL_ES_2
- ::glBindAttribLocation(program, index, name);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.BindAttribLocation(program, index, name);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glBindBuffer(GLenum target, GLuint buffer)
{
-#ifdef QT_OPENGL_ES_2
- ::glBindBuffer(target, buffer);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.BindBuffer(target, buffer);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
@@ -1137,1034 +941,662 @@ inline void QOpenGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffe
{
if (framebuffer == 0)
framebuffer = QOpenGLContext::currentContext()->defaultFramebufferObject();
-#ifdef QT_OPENGL_ES_2
- ::glBindFramebuffer(target, framebuffer);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.BindFramebuffer(target, framebuffer);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glBindRenderbuffer(GLenum target, GLuint renderbuffer)
{
-#ifdef QT_OPENGL_ES_2
- ::glBindRenderbuffer(target, renderbuffer);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.BindRenderbuffer(target, renderbuffer);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
{
-#ifdef QT_OPENGL_ES_2
- ::glBlendColor(red, green, blue, alpha);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.BlendColor(red, green, blue, alpha);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glBlendEquation(GLenum mode)
{
-#ifdef QT_OPENGL_ES_2
- ::glBlendEquation(mode);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.BlendEquation(mode);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
{
-#ifdef QT_OPENGL_ES_2
- ::glBlendEquationSeparate(modeRGB, modeAlpha);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.BlendEquationSeparate(modeRGB, modeAlpha);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
{
-#ifdef QT_OPENGL_ES_2
- ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.BlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glBufferData(GLenum target, qopengl_GLsizeiptr size, const void* data, GLenum usage)
{
-#ifdef QT_OPENGL_ES_2
- ::glBufferData(target, size, data, usage);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.BufferData(target, size, data, usage);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glBufferSubData(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, const void* data)
{
-#ifdef QT_OPENGL_ES_2
- ::glBufferSubData(target, offset, size, data);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.BufferSubData(target, offset, size, data);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline GLenum QOpenGLFunctions::glCheckFramebufferStatus(GLenum target)
{
-#ifdef QT_OPENGL_ES_2
- GLenum result = ::glCheckFramebufferStatus(target);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLenum result = d_ptr->f.CheckFramebufferStatus(target);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline void QOpenGLFunctions::glClearDepthf(GLclampf depth)
{
-#ifndef QT_OPENGL_ES
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.ClearDepthf(depth);
-#else
- ::glClearDepthf(depth);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glCompileShader(GLuint shader)
{
-#ifdef QT_OPENGL_ES_2
- ::glCompileShader(shader);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.CompileShader(shader);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data)
{
-#ifdef QT_OPENGL_ES_2
- ::glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
{
-#ifdef QT_OPENGL_ES_2
- ::glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline GLuint QOpenGLFunctions::glCreateProgram()
{
-#ifdef QT_OPENGL_ES_2
- GLuint result = ::glCreateProgram();
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLuint result = d_ptr->f.CreateProgram();
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline GLuint QOpenGLFunctions::glCreateShader(GLenum type)
{
-#ifdef QT_OPENGL_ES_2
- GLuint result = ::glCreateShader(type);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLuint result = d_ptr->f.CreateShader(type);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline void QOpenGLFunctions::glDeleteBuffers(GLsizei n, const GLuint* buffers)
{
-#ifdef QT_OPENGL_ES_2
- ::glDeleteBuffers(n, buffers);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DeleteBuffers(n, buffers);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
{
-#ifdef QT_OPENGL_ES_2
- ::glDeleteFramebuffers(n, framebuffers);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DeleteFramebuffers(n, framebuffers);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDeleteProgram(GLuint program)
{
-#ifdef QT_OPENGL_ES_2
- ::glDeleteProgram(program);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DeleteProgram(program);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
{
-#ifdef QT_OPENGL_ES_2
- ::glDeleteRenderbuffers(n, renderbuffers);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DeleteRenderbuffers(n, renderbuffers);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDeleteShader(GLuint shader)
{
-#ifdef QT_OPENGL_ES_2
- ::glDeleteShader(shader);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DeleteShader(shader);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDepthRangef(GLclampf zNear, GLclampf zFar)
{
-#ifndef QT_OPENGL_ES
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DepthRangef(zNear, zFar);
-#else
- ::glDepthRangef(zNear, zFar);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDetachShader(GLuint program, GLuint shader)
{
-#ifdef QT_OPENGL_ES_2
- ::glDetachShader(program, shader);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DetachShader(program, shader);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glDisableVertexAttribArray(GLuint index)
{
-#ifdef QT_OPENGL_ES_2
- ::glDisableVertexAttribArray(index);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.DisableVertexAttribArray(index);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glEnableVertexAttribArray(GLuint index)
{
-#ifdef QT_OPENGL_ES_2
- ::glEnableVertexAttribArray(index);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.EnableVertexAttribArray(index);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
{
-#ifdef QT_OPENGL_ES_2
- ::glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
{
-#ifdef QT_OPENGL_ES_2
- ::glFramebufferTexture2D(target, attachment, textarget, texture, level);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.FramebufferTexture2D(target, attachment, textarget, texture, level);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGenBuffers(GLsizei n, GLuint* buffers)
{
-#ifdef QT_OPENGL_ES_2
- ::glGenBuffers(n, buffers);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GenBuffers(n, buffers);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGenerateMipmap(GLenum target)
{
-#ifdef QT_OPENGL_ES_2
- ::glGenerateMipmap(target);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GenerateMipmap(target);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGenFramebuffers(GLsizei n, GLuint* framebuffers)
{
-#ifdef QT_OPENGL_ES_2
- ::glGenFramebuffers(n, framebuffers);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GenFramebuffers(n, framebuffers);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
{
-#ifdef QT_OPENGL_ES_2
- ::glGenRenderbuffers(n, renderbuffers);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GenRenderbuffers(n, renderbuffers);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetActiveAttrib(program, index, bufsize, length, size, type, name);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetActiveAttrib(program, index, bufsize, length, size, type, name);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetActiveUniform(program, index, bufsize, length, size, type, name);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetActiveUniform(program, index, bufsize, length, size, type, name);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetAttachedShaders(program, maxcount, count, shaders);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetAttachedShaders(program, maxcount, count, shaders);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline GLint QOpenGLFunctions::glGetAttribLocation(GLuint program, const char* name)
{
-#ifdef QT_OPENGL_ES_2
- GLint result = ::glGetAttribLocation(program, name);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLint result = d_ptr->f.GetAttribLocation(program, name);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline void QOpenGLFunctions::glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetBufferParameteriv(target, pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetBufferParameteriv(target, pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetProgramiv(GLuint program, GLenum pname, GLint* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetProgramiv(program, pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetProgramiv(program, pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetProgramInfoLog(program, bufsize, length, infolog);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetProgramInfoLog(program, bufsize, length, infolog);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetRenderbufferParameteriv(target, pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetRenderbufferParameteriv(target, pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetShaderiv(shader, pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetShaderiv(shader, pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetShaderInfoLog(shader, bufsize, length, infolog);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetShaderInfoLog(shader, bufsize, length, infolog);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetShaderSource(shader, bufsize, length, source);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetShaderSource(shader, bufsize, length, source);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetUniformfv(GLuint program, GLint location, GLfloat* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetUniformfv(program, location, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetUniformfv(program, location, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetUniformiv(GLuint program, GLint location, GLint* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetUniformiv(program, location, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetUniformiv(program, location, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline GLint QOpenGLFunctions::glGetUniformLocation(GLuint program, const char* name)
{
-#ifdef QT_OPENGL_ES_2
- GLint result = ::glGetUniformLocation(program, name);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLint result = d_ptr->f.GetUniformLocation(program, name);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline void QOpenGLFunctions::glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetVertexAttribfv(index, pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetVertexAttribfv(index, pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetVertexAttribiv(index, pname, params);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetVertexAttribiv(index, pname, params);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer)
{
-#ifdef QT_OPENGL_ES_2
- ::glGetVertexAttribPointerv(index, pname, pointer);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.GetVertexAttribPointerv(index, pname, pointer);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline GLboolean QOpenGLFunctions::glIsBuffer(GLuint buffer)
{
-#ifdef QT_OPENGL_ES_2
- GLboolean result = ::glIsBuffer(buffer);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLboolean result = d_ptr->f.IsBuffer(buffer);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline GLboolean QOpenGLFunctions::glIsFramebuffer(GLuint framebuffer)
{
-#ifdef QT_OPENGL_ES_2
- GLboolean result = ::glIsFramebuffer(framebuffer);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLboolean result = d_ptr->f.IsFramebuffer(framebuffer);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline GLboolean QOpenGLFunctions::glIsProgram(GLuint program)
{
-#ifdef QT_OPENGL_ES_2
- GLboolean result = ::glIsProgram(program);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLboolean result = d_ptr->f.IsProgram(program);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline GLboolean QOpenGLFunctions::glIsRenderbuffer(GLuint renderbuffer)
{
-#ifdef QT_OPENGL_ES_2
- GLboolean result = ::glIsRenderbuffer(renderbuffer);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLboolean result = d_ptr->f.IsRenderbuffer(renderbuffer);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline GLboolean QOpenGLFunctions::glIsShader(GLuint shader)
{
-#ifdef QT_OPENGL_ES_2
- GLboolean result = ::glIsShader(shader);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
GLboolean result = d_ptr->f.IsShader(shader);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
return result;
}
inline void QOpenGLFunctions::glLinkProgram(GLuint program)
{
-#ifdef QT_OPENGL_ES_2
- ::glLinkProgram(program);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.LinkProgram(program);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glReleaseShaderCompiler()
{
-#ifdef QT_OPENGL_ES_2
- ::glReleaseShaderCompiler();
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.ReleaseShaderCompiler();
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
{
-#ifdef QT_OPENGL_ES_2
- ::glRenderbufferStorage(target, internalformat, width, height);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.RenderbufferStorage(target, internalformat, width, height);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glSampleCoverage(GLclampf value, GLboolean invert)
{
-#ifdef QT_OPENGL_ES_2
- ::glSampleCoverage(value, invert);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.SampleCoverage(value, invert);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length)
{
-#ifdef QT_OPENGL_ES_2
- ::glShaderBinary(n, shaders, binaryformat, binary, length);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.ShaderBinary(n, shaders, binaryformat, binary, length);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length)
{
-#ifdef QT_OPENGL_ES_2
- ::glShaderSource(shader, count, string, length);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.ShaderSource(shader, count, string, length);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
{
-#ifdef QT_OPENGL_ES_2
- ::glStencilFuncSeparate(face, func, ref, mask);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.StencilFuncSeparate(face, func, ref, mask);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glStencilMaskSeparate(GLenum face, GLuint mask)
{
-#ifdef QT_OPENGL_ES_2
- ::glStencilMaskSeparate(face, mask);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.StencilMaskSeparate(face, mask);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
{
-#ifdef QT_OPENGL_ES_2
- ::glStencilOpSeparate(face, fail, zfail, zpass);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.StencilOpSeparate(face, fail, zfail, zpass);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform1f(GLint location, GLfloat x)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform1f(location, x);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform1f(location, x);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform1fv(location, count, v);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform1fv(location, count, v);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform1i(GLint location, GLint x)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform1i(location, x);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform1i(location, x);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform1iv(GLint location, GLsizei count, const GLint* v)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform1iv(location, count, v);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform1iv(location, count, v);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform2f(GLint location, GLfloat x, GLfloat y)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform2f(location, x, y);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform2f(location, x, y);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform2fv(location, count, v);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform2fv(location, count, v);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform2i(GLint location, GLint x, GLint y)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform2i(location, x, y);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform2i(location, x, y);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform2iv(GLint location, GLsizei count, const GLint* v)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform2iv(location, count, v);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform2iv(location, count, v);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform3f(location, x, y, z);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform3f(location, x, y, z);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform3fv(location, count, v);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform3fv(location, count, v);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform3i(GLint location, GLint x, GLint y, GLint z)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform3i(location, x, y, z);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform3i(location, x, y, z);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform3iv(GLint location, GLsizei count, const GLint* v)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform3iv(location, count, v);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform3iv(location, count, v);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform4f(location, x, y, z, w);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform4f(location, x, y, z, w);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform4fv(location, count, v);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform4fv(location, count, v);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform4i(location, x, y, z, w);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform4i(location, x, y, z, w);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniform4iv(GLint location, GLsizei count, const GLint* v)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniform4iv(location, count, v);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.Uniform4iv(location, count, v);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniformMatrix2fv(location, count, transpose, value);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.UniformMatrix2fv(location, count, transpose, value);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniformMatrix3fv(location, count, transpose, value);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.UniformMatrix3fv(location, count, transpose, value);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
-#ifdef QT_OPENGL_ES_2
- ::glUniformMatrix4fv(location, count, transpose, value);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.UniformMatrix4fv(location, count, transpose, value);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glUseProgram(GLuint program)
{
-#ifdef QT_OPENGL_ES_2
- ::glUseProgram(program);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.UseProgram(program);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glValidateProgram(GLuint program)
{
-#ifdef QT_OPENGL_ES_2
- ::glValidateProgram(program);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.ValidateProgram(program);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glVertexAttrib1f(GLuint indx, GLfloat x)
{
-#ifdef QT_OPENGL_ES_2
- ::glVertexAttrib1f(indx, x);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.VertexAttrib1f(indx, x);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glVertexAttrib1fv(GLuint indx, const GLfloat* values)
{
-#ifdef QT_OPENGL_ES_2
- ::glVertexAttrib1fv(indx, values);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.VertexAttrib1fv(indx, values);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
{
-#ifdef QT_OPENGL_ES_2
- ::glVertexAttrib2f(indx, x, y);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.VertexAttrib2f(indx, x, y);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glVertexAttrib2fv(GLuint indx, const GLfloat* values)
{
-#ifdef QT_OPENGL_ES_2
- ::glVertexAttrib2fv(indx, values);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.VertexAttrib2fv(indx, values);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
{
-#ifdef QT_OPENGL_ES_2
- ::glVertexAttrib3f(indx, x, y, z);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.VertexAttrib3f(indx, x, y, z);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glVertexAttrib3fv(GLuint indx, const GLfloat* values)
{
-#ifdef QT_OPENGL_ES_2
- ::glVertexAttrib3fv(indx, values);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.VertexAttrib3fv(indx, values);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
-#ifdef QT_OPENGL_ES_2
- ::glVertexAttrib4f(indx, x, y, z, w);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.VertexAttrib4f(indx, x, y, z, w);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glVertexAttrib4fv(GLuint indx, const GLfloat* values)
{
-#ifdef QT_OPENGL_ES_2
- ::glVertexAttrib4fv(indx, values);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.VertexAttrib4fv(indx, values);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
inline void QOpenGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
{
-#ifdef QT_OPENGL_ES_2
- ::glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
-#else
Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
d_ptr->f.VertexAttribPointer(indx, size, type, normalized, stride, ptr);
-#endif
Q_OPENGL_FUNCTIONS_DEBUG
}
diff --git a/src/gui/opengl/qopenglprogrambinarycache.cpp b/src/gui/opengl/qopenglprogrambinarycache.cpp
new file mode 100644
index 0000000000..5c8e425e29
--- /dev/null
+++ b/src/gui/opengl/qopenglprogrambinarycache.cpp
@@ -0,0 +1,336 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopenglprogrambinarycache_p.h"
+#include <QOpenGLContext>
+#include <QOpenGLExtraFunctions>
+#include <QStandardPaths>
+#include <QDir>
+#include <QSaveFile>
+#include <QLoggingCategory>
+
+#ifdef Q_OS_UNIX
+#include <sys/mman.h>
+#include <private/qcore_unix_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(DBG_SHADER_CACHE)
+
+#ifndef GL_PROGRAM_BINARY_LENGTH
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#endif
+
+const quint32 BINSHADER_MAGIC = 0x5174;
+const quint32 BINSHADER_VERSION = 0x1;
+const quint32 BINSHADER_QTVERSION = QT_VERSION;
+
+struct GLEnvInfo
+{
+ GLEnvInfo();
+
+ QByteArray glvendor;
+ QByteArray glrenderer;
+ QByteArray glversion;
+};
+
+GLEnvInfo::GLEnvInfo()
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ Q_ASSERT(ctx);
+ QOpenGLFunctions *f = ctx->functions();
+ const char *vendor = reinterpret_cast<const char *>(f->glGetString(GL_VENDOR));
+ const char *renderer = reinterpret_cast<const char *>(f->glGetString(GL_RENDERER));
+ const char *version = reinterpret_cast<const char *>(f->glGetString(GL_VERSION));
+ if (vendor)
+ glvendor = QByteArray(vendor);
+ if (renderer)
+ glrenderer = QByteArray(renderer);
+ if (version)
+ glversion = QByteArray(version);
+}
+
+static inline bool qt_ensureWritableDir(const QString &name)
+{
+ QDir::root().mkpath(name);
+ return QFileInfo(name).isWritable();
+}
+
+QOpenGLProgramBinaryCache::QOpenGLProgramBinaryCache()
+ : m_cacheWritable(false)
+{
+ const QString subPath = QLatin1String("/qtshadercache/");
+ const QString sharedCachePath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation);
+ if (!sharedCachePath.isEmpty()) {
+ m_cacheDir = sharedCachePath + subPath;
+ m_cacheWritable = qt_ensureWritableDir(m_cacheDir);
+ }
+ if (!m_cacheWritable) {
+ m_cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + subPath;
+ m_cacheWritable = qt_ensureWritableDir(m_cacheDir);
+ }
+ qCDebug(DBG_SHADER_CACHE, "Cache location '%s' writable = %d", qPrintable(m_cacheDir), m_cacheWritable);
+}
+
+QString QOpenGLProgramBinaryCache::cacheFileName(const QByteArray &cacheKey) const
+{
+ return m_cacheDir + QString::fromUtf8(cacheKey);
+}
+
+static const int HEADER_SIZE = 3 * sizeof(quint32);
+
+bool QOpenGLProgramBinaryCache::verifyHeader(const QByteArray &buf) const
+{
+ if (buf.size() < HEADER_SIZE) {
+ qCDebug(DBG_SHADER_CACHE, "Cached size too small");
+ return false;
+ }
+ const quint32 *p = reinterpret_cast<const quint32 *>(buf.constData());
+ if (*p++ != BINSHADER_MAGIC) {
+ qCDebug(DBG_SHADER_CACHE, "Magic does not match");
+ return false;
+ }
+ if (*p++ != BINSHADER_VERSION) {
+ qCDebug(DBG_SHADER_CACHE, "Version does not match");
+ return false;
+ }
+ if (*p++ != BINSHADER_QTVERSION) {
+ qCDebug(DBG_SHADER_CACHE, "Qt version does not match");
+ return false;
+ }
+ return true;
+}
+
+bool QOpenGLProgramBinaryCache::setProgramBinary(uint programId, uint blobFormat, const void *p, uint blobSize)
+{
+ QOpenGLExtraFunctions *funcs = QOpenGLContext::currentContext()->extraFunctions();
+ while (funcs->glGetError() != GL_NO_ERROR) { }
+ funcs->glProgramBinary(programId, blobFormat, p, blobSize);
+ int err = funcs->glGetError();
+ qCDebug(DBG_SHADER_CACHE, "Program binary set for program %u, size %d, format 0x%x, err = 0x%x",
+ programId, blobSize, blobFormat, err);
+ return err == 0;
+}
+
+#ifdef Q_OS_UNIX
+class FdWrapper
+{
+public:
+ FdWrapper(const QString &fn)
+ : ptr(MAP_FAILED)
+ {
+ fd = qt_safe_open(QFile::encodeName(fn).constData(), O_RDONLY);
+ }
+ ~FdWrapper()
+ {
+ if (ptr != MAP_FAILED)
+ munmap(ptr, mapSize);
+ if (fd != -1)
+ qt_safe_close(fd);
+ }
+ bool map()
+ {
+ off_t offs = lseek(fd, 0, SEEK_END);
+ if (offs == (off_t) -1) {
+ qErrnoWarning(errno, "lseek failed for program binary");
+ return false;
+ }
+ mapSize = static_cast<size_t>(offs);
+ ptr = mmap(nullptr, mapSize, PROT_READ, MAP_SHARED, fd, 0);
+ return ptr != MAP_FAILED;
+ }
+
+ int fd;
+ void *ptr;
+ size_t mapSize;
+};
+#endif
+
+class DeferredFileRemove
+{
+public:
+ DeferredFileRemove(const QString &fn)
+ : fn(fn),
+ active(false)
+ {
+ }
+ ~DeferredFileRemove()
+ {
+ if (active)
+ QFile(fn).remove();
+ }
+ void setActive()
+ {
+ active = true;
+ }
+
+ QString fn;
+ bool active;
+};
+
+bool QOpenGLProgramBinaryCache::load(const QByteArray &cacheKey, uint programId)
+{
+ if (m_memCache.contains(cacheKey)) {
+ const MemCacheEntry *e = m_memCache[cacheKey];
+ return setProgramBinary(programId, e->format, e->blob.constData(), e->blob.size());
+ }
+
+ QByteArray buf;
+ const QString fn = cacheFileName(cacheKey);
+ DeferredFileRemove undertaker(fn);
+#ifdef Q_OS_UNIX
+ FdWrapper fdw(fn);
+ if (fdw.fd == -1)
+ return false;
+ char header[HEADER_SIZE];
+ qint64 bytesRead = qt_safe_read(fdw.fd, header, HEADER_SIZE);
+ if (bytesRead == HEADER_SIZE)
+ buf = QByteArray::fromRawData(header, HEADER_SIZE);
+#else
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly))
+ return false;
+ buf = f.read(HEADER_SIZE);
+#endif
+
+ if (!verifyHeader(buf)) {
+ undertaker.setActive();
+ return false;
+ }
+
+ const quint32 *p;
+#ifdef Q_OS_UNIX
+ if (!fdw.map()) {
+ undertaker.setActive();
+ return false;
+ }
+ p = reinterpret_cast<const quint32 *>(static_cast<const char *>(fdw.ptr) + HEADER_SIZE);
+#else
+ buf = f.readAll();
+ p = reinterpret_cast<const quint32 *>(buf.constData());
+#endif
+
+ GLEnvInfo info;
+
+ quint32 v = *p++;
+ QByteArray vendor = QByteArray::fromRawData(reinterpret_cast<const char *>(p), v);
+ if (vendor != info.glvendor) {
+ qCDebug(DBG_SHADER_CACHE, "GL_VENDOR does not match (%s, %s)", vendor.constData(), info.glvendor.constData());
+ undertaker.setActive();
+ return false;
+ }
+ p = reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(p) + v);
+ v = *p++;
+ QByteArray renderer = QByteArray::fromRawData(reinterpret_cast<const char *>(p), v);
+ if (renderer != info.glrenderer) {
+ qCDebug(DBG_SHADER_CACHE, "GL_RENDERER does not match (%s, %s)", renderer.constData(), info.glrenderer.constData());
+ undertaker.setActive();
+ return false;
+ }
+ p = reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(p) + v);
+ v = *p++;
+ QByteArray version = QByteArray::fromRawData(reinterpret_cast<const char *>(p), v);
+ if (version != info.glversion) {
+ qCDebug(DBG_SHADER_CACHE, "GL_VERSION does not match (%s, %s)", version.constData(), info.glversion.constData());
+ undertaker.setActive();
+ return false;
+ }
+ p = reinterpret_cast<const quint32 *>(reinterpret_cast<const char *>(p) + v);
+
+ quint32 blobFormat = *p++;
+ quint32 blobSize = *p++;
+
+ return setProgramBinary(programId, blobFormat, p, blobSize)
+ && m_memCache.insert(cacheKey, new MemCacheEntry(p, blobSize, blobFormat));
+}
+
+void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId)
+{
+ if (!m_cacheWritable)
+ return;
+
+ GLEnvInfo info;
+
+ QOpenGLExtraFunctions *funcs = QOpenGLContext::currentContext()->extraFunctions();
+ GLint blobSize = 0;
+ while (funcs->glGetError() != GL_NO_ERROR) { }
+ funcs->glGetProgramiv(programId, GL_PROGRAM_BINARY_LENGTH, &blobSize);
+ int totalSize = blobSize + 8 + 12 + 12 + info.glvendor.size() + info.glrenderer.size() + info.glversion.size();
+ qCDebug(DBG_SHADER_CACHE, "Program binary is %d bytes, err = 0x%x, total %d", blobSize, funcs->glGetError(), totalSize);
+ if (!blobSize)
+ return;
+
+ QByteArray blob(totalSize, Qt::Uninitialized);
+ quint32 *p = reinterpret_cast<quint32 *>(blob.data());
+
+ *p++ = BINSHADER_MAGIC;
+ *p++ = BINSHADER_VERSION;
+ *p++ = BINSHADER_QTVERSION;
+
+ *p++ = info.glvendor.size();
+ memcpy(p, info.glvendor.constData(), info.glvendor.size());
+ p = reinterpret_cast<quint32 *>(reinterpret_cast<char *>(p) + info.glvendor.size());
+ *p++ = info.glrenderer.size();
+ memcpy(p, info.glrenderer.constData(), info.glrenderer.size());
+ p = reinterpret_cast<quint32 *>(reinterpret_cast<char *>(p) + info.glrenderer.size());
+ *p++ = info.glversion.size();
+ memcpy(p, info.glversion.constData(), info.glversion.size());
+ p = reinterpret_cast<quint32 *>(reinterpret_cast<char *>(p) + info.glversion.size());
+
+ GLint outSize = 0;
+ quint32 *blobFormat = p++;
+ *p++ = blobSize;
+ funcs->glGetProgramBinary(programId, blobSize, &outSize, blobFormat, p);
+ if (blobSize != outSize) {
+ qCDebug(DBG_SHADER_CACHE, "glGetProgramBinary returned size %d instead of %d", outSize, blobSize);
+ return;
+ }
+
+ QSaveFile f(cacheFileName(cacheKey));
+ if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ f.write(blob);
+ if (!f.commit())
+ qCDebug(DBG_SHADER_CACHE, "Failed to write %s to shader cache", qPrintable(f.fileName()));
+ } else {
+ qCDebug(DBG_SHADER_CACHE, "Failed to create %s in shader cache", qPrintable(f.fileName()));
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglprogrambinarycache_p.h b/src/gui/opengl/qopenglprogrambinarycache_p.h
new file mode 100644
index 0000000000..a0e1f91e25
--- /dev/null
+++ b/src/gui/opengl/qopenglprogrambinarycache_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGLPROGRAMBINARYCACHE_P_H
+#define QOPENGLPROGRAMBINARYCACHE_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 <QtGui/qtguiglobal.h>
+#include <QtGui/qopenglshaderprogram.h>
+#include <QtCore/qcache.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLProgramBinaryCache
+{
+public:
+ struct ShaderDesc {
+ ShaderDesc() { }
+ ShaderDesc(QOpenGLShader::ShaderType type, const QByteArray &source = QByteArray())
+ : type(type), source(source)
+ { }
+ QOpenGLShader::ShaderType type;
+ QByteArray source;
+ };
+ struct ProgramDesc {
+ QVector<ShaderDesc> shaders;
+ };
+
+ QOpenGLProgramBinaryCache();
+
+ bool load(const QByteArray &cacheKey, uint programId);
+ void save(const QByteArray &cacheKey, uint programId);
+
+private:
+ QString cacheFileName(const QByteArray &cacheKey) const;
+ bool verifyHeader(const QByteArray &buf) const;
+ bool setProgramBinary(uint programId, uint blobFormat, const void *p, uint blobSize);
+
+ QString m_cacheDir;
+ bool m_cacheWritable;
+ struct MemCacheEntry {
+ MemCacheEntry(const void *p, int size, uint format)
+ : blob(reinterpret_cast<const char *>(p), size),
+ format(format)
+ { }
+ QByteArray blob;
+ uint format;
+ };
+ QCache<QByteArray, MemCacheEntry> m_memCache;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp
index cd582c5285..d296f327c8 100644
--- a/src/gui/opengl/qopenglshaderprogram.cpp
+++ b/src/gui/opengl/qopenglshaderprogram.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qopenglshaderprogram.h"
+#include "qopenglprogrambinarycache_p.h"
#include "qopenglfunctions.h"
#include "private/qopenglcontext_p.h"
#include <QtCore/private/qobject_p.h>
@@ -46,6 +47,9 @@
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qvector.h>
#include <QtCore/qregularexpression.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qcoreapplication.h>
#include <QtGui/qtransform.h>
#include <QtGui/QColor>
#include <QtGui/QSurfaceFormat>
@@ -127,6 +131,20 @@ QT_BEGIN_NAMESPACE
on the shader program. The shader program's id can be explicitly
created using the create() function.
+ \section2 Caching Program Binaries
+
+ As of Qt 5.9, support for caching program binaries on disk is built in. To
+ enable this, switch to using addCacheableShaderFromSourceCode() and
+ addCacheableShaderFromSourceFile(). With an OpenGL ES 3.x context or support
+ for \c{GL_ARB_get_program_binary}, this will transparently cache program
+ binaries under QStandardPaths::GenericCacheLocation or
+ QStandardPaths::CacheLocation. When support is not available, calling the
+ cacheable function variants is equivalent to the normal ones.
+
+ \note Some drivers do not have any binary formats available, even though
+ they advertise the extension or offer OpenGL ES 3.0. In this case program
+ binary support will be disabled.
+
\sa QOpenGLShader
*/
@@ -162,6 +180,84 @@ QT_BEGIN_NAMESPACE
based on the core feature (requires OpenGL >= 4.3).
*/
+Q_LOGGING_CATEGORY(DBG_SHADER_CACHE, "qt.opengl.diskcache")
+
+// For GLES 3.1/3.2
+#ifndef GL_GEOMETRY_SHADER
+#define GL_GEOMETRY_SHADER 0x8DD9
+#endif
+#ifndef GL_TESS_CONTROL_SHADER
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#endif
+#ifndef GL_TESS_EVALUATION_SHADER
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#endif
+#ifndef GL_COMPUTE_SHADER
+#define GL_COMPUTE_SHADER 0x91B9
+#endif
+#ifndef GL_MAX_GEOMETRY_OUTPUT_VERTICES
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#endif
+#ifndef GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#endif
+#ifndef GL_PATCH_VERTICES
+#define GL_PATCH_VERTICES 0x8E72
+#endif
+#ifndef GL_PATCH_DEFAULT_OUTER_LEVEL
+#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#endif
+#ifndef GL_PATCH_DEFAULT_INNER_LEVEL
+#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#endif
+
+#ifndef GL_NUM_PROGRAM_BINARY_FORMATS
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#endif
+
+static inline bool isFormatGLES(const QSurfaceFormat &f)
+{
+ return (f.renderableType() == QSurfaceFormat::OpenGLES);
+}
+
+static inline bool supportsGeometry(const QSurfaceFormat &f)
+{
+#ifndef QT_OPENGL_ES_2
+ if (!isFormatGLES(f))
+ return (f.version() >= qMakePair<int, int>(3, 2));
+ else
+ return false;
+#else
+ Q_UNUSED(f);
+ return false;
+#endif
+}
+
+static inline bool supportsCompute(const QSurfaceFormat &f)
+{
+#ifndef QT_OPENGL_ES_2
+ if (!isFormatGLES(f))
+ return (f.version() >= qMakePair<int, int>(4, 3));
+ else
+ return (f.version() >= qMakePair<int, int>(3, 1));
+#else
+ return (f.version() >= qMakePair<int, int>(3, 1));
+#endif
+}
+
+static inline bool supportsTessellation(const QSurfaceFormat &f)
+{
+#ifndef QT_OPENGL_ES_2
+ if (!isFormatGLES(f))
+ return (f.version() >= qMakePair<int, int>(4, 0));
+ else
+ return false;
+#else
+ Q_UNUSED(f);
+ return false;
+#endif
+}
+
class QOpenGLShaderPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QOpenGLShader)
@@ -171,22 +267,16 @@ public:
, shaderType(type)
, compiled(false)
, glfuncs(new QOpenGLFunctions(ctx))
-#ifndef QT_OPENGL_ES_2
, supportsGeometryShaders(false)
, supportsTessellationShaders(false)
-#endif
+ , supportsComputeShaders(false)
{
-#ifndef QT_OPENGL_ES_2
- if (!ctx->isOpenGLES()) {
- QSurfaceFormat f = ctx->format();
-
- // Geometry shaders require OpenGL >= 3.2
- if (shaderType & QOpenGLShader::Geometry)
- supportsGeometryShaders = (f.version() >= qMakePair<int, int>(3, 2));
- else if (shaderType & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation))
- supportsTessellationShaders = (f.version() >= qMakePair<int, int>(4, 0));
- }
-#endif
+ if (shaderType & QOpenGLShader::Geometry)
+ supportsGeometryShaders = supportsGeometry(ctx->format());
+ else if (shaderType & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation))
+ supportsTessellationShaders = supportsTessellation(ctx->format());
+ else if (shaderType & QOpenGLShader::Compute)
+ supportsComputeShaders = supportsCompute(ctx->format());
}
~QOpenGLShaderPrivate();
@@ -197,13 +287,13 @@ public:
QOpenGLFunctions *glfuncs;
-#ifndef QT_OPENGL_ES_2
// Support for geometry shaders
bool supportsGeometryShaders;
-
// Support for tessellation shaders
bool supportsTessellationShaders;
-#endif
+ // Support for compute shaders
+ bool supportsComputeShaders;
+
bool create();
bool compile(QOpenGLShader *q);
@@ -229,24 +319,18 @@ bool QOpenGLShaderPrivate::create()
QOpenGLContext *context = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
if (!context)
return false;
- GLuint shader;
+ GLuint shader = 0;
if (shaderType == QOpenGLShader::Vertex) {
shader = glfuncs->glCreateShader(GL_VERTEX_SHADER);
-#if defined(QT_OPENGL_3_2)
} else if (shaderType == QOpenGLShader::Geometry && supportsGeometryShaders) {
shader = glfuncs->glCreateShader(GL_GEOMETRY_SHADER);
-#endif
-#if defined(QT_OPENGL_4)
} else if (shaderType == QOpenGLShader::TessellationControl && supportsTessellationShaders) {
shader = glfuncs->glCreateShader(GL_TESS_CONTROL_SHADER);
} else if (shaderType == QOpenGLShader::TessellationEvaluation && supportsTessellationShaders) {
shader = glfuncs->glCreateShader(GL_TESS_EVALUATION_SHADER);
-#endif
-#if defined(QT_OPENGL_4_3)
- } else if (shaderType == QOpenGLShader::Compute) {
+ } else if (shaderType == QOpenGLShader::Compute && supportsComputeShaders) {
shader = glfuncs->glCreateShader(GL_COMPUTE_SHADER);
-#endif
- } else {
+ } else if (shaderType == QOpenGLShader::Fragment) {
shader = glfuncs->glCreateShader(GL_FRAGMENT_SHADER);
}
if (!shader) {
@@ -710,6 +794,7 @@ public:
#ifndef QT_OPENGL_ES_2
, tessellationFuncs(0)
#endif
+ , linkBinaryRecursion(false)
{
}
~QOpenGLShaderProgramPrivate();
@@ -731,6 +816,13 @@ public:
#endif
bool hasShader(QOpenGLShader::ShaderType type) const;
+
+ QOpenGLProgramBinaryCache::ProgramDesc binaryProgram;
+ bool isCacheDisabled() const;
+ bool compileCacheable();
+ bool linkBinary();
+
+ bool linkBinaryRecursion;
};
namespace {
@@ -962,6 +1054,139 @@ bool QOpenGLShaderProgram::addShaderFromSourceFile
}
/*!
+ Registers the shader of the specified \a type and \a source to this
+ program. Unlike addShaderFromSourceCode(), this function does not perform
+ compilation. Compilation is deferred to link(), and may not happen at all,
+ because link() may potentially use a program binary from Qt's shader disk
+ cache. This will typically lead to a significant increase in performance.
+
+ \return true if the shader has been registered or, in the non-cached case,
+ compiled successfully; false if there was an error. The compilation error
+ messages can be retrieved via log().
+
+ When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for
+ example, or the OpenGL context has no support for context binaries, calling
+ this function is equivalent to addShaderFromSourceCode().
+
+ \since 5.9
+ \sa addShaderFromSourceCode(), addCacheableShaderFromSourceFile()
+ */
+bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source)
+{
+ Q_D(QOpenGLShaderProgram);
+ if (!init())
+ return false;
+ if (d->isCacheDisabled())
+ return addShaderFromSourceCode(type, source);
+
+ return addCacheableShaderFromSourceCode(type, QByteArray(source));
+}
+
+/*!
+ \overload
+
+ Registers the shader of the specified \a type and \a source to this
+ program. Unlike addShaderFromSourceCode(), this function does not perform
+ compilation. Compilation is deferred to link(), and may not happen at all,
+ because link() may potentially use a program binary from Qt's shader disk
+ cache. This will typically lead to a significant increase in performance.
+
+ \return true if the shader has been registered or, in the non-cached case,
+ compiled successfully; false if there was an error. The compilation error
+ messages can be retrieved via log().
+
+ When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for
+ example, or the OpenGL context has no support for context binaries, calling
+ this function is equivalent to addShaderFromSourceCode().
+
+ \since 5.9
+ \sa addShaderFromSourceCode(), addCacheableShaderFromSourceFile()
+ */
+bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const QByteArray &source)
+{
+ Q_D(QOpenGLShaderProgram);
+ if (!init())
+ return false;
+ if (d->isCacheDisabled())
+ return addShaderFromSourceCode(type, source);
+
+ d->binaryProgram.shaders.append(QOpenGLProgramBinaryCache::ShaderDesc(type, source));
+ return true;
+}
+
+/*!
+ \overload
+
+ Registers the shader of the specified \a type and \a source to this
+ program. Unlike addShaderFromSourceCode(), this function does not perform
+ compilation. Compilation is deferred to link(), and may not happen at all,
+ because link() may potentially use a program binary from Qt's shader disk
+ cache. This will typically lead to a significant increase in performance.
+
+ When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for
+ example, or the OpenGL context has no support for context binaries, calling
+ this function is equivalent to addShaderFromSourceCode().
+
+ \since 5.9
+ \sa addShaderFromSourceCode(), addCacheableShaderFromSourceFile()
+ */
+bool QOpenGLShaderProgram::addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const QString &source)
+{
+ Q_D(QOpenGLShaderProgram);
+ if (!init())
+ return false;
+ if (d->isCacheDisabled())
+ return addShaderFromSourceCode(type, source);
+
+ return addCacheableShaderFromSourceCode(type, source.toUtf8().constData());
+}
+
+/*!
+ Registers the shader of the specified \a type and \a fileName to this
+ program. Unlike addShaderFromSourceFile(), this function does not perform
+ compilation. Compilation is deferred to link(), and may not happen at all,
+ because link() may potentially use a program binary from Qt's shader disk
+ cache. This will typically lead to a significant increase in performance.
+
+ \return true if the file has been read successfully, false if the file could
+ not be opened or the normal, non-cached compilation of the shader has
+ failed. The compilation error messages can be retrieved via log().
+
+ When the disk cache is disabled, via Qt::AA_DisableShaderDiskCache for
+ example, or the OpenGL context has no support for context binaries, calling
+ this function is equivalent to addShaderFromSourceFile().
+
+ \since 5.9
+ \sa addShaderFromSourceFile(), addCacheableShaderFromSourceCode()
+ */
+bool QOpenGLShaderProgram::addCacheableShaderFromSourceFile(QOpenGLShader::ShaderType type, const QString &fileName)
+{
+ Q_D(QOpenGLShaderProgram);
+ if (!init())
+ return false;
+ if (d->isCacheDisabled())
+ return addShaderFromSourceFile(type, fileName);
+
+ QOpenGLProgramBinaryCache::ShaderDesc shader(type);
+ // NB! It could be tempting to defer reading the file contents and just
+ // hash the filename as the cache key, perhaps combined with last-modified
+ // timestamp checks. However, this would raise a number of issues (no
+ // timestamps for files in the resource system; preference for global, not
+ // per-application cache items (where filenames may clash); resource-based
+ // shaders from libraries like Qt Quick; etc.), so just avoid it.
+ QFile f(fileName);
+ if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ shader.source = f.readAll();
+ f.close();
+ } else {
+ qWarning("QOpenGLShaderProgram: Unable to open file %s", qPrintable(fileName));
+ return false;
+ }
+ d->binaryProgram.shaders.append(shader);
+ return true;
+}
+
+/*!
Removes \a shader from this shader program. The object is not deleted.
The shader program must be valid in the current QOpenGLContext.
@@ -1019,6 +1244,7 @@ void QOpenGLShaderProgram::removeAllShaders()
qDeleteAll(d->anonShaders);
d->shaders.clear();
d->anonShaders.clear();
+ d->binaryProgram = QOpenGLProgramBinaryCache::ProgramDesc();
d->linked = false; // Program needs to be relinked.
d->removingShaders = false;
}
@@ -1035,6 +1261,16 @@ void QOpenGLShaderProgram::removeAllShaders()
If the shader program was already linked, calling this
function again will force it to be re-linked.
+ When shaders were added to this program via
+ addCacheableShaderFromSourceCode() or addCacheableShaderFromSourceFile(),
+ program binaries are supported, and a cached binary is available on disk,
+ actual compilation and linking are skipped. Instead, link() will initialize
+ the program with the binary blob via glProgramBinary(). If there is no
+ cached version of the program or it was generated with a different driver
+ version, the shaders will be compiled from source and the program will get
+ linked normally. This allows seamless upgrading of the graphics drivers,
+ without having to worry about potentially incompatible binary formats.
+
\sa addShader(), log()
*/
bool QOpenGLShaderProgram::link()
@@ -1044,12 +1280,17 @@ bool QOpenGLShaderProgram::link()
if (!program)
return false;
+ if (!d->linkBinaryRecursion && d->shaders.isEmpty() && !d->binaryProgram.shaders.isEmpty())
+ return d->linkBinary();
+
GLint value;
if (d->shaders.isEmpty()) {
// If there are no explicit shaders, then it is possible that the
- // application added a program binary with glProgramBinaryOES(),
- // or otherwise populated the shaders itself. Check to see if the
- // program is already linked and bail out if so.
+ // application added a program binary with glProgramBinaryOES(), or
+ // otherwise populated the shaders itself. This is also the case when
+ // we are recursively called back from linkBinary() after a successful
+ // glProgramBinary(). Check to see if the program is already linked and
+ // bail out if so.
value = 0;
d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, &value);
d->linked = (value != 0);
@@ -3230,10 +3471,8 @@ void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4
int QOpenGLShaderProgram::maxGeometryOutputVertices() const
{
GLint n = 0;
-#if defined(QT_OPENGL_3_2)
Q_D(const QOpenGLShaderProgram);
d->glfuncs->glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &n);
-#endif
return n;
}
@@ -3257,7 +3496,7 @@ int QOpenGLShaderProgram::maxGeometryOutputVertices() const
*/
void QOpenGLShaderProgram::setPatchVertexCount(int count)
{
-#if defined(QT_OPENGL_4)
+#ifndef QT_OPENGL_ES_2
Q_D(QOpenGLShaderProgram);
if (d->tessellationFuncs)
d->tessellationFuncs->glPatchParameteri(GL_PATCH_VERTICES, count);
@@ -3276,13 +3515,15 @@ void QOpenGLShaderProgram::setPatchVertexCount(int count)
*/
int QOpenGLShaderProgram::patchVertexCount() const
{
+#ifndef QT_OPENGL_ES_2
int patchVertices = 0;
-#if defined(QT_OPENGL_4)
Q_D(const QOpenGLShaderProgram);
if (d->tessellationFuncs)
d->tessellationFuncs->glGetIntegerv(GL_PATCH_VERTICES, &patchVertices);
-#endif
return patchVertices;
+#else
+ return 0;
+#endif
}
/*!
@@ -3304,21 +3545,21 @@ int QOpenGLShaderProgram::patchVertexCount() const
*/
void QOpenGLShaderProgram::setDefaultOuterTessellationLevels(const QVector<float> &levels)
{
-#if defined(QT_OPENGL_4)
- QVector<float> tessLevels = levels;
-
- // Ensure we have the required 4 outer tessellation levels
- // Use default of 1 for missing entries (same as spec)
- const int argCount = 4;
- if (tessLevels.size() < argCount) {
- tessLevels.reserve(argCount);
- for (int i = tessLevels.size(); i < argCount; ++i)
- tessLevels.append(1.0f);
- }
-
+#ifndef QT_OPENGL_ES_2
Q_D(QOpenGLShaderProgram);
- if (d->tessellationFuncs)
+ if (d->tessellationFuncs) {
+ QVector<float> tessLevels = levels;
+
+ // Ensure we have the required 4 outer tessellation levels
+ // Use default of 1 for missing entries (same as spec)
+ const int argCount = 4;
+ if (tessLevels.size() < argCount) {
+ tessLevels.reserve(argCount);
+ for (int i = tessLevels.size(); i < argCount; ++i)
+ tessLevels.append(1.0f);
+ }
d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, tessLevels.data());
+ }
#else
Q_UNUSED(levels);
#endif
@@ -3341,13 +3582,15 @@ void QOpenGLShaderProgram::setDefaultOuterTessellationLevels(const QVector<float
*/
QVector<float> QOpenGLShaderProgram::defaultOuterTessellationLevels() const
{
+#ifndef QT_OPENGL_ES_2
QVector<float> tessLevels(4, 1.0f);
-#if defined(QT_OPENGL_4)
Q_D(const QOpenGLShaderProgram);
if (d->tessellationFuncs)
d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_OUTER_LEVEL, tessLevels.data());
-#endif
return tessLevels;
+#else
+ return QVector<float>();
+#endif
}
/*!
@@ -3369,21 +3612,21 @@ QVector<float> QOpenGLShaderProgram::defaultOuterTessellationLevels() const
*/
void QOpenGLShaderProgram::setDefaultInnerTessellationLevels(const QVector<float> &levels)
{
-#if defined(QT_OPENGL_4)
- QVector<float> tessLevels = levels;
-
- // Ensure we have the required 2 inner tessellation levels
- // Use default of 1 for missing entries (same as spec)
- const int argCount = 2;
- if (tessLevels.size() < argCount) {
- tessLevels.reserve(argCount);
- for (int i = tessLevels.size(); i < argCount; ++i)
- tessLevels.append(1.0f);
- }
-
+#ifndef QT_OPENGL_ES_2
Q_D(QOpenGLShaderProgram);
- if (d->tessellationFuncs)
+ if (d->tessellationFuncs) {
+ QVector<float> tessLevels = levels;
+
+ // Ensure we have the required 2 inner tessellation levels
+ // Use default of 1 for missing entries (same as spec)
+ const int argCount = 2;
+ if (tessLevels.size() < argCount) {
+ tessLevels.reserve(argCount);
+ for (int i = tessLevels.size(); i < argCount; ++i)
+ tessLevels.append(1.0f);
+ }
d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, tessLevels.data());
+ }
#else
Q_UNUSED(levels);
#endif
@@ -3406,13 +3649,15 @@ void QOpenGLShaderProgram::setDefaultInnerTessellationLevels(const QVector<float
*/
QVector<float> QOpenGLShaderProgram::defaultInnerTessellationLevels() const
{
+#ifndef QT_OPENGL_ES_2
QVector<float> tessLevels(2, 1.0f);
-#if defined(QT_OPENGL_4)
Q_D(const QOpenGLShaderProgram);
if (d->tessellationFuncs)
d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_INNER_LEVEL, tessLevels.data());
-#endif
return tessLevels;
+#else
+ return QVector<float>();
+#endif
}
@@ -3425,16 +3670,11 @@ QVector<float> QOpenGLShaderProgram::defaultInnerTessellationLevels() const
*/
bool QOpenGLShaderProgram::hasOpenGLShaderPrograms(QOpenGLContext *context)
{
-#if !defined(QT_OPENGL_ES_2)
if (!context)
context = QOpenGLContext::currentContext();
if (!context)
return false;
return QOpenGLFunctions(context).hasOpenGLFeature(QOpenGLFunctions::Shaders);
-#else
- Q_UNUSED(context);
- return true;
-#endif
}
/*!
@@ -3465,37 +3705,148 @@ bool QOpenGLShader::hasOpenGLShaders(ShaderType type, QOpenGLContext *context)
if ((type & ~(Geometry | Vertex | Fragment | TessellationControl | TessellationEvaluation | Compute)) || type == 0)
return false;
- QSurfaceFormat format = context->format();
- if (type == Geometry) {
-#ifndef QT_OPENGL_ES_2
- // Geometry shaders require OpenGL 3.2 or newer
- QSurfaceFormat format = context->format();
- return (!context->isOpenGLES())
- && (format.version() >= qMakePair<int, int>(3, 2));
-#else
- // No geometry shader support in OpenGL ES2
- return false;
-#endif
- } else if (type == TessellationControl || type == TessellationEvaluation) {
-#if !defined(QT_OPENGL_ES_2)
- return (!context->isOpenGLES())
- && (format.version() >= qMakePair<int, int>(4, 0));
-#else
- // No tessellation shader support in OpenGL ES2
- return false;
-#endif
- } else if (type == Compute) {
-#if defined(QT_OPENGL_4_3)
- return (format.version() >= qMakePair<int, int>(4, 3));
-#else
- // No compute shader support without OpenGL 4.3 or newer
- return false;
-#endif
- }
+ if (type & QOpenGLShader::Geometry)
+ return supportsGeometry(context->format());
+ else if (type & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation))
+ return supportsTessellation(context->format());
+ else if (type & QOpenGLShader::Compute)
+ return supportsCompute(context->format());
// Unconditional support of vertex and fragment shaders implicitly assumes
// a minimum OpenGL version of 2.0
return true;
}
+// While unlikely, one application can in theory use contexts with different versions
+// or profiles. Therefore any version- or extension-specific checks must be done on a
+// per-context basis, not just once per process. QOpenGLSharedResource enables this,
+// although it's once-per-sharing-context-group, not per-context. Still, this should
+// be good enough in practice.
+class QOpenGLProgramBinarySupportCheck : public QOpenGLSharedResource
+{
+public:
+ QOpenGLProgramBinarySupportCheck(QOpenGLContext *context);
+ void invalidateResource() override { }
+ void freeResource(QOpenGLContext *) override { }
+
+ bool isSupported() const { return m_supported; }
+
+private:
+ bool m_supported;
+};
+
+QOpenGLProgramBinarySupportCheck::QOpenGLProgramBinarySupportCheck(QOpenGLContext *context)
+ : QOpenGLSharedResource(context->shareGroup()),
+ m_supported(false)
+{
+ if (QCoreApplication::testAttribute(Qt::AA_DisableShaderDiskCache)) {
+ qCDebug(DBG_SHADER_CACHE, "Shader cache disabled via app attribute");
+ return;
+ }
+ if (qEnvironmentVariableIntValue("QT_DISABLE_SHADER_DISK_CACHE")) {
+ qCDebug(DBG_SHADER_CACHE, "Shader cache disabled via env var");
+ return;
+ }
+
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (ctx) {
+ if (ctx->isOpenGLES()) {
+ qCDebug(DBG_SHADER_CACHE, "OpenGL ES v%d context", ctx->format().majorVersion());
+ if (ctx->format().majorVersion() >= 3)
+ m_supported = true;
+ } else {
+ const bool hasExt = ctx->hasExtension("GL_ARB_get_program_binary");
+ qCDebug(DBG_SHADER_CACHE, "GL_ARB_get_program_binary support = %d", hasExt);
+ if (hasExt)
+ m_supported = true;
+ }
+ if (m_supported) {
+ GLint fmtCount = 0;
+ ctx->functions()->glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &fmtCount);
+ qCDebug(DBG_SHADER_CACHE, "Supported binary format count = %d", fmtCount);
+ m_supported = fmtCount > 0;
+ }
+ }
+ qCDebug(DBG_SHADER_CACHE, "Shader cache supported = %d", m_supported);
+}
+
+class QOpenGLProgramBinarySupportCheckWrapper
+{
+public:
+ QOpenGLProgramBinarySupportCheck *get(QOpenGLContext *context)
+ {
+ return m_resource.value<QOpenGLProgramBinarySupportCheck>(context);
+ }
+
+private:
+ QOpenGLMultiGroupSharedResource m_resource;
+};
+
+bool QOpenGLShaderProgramPrivate::isCacheDisabled() const
+{
+ static QOpenGLProgramBinarySupportCheckWrapper binSupportCheck;
+ return !binSupportCheck.get(QOpenGLContext::currentContext())->isSupported();
+}
+
+bool QOpenGLShaderProgramPrivate::compileCacheable()
+{
+ Q_Q(QOpenGLShaderProgram);
+ for (const QOpenGLProgramBinaryCache::ShaderDesc &shader : qAsConst(binaryProgram.shaders)) {
+ QScopedPointer<QOpenGLShader> s(new QOpenGLShader(shader.type, q));
+ if (!s->compileSourceCode(shader.source)) {
+ log = s->log();
+ return false;
+ }
+ anonShaders.append(s.take());
+ if (!q->addShader(anonShaders.last()))
+ return false;
+ }
+ return true;
+}
+
+bool QOpenGLShaderProgramPrivate::linkBinary()
+{
+ static QOpenGLProgramBinaryCache binCache;
+
+ Q_Q(QOpenGLShaderProgram);
+
+ QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
+ for (const QOpenGLProgramBinaryCache::ShaderDesc &shader : qAsConst(binaryProgram.shaders))
+ keyBuilder.addData(shader.source);
+
+ const QByteArray cacheKey = keyBuilder.result().toHex();
+ if (DBG_SHADER_CACHE().isEnabled(QtDebugMsg))
+ qCDebug(DBG_SHADER_CACHE, "program with %d shaders, cache key %s",
+ binaryProgram.shaders.count(), cacheKey.constData());
+
+ bool needsCompile = true;
+ if (binCache.load(cacheKey, q->programId())) {
+ qCDebug(DBG_SHADER_CACHE, "Program binary received from cache");
+ linkBinaryRecursion = true;
+ bool ok = q->link();
+ linkBinaryRecursion = false;
+ if (ok)
+ needsCompile = false;
+ else
+ qCDebug(DBG_SHADER_CACHE, "Link failed after glProgramBinary");
+ }
+
+ bool needsSave = false;
+ if (needsCompile) {
+ qCDebug(DBG_SHADER_CACHE, "Program binary not in cache, compiling");
+ if (compileCacheable())
+ needsSave = true;
+ else
+ return false;
+ }
+
+ linkBinaryRecursion = true;
+ bool ok = q->link();
+ linkBinaryRecursion = false;
+ if (ok && needsSave)
+ binCache.save(cacheKey, q->programId());
+
+ return ok;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglshaderprogram.h b/src/gui/opengl/qopenglshaderprogram.h
index 2da359c535..fd4d82ecf9 100644
--- a/src/gui/opengl/qopenglshaderprogram.h
+++ b/src/gui/opengl/qopenglshaderprogram.h
@@ -50,6 +50,13 @@
#include <QtGui/qvector4d.h>
#include <QtGui/qmatrix4x4.h>
+#if defined(Q_CLANG_QDOC)
+#undef GLint
+typedef int GLint;
+#undef GLfloat
+typedef double GLfloat;
+#endif
+
QT_BEGIN_NAMESPACE
@@ -119,6 +126,11 @@ public:
bool addShaderFromSourceCode(QOpenGLShader::ShaderType type, const QString& source);
bool addShaderFromSourceFile(QOpenGLShader::ShaderType type, const QString& fileName);
+ bool addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source);
+ bool addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const QByteArray &source);
+ bool addCacheableShaderFromSourceCode(QOpenGLShader::ShaderType type, const QString &source);
+ bool addCacheableShaderFromSourceFile(QOpenGLShader::ShaderType type, const QString &fileName);
+
void removeAllShaders();
virtual bool link();
diff --git a/src/gui/opengl/qopengltextureblitter.cpp b/src/gui/opengl/qopengltextureblitter.cpp
index 858fc0d857..b65df9dc82 100644
--- a/src/gui/opengl/qopengltextureblitter.cpp
+++ b/src/gui/opengl/qopengltextureblitter.cpp
@@ -330,8 +330,8 @@ bool QOpenGLTextureBlitterPrivate::buildProgram(ProgramIndex idx, const char *vs
p->glProgram.reset(new QOpenGLShaderProgram);
- p->glProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, vs);
- p->glProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, fs);
+ p->glProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vs);
+ p->glProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fs);
p->glProgram->link();
if (!p->glProgram->isLinked()) {
qWarning() << "Could not link shader program:\n" << p->glProgram->log();
diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp
index 9a7b1eb21d..afd5004cec 100644
--- a/src/gui/opengl/qopengltextureglyphcache.cpp
+++ b/src/gui/opengl/qopengltextureglyphcache.cpp
@@ -342,22 +342,14 @@ void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height)
QString source;
source.append(QLatin1String(isCoreProfile ? qopenglslMainWithTexCoordsVertexShader_core : qopenglslMainWithTexCoordsVertexShader));
source.append(QLatin1String(isCoreProfile ? qopenglslUntransformedPositionVertexShader_core : qopenglslUntransformedPositionVertexShader));
-
- QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_blitProgram);
- vertexShader->compileSourceCode(source);
-
- m_blitProgram->addShader(vertexShader);
+ m_blitProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, source);
}
{
QString source;
source.append(QLatin1String(isCoreProfile ? qopenglslMainFragmentShader_core : qopenglslMainFragmentShader));
source.append(QLatin1String(isCoreProfile ? qopenglslImageSrcFragmentShader_core : qopenglslImageSrcFragmentShader));
-
- QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_blitProgram);
- fragmentShader->compileSourceCode(source);
-
- m_blitProgram->addShader(fragmentShader);
+ m_blitProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, source);
}
m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 86e35c39f8..63e345545c 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -8,6 +8,7 @@ HEADERS += \
painting/qbrush.h \
painting/qcolor.h \
painting/qcolor_p.h \
+ painting/qcolorprofile_p.h \
painting/qcosmeticstroker_p.h \
painting/qdatabuffer_p.h \
painting/qdrawhelper_p.h \
@@ -63,11 +64,11 @@ SOURCES += \
painting/qblittable.cpp \
painting/qbrush.cpp \
painting/qcolor.cpp \
+ painting/qcolorprofile.cpp \
painting/qcompositionfunctions.cpp \
painting/qcosmeticstroker.cpp \
painting/qdrawhelper.cpp \
painting/qemulationpaintengine.cpp \
- painting/qgammatables.cpp \
painting/qgrayraster.c \
painting/qimagescale.cpp \
painting/qmatrix.cpp \
diff --git a/src/gui/painting/qcolorprofile.cpp b/src/gui/painting/qcolorprofile.cpp
new file mode 100644
index 0000000000..3b7b0a248b
--- /dev/null
+++ b/src/gui/painting/qcolorprofile.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcolorprofile_p.h"
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+QColorProfile *QColorProfile::fromGamma(qreal gamma)
+{
+ QColorProfile *cp = new QColorProfile;
+
+ for (int i = 0; i <= (255 * 16); ++i) {
+ cp->m_toLinear[i] = ushort(qRound(qPow(i / qreal(255 * 16), gamma) * (255 * 256)));
+ cp->m_fromLinear[i] = ushort(qRound(qPow(i / qreal(255 * 16), qreal(1) / gamma) * (255 * 256)));
+ }
+
+ return cp;
+}
+
+static qreal srgbToLinear(qreal v)
+{
+ const qreal a = 0.055;
+ if (v <= qreal(0.04045))
+ return v / qreal(12.92);
+ else
+ return qPow((v + a) / (qreal(1) + a), qreal(2.4));
+}
+
+static qreal linearToSrgb(qreal v)
+{
+ const qreal a = 0.055;
+ if (v <= qreal(0.0031308))
+ return v * qreal(12.92);
+ else
+ return (qreal(1) + a) * qPow(v, qreal(1.0 / 2.4)) - a;
+}
+
+QColorProfile *QColorProfile::fromSRgb()
+{
+ QColorProfile *cp = new QColorProfile;
+
+ for (int i = 0; i <= (255 * 16); ++i) {
+ cp->m_toLinear[i] = ushort(qRound(srgbToLinear(i / qreal(255 * 16)) * (255 * 256)));
+ cp->m_fromLinear[i] = ushort(qRound(linearToSrgb(i / qreal(255 * 16)) * (255 * 256)));
+ }
+
+ return cp;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qcolorprofile_p.h b/src/gui/painting/qcolorprofile_p.h
new file mode 100644
index 0000000000..ca1786ee6d
--- /dev/null
+++ b/src/gui/painting/qcolorprofile_p.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOLORPROFILE_P_H
+#define QCOLORPROFILE_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 <QtGui/private/qtguiglobal_p.h>
+#include <QtGui/qrgb.h>
+#include <QtGui/qrgba64.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QColorProfile
+{
+public:
+ static QColorProfile *fromGamma(qreal gamma);
+ static QColorProfile *fromSRgb();
+
+ // The following methods all convert opaque or unpremultiplied colors:
+
+ QRgba64 toLinear64(QRgb rgb32) const
+ {
+ ushort r = m_toLinear[qRed(rgb32) << 4];
+ ushort g = m_toLinear[qGreen(rgb32) << 4];
+ ushort b = m_toLinear[qBlue(rgb32) << 4];
+ r = r + (r >> 8);
+ g = g + (g >> 8);
+ b = b + (b >> 8);
+ return QRgba64::fromRgba64(r, g, b, qAlpha(rgb32) * 257);
+ }
+
+ QRgb toLinear(QRgb rgb32) const
+ {
+ uchar r = (m_toLinear[qRed(rgb32) << 4] + 0x80) >> 8;
+ uchar g = (m_toLinear[qGreen(rgb32) << 4] + 0x80) >> 8;
+ uchar b = (m_toLinear[qBlue(rgb32) << 4] + 0x80) >> 8;
+ return qRgba(r, g, b, qAlpha(rgb32));
+ }
+
+ QRgba64 toLinear(QRgba64 rgb64) const
+ {
+ ushort r = rgb64.red();
+ ushort g = rgb64.green();
+ ushort b = rgb64.blue();
+ r = r - (r >> 8);
+ g = g - (g >> 8);
+ b = b - (b >> 8);
+ r = m_toLinear[r >> 4];
+ g = m_toLinear[g >> 4];
+ b = m_toLinear[b >> 4];
+ r = r + (r >> 8);
+ g = g + (g >> 8);
+ b = b + (b >> 8);
+ return QRgba64::fromRgba64(r, g, b, rgb64.alpha());
+ }
+
+ QRgb fromLinear64(QRgba64 rgb64) const
+ {
+ ushort r = rgb64.red();
+ ushort g = rgb64.green();
+ ushort b = rgb64.blue();
+ r = r - (r >> 8);
+ g = g - (g >> 8);
+ b = b - (b >> 8);
+ r = (m_fromLinear[r >> 4] + 0x80) >> 8;
+ g = (m_fromLinear[g >> 4] + 0x80) >> 8;
+ b = (m_fromLinear[b >> 4] + 0x80) >> 8;
+ return qRgba(r, g, b, rgb64.alpha8());
+ }
+
+ QRgb fromLinear(QRgb rgb32) const
+ {
+ uchar r = (m_fromLinear[qRed(rgb32) << 4] + 0x80) >> 8;
+ uchar g = (m_fromLinear[qGreen(rgb32) << 4] + 0x80) >> 8;
+ uchar b = (m_fromLinear[qBlue(rgb32) << 4] + 0x80) >> 8;
+ return qRgba(r, g, b, qAlpha(rgb32));
+ }
+
+ QRgba64 fromLinear(QRgba64 rgb64) const
+ {
+ ushort r = rgb64.red();
+ ushort g = rgb64.green();
+ ushort b = rgb64.blue();
+ r = r - (r >> 8);
+ g = g - (g >> 8);
+ b = b - (b >> 8);
+ r = m_fromLinear[r >> 4];
+ g = m_fromLinear[g >> 4];
+ b = m_fromLinear[b >> 4];
+ r = r + (r >> 8);
+ g = g + (g >> 8);
+ b = b + (b >> 8);
+ return QRgba64::fromRgba64(r, g, b, rgb64.alpha());
+ }
+
+private:
+ QColorProfile() { }
+
+ // We translate to 0-65280 (255*256) instead to 0-65535 to make simple
+ // shifting an accurate conversion.
+ // We translate from 0-4080 (255*16) for the same speed up, and to keep
+ // the tables small enough to fit in most inner caches.
+ ushort m_toLinear[(255 * 16) + 1]; // [0-4080] -> [0-65280]
+ ushort m_fromLinear[(255 * 16) + 1]; // [0-4080] -> [0-65280]
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QCOLORPROFILE_P_H
diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm
index 466b18d59b..bf0be7f3d3 100644
--- a/src/gui/painting/qcoregraphics.mm
+++ b/src/gui/painting/qcoregraphics.mm
@@ -39,6 +39,7 @@
#include <QtGui/private/qpaintengine_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qcoreapplication.h>
+#include <QtCore/qoperatingsystemversion.h>
QT_BEGIN_NAMESPACE
@@ -119,7 +120,7 @@ QT_END_NAMESPACE
+ (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState
{
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_NA)
- if (QT_PREPEND_NAMESPACE(QSysInfo::MacintoshVersion) >= QT_PREPEND_NAMESPACE(QSysInfo::MV_10_10))
+ if (QT_PREPEND_NAMESPACE(QOperatingSystemVersion::current()) >= QT_PREPEND_NAMESPACE(QOperatingSystemVersion::OSXYosemite))
return [self graphicsContextWithCGContext:graphicsPort flipped:initialFlippedState];
#endif
return [self graphicsContextWithGraphicsPort:graphicsPort flipped:initialFlippedState];
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index ff7c8dfc28..08f96bd654 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -43,6 +43,7 @@
#include <qstylehints.h>
#include <qguiapplication.h>
#include <qatomic.h>
+#include <private/qcolorprofile_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qpainter_p.h>
@@ -1319,7 +1320,7 @@ static void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, con
static void QT_FASTCALL convertFromRgb64(uint *dest, const QRgba64 *src, int length)
{
for (int i = 0; i < length; ++i) {
- dest[i] = src[i].toArgb32();
+ dest[i] = toArgb32(src[i]);
}
}
@@ -1410,7 +1411,7 @@ static void QT_FASTCALL destStore64ARGB32(QRasterBuffer *rasterBuffer, int x, in
{
uint *dest = (uint*)rasterBuffer->scanLine(y) + x;
for (int i = 0; i < length; ++i) {
- dest[i] = buffer[i].unpremultiplied().toArgb32();
+ dest[i] = toArgb32(buffer[i].unpremultiplied());
}
}
@@ -1418,7 +1419,7 @@ static void QT_FASTCALL destStore64RGBA8888(QRasterBuffer *rasterBuffer, int x,
{
uint *dest = (uint*)rasterBuffer->scanLine(y) + x;
for (int i = 0; i < length; ++i) {
- dest[i] = ARGB2RGBA(buffer[i].unpremultiplied().toArgb32());
+ dest[i] = toRgba8888(buffer[i].unpremultiplied());
}
}
@@ -5194,6 +5195,8 @@ void qBlendTexture(int count, const QSpan *spans, void *userData)
case QImage::Format_RGB16:
proc = processTextureSpansRGB16[blendType];
break;
+ case QImage::Format_ARGB32:
+ case QImage::Format_RGBA8888:
case QImage::Format_BGR30:
case QImage::Format_A2BGR30_Premultiplied:
case QImage::Format_RGB30:
@@ -5435,80 +5438,27 @@ static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
}
}
-static inline void rgbBlendPixel(quint32 *dst, int coverage, int sr, int sg, int sb, const uchar *gamma, const uchar *invgamma)
+static inline void rgbBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, const QColorProfile *colorProfile)
{
- // Do a gray alphablend...
- int da = qAlpha(*dst);
- int dr = qRed(*dst);
- int dg = qGreen(*dst);
- int db = qBlue(*dst);
+ // Do a gammacorrected RGB alphablend...
+ const QRgba64 dlinear = colorProfile->toLinear64(*dst);
- if (da != 255
- ) {
+ QRgba64 blend = rgbBlend(dlinear, slinear, coverage);
- int a = qGray(coverage);
- sr = qt_div_255(invgamma[sr] * a);
- sg = qt_div_255(invgamma[sg] * a);
- sb = qt_div_255(invgamma[sb] * a);
-
- int ia = 255 - a;
- dr = qt_div_255(dr * ia);
- dg = qt_div_255(dg * ia);
- db = qt_div_255(db * ia);
-
- *dst = ((a + qt_div_255((255 - a) * da)) << 24)
- | ((sr + dr) << 16)
- | ((sg + dg) << 8)
- | ((sb + db));
- return;
- }
-
- int mr = qRed(coverage);
- int mg = qGreen(coverage);
- int mb = qBlue(coverage);
-
- dr = gamma[dr];
- dg = gamma[dg];
- db = gamma[db];
-
- int nr = qt_div_255(sr * mr + dr * (255 - mr));
- int ng = qt_div_255(sg * mg + dg * (255 - mg));
- int nb = qt_div_255(sb * mb + db * (255 - mb));
-
- nr = invgamma[nr];
- ng = invgamma[ng];
- nb = invgamma[nb];
-
- *dst = qRgb(nr, ng, nb);
+ *dst = colorProfile->fromLinear64(blend);
}
-#if defined(Q_OS_WIN)
Q_GUI_EXPORT bool qt_needs_a8_gamma_correction = false;
-static inline void grayBlendPixel(quint32 *dst, int coverage, int sr, int sg, int sb, const uint *gamma, const uchar *invgamma)
+static inline void grayBlendPixel(quint32 *dst, int coverage, QRgba64 slinear, const QColorProfile *colorProfile)
{
// Do a gammacorrected gray alphablend...
- int dr = qRed(*dst);
- int dg = qGreen(*dst);
- int db = qBlue(*dst);
-
- dr = gamma[dr];
- dg = gamma[dg];
- db = gamma[db];
+ const QRgba64 dlinear = colorProfile->toLinear64(*dst);
- int alpha = coverage;
- int ialpha = 255 - alpha;
- int nr = qt_div_255(sr * alpha + dr * ialpha);
- int ng = qt_div_255(sg * alpha + dg * ialpha);
- int nb = qt_div_255(sb * alpha + db * ialpha);
+ QRgba64 blend = interpolate255(slinear, coverage, dlinear, 255 - coverage);
- nr = invgamma[nr];
- ng = invgamma[ng];
- nb = invgamma[nb];
-
- *dst = qRgb(nr, ng, nb);
+ *dst = colorProfile->fromLinear64(blend);
}
-#endif
static void qt_alphamapblit_uint32(QRasterBuffer *rasterBuffer,
int x, int y, quint32 color,
@@ -5519,21 +5469,14 @@ static void qt_alphamapblit_uint32(QRasterBuffer *rasterBuffer,
const quint32 c = color;
const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32);
-#if defined(Q_OS_WIN)
- const QDrawHelperGammaTables *tables = QGuiApplicationPrivate::instance()->gammaTables();
- if (!tables)
+ const QColorProfile *colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text();
+ if (!colorProfile)
return;
- const uint *gamma = tables->qt_pow_gamma;
- const uchar *invgamma = tables->qt_pow_invgamma;
-
- int sr = gamma[qRed(color)];
- int sg = gamma[qGreen(color)];
- int sb = gamma[qBlue(color)];
+ const QRgba64 slinear = colorProfile->toLinear64(c);
bool opaque_src = (qAlpha(color) == 255);
bool doGrayBlendPixel = opaque_src && qt_needs_a8_gamma_correction;
-#endif
if (!clip) {
quint32 *dest = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x;
@@ -5546,13 +5489,9 @@ static void qt_alphamapblit_uint32(QRasterBuffer *rasterBuffer,
} else if (coverage == 255) {
dest[i] = c;
} else {
-#if defined(Q_OS_WIN)
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && doGrayBlendPixel
- && qAlpha(dest[i]) == 255) {
- grayBlendPixel(dest+i, coverage, sr, sg, sb, gamma, invgamma);
- } else
-#endif
- {
+ if (doGrayBlendPixel && qAlpha(dest[i]) == 255) {
+ grayBlendPixel(dest+i, coverage, slinear, colorProfile);
+ } else {
int ialpha = 255 - coverage;
dest[i] = INTERPOLATE_PIXEL_255(c, coverage, dest[i], ialpha);
}
@@ -5587,13 +5526,9 @@ static void qt_alphamapblit_uint32(QRasterBuffer *rasterBuffer,
} else if (coverage == 255) {
dest[xp] = c;
} else {
-#if defined(Q_OS_WIN)
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && doGrayBlendPixel
- && qAlpha(dest[xp]) == 255) {
- grayBlendPixel(dest+xp, coverage, sr, sg, sb, gamma, invgamma);
- } else
-#endif
- {
+ if (doGrayBlendPixel && qAlpha(dest[xp]) == 255) {
+ grayBlendPixel(dest+xp, coverage, slinear, colorProfile);
+ } else {
int ialpha = 255 - coverage;
dest[xp] = INTERPOLATE_PIXEL_255(c, coverage, dest[xp], ialpha);
}
@@ -5627,6 +5562,11 @@ static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer,
}
#endif
+inline static int qRgbAvg(QRgb rgb)
+{
+ return (qRed(rgb) * 5 + qGreen(rgb) * 6 + qBlue(rgb) * 5) / 16;
+}
+
static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
int x, int y, const QRgba64 &color,
const uint *src, int mapWidth, int mapHeight, int srcStride,
@@ -5634,21 +5574,13 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
{
const quint32 c = color.toArgb32();
- int sr = qRed(c);
- int sg = qGreen(c);
- int sb = qBlue(c);
int sa = qAlpha(c);
- const QDrawHelperGammaTables *tables = QGuiApplicationPrivate::instance()->gammaTables();
- if (!tables)
+ const QColorProfile *colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text();
+ if (!colorProfile)
return;
- const uchar *gamma = tables->qt_pow_rgb_gamma;
- const uchar *invgamma = tables->qt_pow_rgb_invgamma;
-
- sr = gamma[sr];
- sg = gamma[sg];
- sb = gamma[sb];
+ const QRgba64 slinear = colorProfile->toLinear64(c);
if (sa == 0)
return;
@@ -5662,7 +5594,13 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
if (coverage == 0xffffffff) {
dst[i] = c;
} else if (coverage != 0xff000000) {
- rgbBlendPixel(dst+i, coverage, sr, sg, sb, gamma, invgamma);
+ if (dst[i] >= 0xff000000) {
+ rgbBlendPixel(dst+i, coverage, slinear, colorProfile);
+ } else {
+ // Give up and do a naive blend.
+ const int a = qRgbAvg(coverage);
+ dst[i] = INTERPOLATE_PIXEL_255(c, a, dst[i], 255 - a);
+ }
}
}
@@ -5692,7 +5630,13 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
if (coverage == 0xffffffff) {
dst[xp] = c;
} else if (coverage != 0xff000000) {
- rgbBlendPixel(dst+xp, coverage, sr, sg, sb, gamma, invgamma);
+ if (dst[xp] >= 0xff000000) {
+ rgbBlendPixel(dst+xp, coverage, slinear, colorProfile);
+ } else {
+ // Give up and do a naive blend.
+ const int a = qRgbAvg(coverage);
+ dst[xp] = INTERPOLATE_PIXEL_255(c, a, dst[xp], 255 - coverage);
+ }
}
}
} // for (i -> line.count)
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index e537c343bb..933da56095 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -157,7 +157,6 @@ struct DrawHelper {
extern SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats];
extern SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats];
extern SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats];
-extern MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3];
extern DrawHelper qDrawHelper[QImage::NImageFormats];
@@ -345,18 +344,6 @@ struct QSpanData
void adjustSpanMethods();
};
-struct QDrawHelperGammaTables
-{
- explicit QDrawHelperGammaTables(qreal smoothing);
-
- void refresh(qreal smoothing);
-
- uchar qt_pow_rgb_gamma[256];
- uchar qt_pow_rgb_invgamma[256];
- uint qt_pow_gamma[256];
- uchar qt_pow_invgamma[2048];
-};
-
static inline uint qt_gradient_clamp(const QGradientData *data, int ipos)
{
if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) {
@@ -1238,6 +1225,7 @@ extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
extern const FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount];
extern StorePixelsFunc qStorePixels[QPixelLayout::BPPCount];
+extern MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3];
QT_END_NAMESPACE
diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp
index 3fbae76de5..25aa6a3122 100644
--- a/src/gui/painting/qmemrotate.cpp
+++ b/src/gui/painting/qmemrotate.cpp
@@ -41,164 +41,10 @@
QT_BEGIN_NAMESPACE
-#if QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
static const int tileSize = 32;
-#endif
-
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
-#if QT_ROTATION_ALGORITHM == QT_ROTATION_PACKED || QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
-#error Big endian version not implemented for the transformed driver!
-#endif
-#endif
-
-template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
-inline void qt_memrotate90_cachedRead(const T *src, int w, int h, int sstride, T *dest,
- int dstride)
-{
- const char *s = reinterpret_cast<const char*>(src);
- char *d = reinterpret_cast<char*>(dest);
- for (int y = 0; y < h; ++y) {
- for (int x = w - 1; x >= 0; --x) {
- T *destline = reinterpret_cast<T *>(d + (w - x - 1) * dstride);
- destline[y] = src[x];
- }
- s += sstride;
- src = reinterpret_cast<const T*>(s);
- }
-}
template <class T>
Q_STATIC_TEMPLATE_FUNCTION
-inline void qt_memrotate270_cachedRead(const T *src, int w, int h, int sstride, T *dest,
- int dstride)
-{
- const char *s = reinterpret_cast<const char*>(src);
- char *d = reinterpret_cast<char*>(dest);
- s += (h - 1) * sstride;
- for (int y = h - 1; y >= 0; --y) {
- src = reinterpret_cast<const T*>(s);
- for (int x = 0; x < w; ++x) {
- T *destline = reinterpret_cast<T *>(d + x * dstride);
- destline[h - y - 1] = src[x];
- }
- s -= sstride;
- }
-}
-
-#if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
-
-template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
-inline void qt_memrotate90_cachedWrite(const T *src, int w, int h, int sstride, T *dest,
- int dstride)
-{
- for (int x = w - 1; x >= 0; --x) {
- T *d = dest + (w - x - 1) * dstride;
- for (int y = 0; y < h; ++y) {
- *d++ = src[y * sstride + x];
- }
- }
-
-}
-
-template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
-inline void qt_memrotate270_cachedWrite(const T *src, int w, int h, int sstride, T *dest,
- int dstride)
-{
- for (int x = 0; x < w; ++x) {
- T *d = dest + x * dstride;
- for (int y = h - 1; y >= 0; --y) {
- *d++ = src[y * sstride + x];
- }
- }
-}
-
-#endif // QT_ROTATION_CACHEDWRITE
-
-#if QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
-
-// TODO: packing algorithms should probably be modified on 64-bit architectures
-
-template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
-inline void qt_memrotate90_packing(const T *src, int w, int h, int sstride, T *dest, int dstride)
-{
- sstride /= sizeof(T);
- dstride /= sizeof(T);
-
- const int pack = sizeof(quint32) / sizeof(T);
- const int unaligned = int((long(dest) & (sizeof(quint32)-1))) / sizeof(T);
-
- for (int x = w - 1; x >= 0; --x) {
- int y = 0;
-
- for (int i = 0; i < unaligned; ++i) {
- dest[(w - x - 1) * dstride + y] = src[y * sstride + x];
- ++y;
- }
-
- quint32 *d = reinterpret_cast<quint32*>(dest + (w - x - 1) * dstride
- + unaligned);
- const int rest = (h - unaligned) % pack;
- while (y < h - rest) {
- quint32 c = src[y * sstride + x];
- for (int i = 1; i < pack; ++i) {
- c |= src[(y + i) * sstride + x] << (sizeof(int) * 8 / pack * i);
- }
- *d++ = c;
- y += pack;
- }
-
- while (y < h) {
- dest[(w - x - 1) * dstride + y] = src[y * sstride + x];
- ++y;
- }
- }
-}
-
-template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
-inline void qt_memrotate270_packing(const T *src, int w, int h, int sstride, T *dest, int dstride)
-{
- sstride /= sizeof(T);
- dstride /= sizeof(T);
-
- const int pack = sizeof(quint32) / sizeof(T);
- const int unaligned = int((long(dest) & (sizeof(quint32)-1))) / sizeof(T);
-
- for (int x = 0; x < w; ++x) {
- int y = h - 1;
-
- for (int i = 0; i < unaligned; ++i) {
- dest[x * dstride + h - y - 1] = src[y * sstride + x];
- --y;
- }
-
- quint32 *d = reinterpret_cast<quint32*>(dest + x * dstride
- + unaligned);
- const int rest = (h - unaligned) % pack;
- while (y > rest) {
- quint32 c = src[y * sstride + x];
- for (int i = 1; i < pack; ++i) {
- c |= src[(y - i) * sstride + x] << (sizeof(int) * 8 / pack * i);
- }
- *d++ = c;
- y -= pack;
- }
- while (y >= 0) {
- dest[x * dstride + h - y - 1] = src[y * sstride + x];
- --y;
- }
- }
-}
-
-#endif // QT_ROTATION_PACKING
-
-#if QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
-template <class T>
-Q_STATIC_TEMPLATE_FUNCTION
inline void qt_memrotate90_tiled(const T *src, int w, int h, int sstride, T *dest, int dstride)
{
sstride /= sizeof(T);
@@ -235,7 +81,7 @@ inline void qt_memrotate90_tiled(const T *src, int w, int h, int sstride, T *des
for (int y = starty; y < stopy; y += pack) {
quint32 c = src[y * sstride + x];
for (int i = 1; i < pack; ++i) {
- const int shift = (sizeof(int) * 8 / pack * i);
+ const int shift = (sizeof(T) * 8 * i);
const T color = src[(y + i) * sstride + x];
c |= color << shift;
}
@@ -293,7 +139,7 @@ inline void qt_memrotate270_tiled(const T *src, int w, int h, int sstride, T *de
const int pack = sizeof(quint32) / sizeof(T);
const int unaligned =
- qMin(uint((long(dest) & (sizeof(quint32)-1)) / sizeof(T)), uint(h));
+ qMin(uint((quintptr(dest) & (sizeof(quint32)-1)) / sizeof(T)), uint(h));
const int restX = w % tileSize;
const int restY = (h - unaligned) % tileSize;
const int unoptimizedY = restY % pack;
@@ -320,10 +166,10 @@ inline void qt_memrotate270_tiled(const T *src, int w, int h, int sstride, T *de
for (int x = startx; x < stopx; ++x) {
quint32 *d = reinterpret_cast<quint32*>(dest + x * dstride
+ h - 1 - starty);
- for (int y = starty; y > stopy; y -= pack) {
+ for (int y = starty; y >= stopy; y -= pack) {
quint32 c = src[y * sstride + x];
for (int i = 1; i < pack; ++i) {
- const int shift = (sizeof(int) * 8 / pack * i);
+ const int shift = (sizeof(T) * 8 * i);
const T color = src[(y - i) * sstride + x];
c |= color << shift;
}
@@ -371,22 +217,26 @@ inline void qt_memrotate270_tiled_unpacked(const T *src, int w, int h, int sstri
}
}
-#endif // QT_ROTATION_ALGORITHM
template <class T>
Q_STATIC_TEMPLATE_FUNCTION
inline void qt_memrotate90_template(const T *src, int srcWidth, int srcHeight, int srcStride,
T *dest, int dstStride)
{
-#if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD
- qt_memrotate90_cachedRead<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
-#elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
- qt_memrotate90_cachedWrite<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
-#elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
- qt_memrotate90_packing<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
-#elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
- qt_memrotate90_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ // packed algorithm assumes little endian and that sizeof(quint32)/sizeof(T) is an integer
+ if (sizeof(quint32) % sizeof(T) == 0)
+ qt_memrotate90_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
+ else
#endif
+ qt_memrotate90_tiled_unpacked<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
+}
+
+template <>
+inline void qt_memrotate90_template<quint32>(const quint32 *src, int w, int h, int sstride, quint32 *dest, int dstride)
+{
+ // packed algorithm doesn't have any benefit for quint32
+ qt_memrotate90_tiled_unpacked(src, w, h, sstride, dest, dstride);
}
template <class T>
@@ -394,11 +244,11 @@ Q_STATIC_TEMPLATE_FUNCTION
inline void qt_memrotate180_template(const T *src, int w, int h, int sstride, T *dest, int dstride)
{
const char *s = (const char*)(src) + (h - 1) * sstride;
- for (int y = h - 1; y >= 0; --y) {
- T *d = reinterpret_cast<T*>((char *)(dest) + (h - y - 1) * dstride);
+ for (int dy = 0; dy < h; ++dy) {
+ T *d = reinterpret_cast<T*>((char *)(dest) + dy * dstride);
src = reinterpret_cast<const T*>(s);
- for (int x = w - 1; x >= 0; --x) {
- d[w - x - 1] = src[x];
+ for (int dx = 0; dx < w; ++dx) {
+ d[dx] = src[w - 1 - dx];
}
s -= sstride;
}
@@ -409,32 +259,20 @@ Q_STATIC_TEMPLATE_FUNCTION
inline void qt_memrotate270_template(const T *src, int srcWidth, int srcHeight, int srcStride,
T *dest, int dstStride)
{
-#if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD
- qt_memrotate270_cachedRead<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
-#elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
- qt_memrotate270_cachedWrite<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
-#elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
- qt_memrotate270_packing<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
-#elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
- qt_memrotate270_tiled_unpacked<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ // packed algorithm assumes little endian and that sizeof(quint32)/sizeof(T) is an integer
+ if (sizeof(quint32) % sizeof(T) == 0)
+ qt_memrotate270_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
+ else
#endif
+ qt_memrotate270_tiled_unpacked<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
}
template <>
-inline void qt_memrotate90_template<quint24>(const quint24 *src, int srcWidth, int srcHeight,
- int srcStride, quint24 *dest, int dstStride)
+inline void qt_memrotate270_template<quint32>(const quint32 *src, int w, int h, int sstride, quint32 *dest, int dstride)
{
-#if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD
- qt_memrotate90_cachedRead<quint24>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
-#elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE
- qt_memrotate90_cachedWrite<quint24>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
-#elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING
- // packed algorithm not implemented
- qt_memrotate90_cachedRead<quint24>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
-#elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED
- // packed algorithm not implemented
- qt_memrotate90_tiled_unpacked<quint24>(src, srcWidth, srcHeight, srcStride, dest, dstStride);
-#endif
+ // packed algorithm doesn't have any benefit for quint32
+ qt_memrotate270_tiled_unpacked(src, w, h, sstride, dest, dstride);
}
#define QT_IMPL_MEMROTATE(type) \
@@ -458,7 +296,7 @@ Q_GUI_EXPORT void qt_memrotate270(const type *src, int w, int h, int sstride, \
Q_GUI_EXPORT void qt_memrotate90(const type *src, int w, int h, int sstride, \
type *dest, int dstride) \
{ \
- qt_memrotate90_tiled_unpacked<type>(src, w, h, sstride, dest, dstride); \
+ qt_memrotate90_tiled_unpacked(src, w, h, sstride, dest, dstride); \
} \
Q_GUI_EXPORT void qt_memrotate180(const type *src, int w, int h, int sstride, \
type *dest, int dstride) \
@@ -468,7 +306,7 @@ Q_GUI_EXPORT void qt_memrotate180(const type *src, int w, int h, int sstride, \
Q_GUI_EXPORT void qt_memrotate270(const type *src, int w, int h, int sstride, \
type *dest, int dstride) \
{ \
- qt_memrotate270_tiled_unpacked<type>(src, w, h, sstride, dest, dstride); \
+ qt_memrotate270_tiled_unpacked(src, w, h, sstride, dest, dstride); \
}
@@ -509,6 +347,21 @@ void qt_memrotate270_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *d
qt_memrotate270((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl);
}
+void qt_memrotate90_24(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
+{
+ qt_memrotate90((const quint24 *)srcPixels, w, h, sbpl, (quint24 *)destPixels, dbpl);
+}
+
+void qt_memrotate180_24(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
+{
+ qt_memrotate180((const quint24 *)srcPixels, w, h, sbpl, (quint24 *)destPixels, dbpl);
+}
+
+void qt_memrotate270_24(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
+{
+ qt_memrotate270((const quint24 *)srcPixels, w, h, sbpl, (quint24 *)destPixels, dbpl);
+}
+
void qt_memrotate90_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
{
qt_memrotate90((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
@@ -524,34 +377,16 @@ void qt_memrotate270_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *d
qt_memrotate270((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
}
-MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3] =
+MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3] =
// 90, 180, 270
{
- { 0, 0, 0 }, // Format_Invalid,
- { 0, 0, 0 }, // Format_Mono,
- { 0, 0, 0 }, // Format_MonoLSB,
- { 0, 0, 0 }, // Format_Indexed8,
- { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_RGB32,
- { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_ARGB32,
- { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_ARGB32_Premultiplied,
- { qt_memrotate90_16, qt_memrotate180_16, qt_memrotate270_16 }, // Format_RGB16,
- { 0, 0, 0 }, // Format_ARGB8565_Premultiplied,
- { 0, 0, 0 }, // Format_RGB666,
- { 0, 0, 0 }, // Format_ARGB6666_Premultiplied,
- { 0, 0, 0 }, // Format_RGB555,
- { 0, 0, 0 }, // Format_ARGB8555_Premultiplied,
- { 0, 0, 0 }, // Format_RGB888,
- { 0, 0, 0 }, // Format_RGB444,
- { 0, 0, 0 }, // Format_ARGB4444_Premultiplied,
- { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_RGBX8888,
- { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_RGBA8888,
- { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_RGBA8888_Premultiplied,
- { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_BGB30,
- { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_A2BGR30_Premultiplied,
- { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_RGB30,
- { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_A2RGB30_Premultiplied,
- { qt_memrotate90_8, qt_memrotate180_8, qt_memrotate270_8 }, // Format_Alpha8,
- { qt_memrotate90_8, qt_memrotate180_8, qt_memrotate270_8 }, // Format_Grayscale8,
+ { 0, 0, 0 }, // BPPNone,
+ { 0, 0, 0 }, // BPP1MSB,
+ { 0, 0, 0 }, // BPP1LSB,
+ { qt_memrotate90_8, qt_memrotate180_8, qt_memrotate270_8 }, // BPP8,
+ { qt_memrotate90_16, qt_memrotate180_16, qt_memrotate270_16 }, // BPP16,
+ { qt_memrotate90_24, qt_memrotate180_24, qt_memrotate270_24 }, // BPP24
+ { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // BPP32
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qmemrotate_p.h b/src/gui/painting/qmemrotate_p.h
index 62613d301a..9bc3fd1010 100644
--- a/src/gui/painting/qmemrotate_p.h
+++ b/src/gui/painting/qmemrotate_p.h
@@ -56,19 +56,6 @@
QT_BEGIN_NAMESPACE
-#define QT_ROTATION_CACHEDREAD 1
-#define QT_ROTATION_CACHEDWRITE 2
-#define QT_ROTATION_PACKING 3
-#define QT_ROTATION_TILED 4
-
-#ifndef QT_ROTATION_ALGORITHM
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
-#define QT_ROTATION_ALGORITHM QT_ROTATION_TILED
-#else
-#define QT_ROTATION_ALGORITHM QT_ROTATION_CACHEDREAD
-#endif
-#endif
-
#define QT_DECL_MEMROTATE(type) \
void Q_GUI_EXPORT qt_memrotate90(const type*, int, int, int, type*, int); \
void Q_GUI_EXPORT qt_memrotate180(const type*, int, int, int, type*, int); \
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index df96a993e3..647bd5cb2c 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -272,6 +272,35 @@ static void qt_debug_path(const QPainterPath &path)
}
#endif
+// QRect::normalized() will change the width/height of the rectangle due to
+// its incusive-integer definition of left/right vs width. This is not
+// something we want to change in QRect as that would potentially introduce
+// regressions all over the place, so we implement a straightforward
+// normalized here. QRectF already does this, so QRectF::normalized() is ok to
+// use.
+static QRect qrect_normalized(const QRect &rect)
+{
+ int x, y, w, h;
+ if (Q_UNLIKELY(rect.width() < 0)) {
+ x = rect.x() + rect.width();
+ w = -rect.width();
+ } else {
+ x = rect.x();
+ w = rect.width();
+ }
+
+ if (Q_UNLIKELY(rect.height() < 0)) {
+ y = rect.y() + rect.height();
+ h = -rect.height();
+ } else {
+ y = rect.y();
+ h = rect.height();
+ }
+
+ return QRect(x, y, w, h);
+}
+
+
QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() :
QPaintEngineExPrivate(),
cachedLines(0)
@@ -1236,7 +1265,9 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
bool QRasterPaintEngine::setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op)
{
Q_D(QRasterPaintEngine);
- QRect clipRect = r & d->deviceRect;
+ // normalize before using the & operator which uses QRect::normalize()
+ // internally which will give us the wrong values.
+ QRect clipRect = qrect_normalized(r) & d->deviceRect;
QRasterPaintEngineState *s = state();
if (op == Qt::ReplaceClip || s->clip == 0) {
@@ -1471,7 +1502,7 @@ void QRasterPaintEngine::drawRects(const QRect *rects, int rectCount)
int offset_x = int(s->matrix.dx());
int offset_y = int(s->matrix.dy());
while (r < lastRect) {
- QRect rect = r->normalized();
+ QRect rect = qrect_normalized(*r);
QRect rr = rect.translated(offset_x, offset_y);
fillRect_normalized(rr, &s->brushData, d);
++r;
@@ -2266,8 +2297,9 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
&& d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source)))
{
RotationType rotationType = qRotationType(s->matrix);
+ const QPixelLayout::BPP plBpp = qPixelLayouts[d->rasterBuffer->format].bpp;
- if (rotationType != NoRotation && qMemRotateFunctions[d->rasterBuffer->format][rotationType] && img.rect().contains(sr.toAlignedRect())) {
+ if (rotationType != NoRotation && qMemRotateFunctions[plBpp][rotationType] && img.rect().contains(sr.toAlignedRect())) {
QRectF transformedTargetRect = s->matrix.mapRect(r);
if ((!(s->renderHints & QPainter::SmoothPixmapTransform) && !(s->renderHints & QPainter::Antialiasing))
@@ -2297,7 +2329,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
uint cw = clippedSourceRect.width();
uint ch = clippedSourceRect.height();
- qMemRotateFunctions[d->rasterBuffer->format][rotationType](srcBase, cw, ch, sbpl, dstBase, dbpl);
+ qMemRotateFunctions[plBpp][rotationType](srcBase, cw, ch, sbpl, dstBase, dbpl);
return;
}
@@ -2500,7 +2532,7 @@ void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap,
QRectF rr = r;
rr.translate(s->matrix.dx(), s->matrix.dy());
- fillRect_normalized(rr.toRect().normalized(), &d->image_filler, d);
+ fillRect_normalized(rr.normalized().toRect(), &d->image_filler, d);
}
}
@@ -2880,7 +2912,7 @@ bool QRasterPaintEnginePrivate::isUnclipped(const QRect &rect,
const QRasterPaintEngineState *s = q->state();
const QClipData *cl = clip();
if (!cl) {
- QRect r = rect.normalized();
+ QRect r = qrect_normalized(rect);
// inline contains() for performance (we know the rects are normalized)
const QRect &r1 = deviceRect;
return (r.left() >= r1.left() && r.right() <= r1.right()
@@ -2895,7 +2927,7 @@ bool QRasterPaintEnginePrivate::isUnclipped(const QRect &rect,
if (s->flags.antialiased)
++penWidth;
- QRect r = rect.normalized();
+ QRect r = qrect_normalized(rect);
if (penWidth > 0) {
r.setX(r.x() - penWidth);
r.setY(r.y() - penWidth);
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 84e18a64dd..7b8bae1642 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -1504,16 +1504,25 @@ void QPdfEnginePrivate::writeInfo()
printString(creator);
xprintf("\n/Producer ");
printString(QString::fromLatin1("Qt " QT_VERSION_STR));
- QDateTime now = QDateTime::currentDateTimeUtc();
+ QDateTime now = QDateTime::currentDateTime();
QTime t = now.time();
QDate d = now.date();
- xprintf("\n/CreationDate (D:%d%02d%02d%02d%02d%02d)\n",
+ xprintf("\n/CreationDate (D:%d%02d%02d%02d%02d%02d",
d.year(),
d.month(),
d.day(),
t.hour(),
t.minute(),
t.second());
+ int offset = now.offsetFromUtc();
+ int hours = (offset / 60) / 60;
+ int mins = (offset / 60) % 60;
+ if (offset < 0)
+ xprintf("-%02d'%02d')\n", -hours, -mins);
+ else if (offset > 0)
+ xprintf("+%02d'%02d')\n", hours , mins);
+ else
+ xprintf("Z)\n");
xprintf(">>\n"
"endobj\n");
}
diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h
index 0dadc038fa..91b5926e43 100644
--- a/src/gui/painting/qrgba64_p.h
+++ b/src/gui/painting/qrgba64_p.h
@@ -185,6 +185,55 @@ inline QRgba64 addWithSaturation(QRgba64 a, QRgba64 b)
qMin(a.alpha() + b.alpha(), 65535));
}
+#if defined __SSE2__
+Q_ALWAYS_INLINE uint toArgb32(__m128i v)
+{
+ v = _mm_unpacklo_epi16(v, _mm_setzero_si128());
+ v = _mm_add_epi32(v, _mm_set1_epi32(128));
+ v = _mm_sub_epi32(v, _mm_srli_epi32(v, 8));
+ v = _mm_srli_epi32(v, 8);
+ v = _mm_packs_epi32(v, v);
+ v = _mm_packus_epi16(v, v);
+ return _mm_cvtsi128_si32(v);
+}
+#elif defined __ARM_NEON__
+Q_ALWAYS_INLINE uint toArgb32(uint16x4_t v)
+{
+ v = vsub_u16(v, vrshr_n_u16(v, 8));
+ v = vrshr_n_u16(v, 8);
+ uint8x8_t v8 = vmovn_u16(vcombine_u16(v, v));
+ return vget_lane_u32(vreinterpret_u32_u8(v8), 0);
+}
+#endif
+
+inline uint toArgb32(QRgba64 rgba64)
+{
+#if defined __SSE2__
+ __m128i v = _mm_loadl_epi64((const __m128i *)&rgba64);
+ v = _mm_shufflelo_epi16(v, _MM_SHUFFLE(3, 0, 1, 2));
+ return toArgb32(v);
+#elif defined __ARM_NEON__
+ uint16x4_t v = vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(&rgba64)));
+ v = vext_u16(v, v, 1);
+ return toArgb32(v);
+#else
+ return rgba64.toArgb32();
+#endif
+}
+
+inline uint toRgba8888(QRgba64 rgba64)
+{
+#if defined __SSE2__
+ __m128i v = _mm_loadl_epi64((const __m128i *)&rgba64);
+ return toArgb32(v);
+#elif defined __ARM_NEON__
+ uint16x4_t v = vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(&rgba64)));
+ return toArgb32(v);
+#else
+ return ARGB2RGBA(toArgb32(rgba64));
+#endif
+}
+
#if defined(__SSE2__)
Q_ALWAYS_INLINE __m128i addWithSaturation(__m128i a, __m128i b)
{
@@ -199,6 +248,52 @@ Q_ALWAYS_INLINE uint16x4_t addWithSaturation(uint16x4_t a, uint16x4_t b)
}
#endif
+inline QRgba64 rgbBlend(QRgba64 d, QRgba64 s, uint rgbAlpha)
+{
+ QRgba64 blend;
+#ifdef __SSE2__
+ __m128i vd = _mm_loadl_epi64((const __m128i *)&d);
+ __m128i vs = _mm_loadl_epi64((const __m128i *)&s);
+ __m128i va = _mm_cvtsi32_si128(rgbAlpha);
+ va = _mm_unpacklo_epi8(va, va);
+ __m128i vb = _mm_xor_si128(_mm_set1_epi16(-1), va);
+
+ vs = _mm_unpacklo_epi16(_mm_mullo_epi16(vs, va), _mm_mulhi_epu16(vs, va));
+ vd = _mm_unpacklo_epi16(_mm_mullo_epi16(vd, vb), _mm_mulhi_epu16(vd, vb));
+ vd = _mm_add_epi32(vd, vs);
+ vd = _mm_add_epi32(vd, _mm_srli_epi32(vd, 16));
+ vd = _mm_add_epi32(vd, _mm_set1_epi32(0x8000));
+ vd = _mm_srai_epi32(vd, 16);
+ vd = _mm_packs_epi32(vd, _mm_setzero_si128());
+
+ _mm_storel_epi64((__m128i *)&blend, vd);
+#elif defined(__ARM_NEON__)
+ uint16x4_t vd = vreinterpret_u16_u64(vmov_n_u64(d));
+ uint16x4_t vs = vreinterpret_u16_u64(vmov_n_u64(s));
+ uint8x8_t va8 = vreinterpret_u8_u32(vmov_n_u32(rgbAlpha));
+ uint16x4_t va = vreinterpret_u16_u8(vzip_u8(va8, va8).val[0]);
+ uint16x4_t vb = vdup_n_u16(0xffff);
+ vb = vsub_u16(vb, va);
+
+ uint32x4_t vs32 = vmull_u16(vs, va);
+ uint32x4_t vd32 = vmull_u16(vd, vb);
+ vd32 = vaddq_u32(vd32, vs32);
+ vd32 = vsraq_n_u32(vd32, vd32, 16);
+ vd = vrshrn_n_u32(vd32, 16);
+ vst1_u64(reinterpret_cast<uint64_t *>(&blend), vreinterpret_u64_u16(vd));
+#else
+ const int mr = qRed(rgbAlpha);
+ const int mg = qGreen(rgbAlpha);
+ const int mb = qBlue(rgbAlpha);
+ blend.setRed (qt_div_255(s.red() * mr + d.red() * (255 - mr)));
+ blend.setGreen(qt_div_255(s.green() * mg + d.green() * (255 - mg)));
+ blend.setBlue (qt_div_255(s.blue() * mb + d.blue() * (255 - mb)));
+ blend.setAlpha(s.alpha());
+#endif
+ return blend;
+}
+
+
QT_END_NAMESPACE
#endif // QRGBA64_P_H
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 0d05fee6ef..5e9fac5f86 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -1145,9 +1145,28 @@ void QTextDocument::setMetaInformation(MetaInformation info, const QString &stri
}
/*!
+ Returns the raw text contained in the document without any
+ formatting information. If you want formatting information
+ use a QTextCursor instead.
+
+ \since 5.9
+ \sa toPlainText()
+*/
+QString QTextDocument::toRawText() const
+{
+ Q_D(const QTextDocument);
+ return d->plainText();
+}
+
+/*!
Returns the plain text contained in the document. If you want
formatting information use a QTextCursor instead.
+ This function returns the same as toRawText(), but will replace
+ some unicode characters, such as line separators and non-breaking
+ spaces, with ASCII alternatives. If you need the precise contents
+ of the document, use toRawText() instead.
+
\note Embedded objects, such as images, are represented by a
Unicode value U+FFFC (OBJECT REPLACEMENT CHARACTER).
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index 1888088f0d..c2761a39b9 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -151,6 +151,7 @@ public:
void setHtml(const QString &html);
#endif
+ QString toRawText() const;
QString toPlainText() const;
void setPlainText(const QString &text);
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index d4c43b3069..269e505a56 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -329,17 +329,17 @@ bool operator<(const QTextHtmlEntity &entity1, const QTextHtmlEntity &entity2)
}
#endif
-static bool operator<(const QString &entityStr, const QTextHtmlEntity &entity)
+static bool operator<(const QStringRef &entityStr, const QTextHtmlEntity &entity)
{
return entityStr < QLatin1String(entity.name);
}
-static bool operator<(const QTextHtmlEntity &entity, const QString &entityStr)
+static bool operator<(const QTextHtmlEntity &entity, const QStringRef &entityStr)
{
return QLatin1String(entity.name) < entityStr;
}
-static QChar resolveEntity(const QString &entity)
+static QChar resolveEntity(const QStringRef &entity)
{
const QTextHtmlEntity *start = &entities[0];
const QTextHtmlEntity *end = &entities[MAX_ENTITY];
@@ -801,8 +801,9 @@ void QTextHtmlParser::parseExclamationTag()
// parses an entity after "&", and returns it
QString QTextHtmlParser::parseEntity()
{
- int recover = pos;
- QString entity;
+ const int recover = pos;
+ int entityLen = 0;
+ QStringRef entity;
while (pos < len) {
QChar c = txt.at(pos++);
if (c.isSpace() || pos - recover > 9) {
@@ -810,36 +811,38 @@ QString QTextHtmlParser::parseEntity()
}
if (c == QLatin1Char(';'))
break;
- entity += c;
+ ++entityLen;
}
- {
+ if (entityLen) {
+ entity = QStringRef(&txt, recover, entityLen);
QChar resolved = resolveEntity(entity);
if (!resolved.isNull())
return QString(resolved);
- }
- if (entity.length() > 1 && entity.at(0) == QLatin1Char('#')) {
- entity.remove(0, 1); // removing leading #
- int base = 10;
- bool ok = false;
+ if (entityLen > 1 && entity.at(0) == QLatin1Char('#')) {
+ entity = entity.mid(1); // removing leading #
- if (entity.at(0).toLower() == QLatin1Char('x')) { // hex entity?
- entity.remove(0, 1);
- base = 16;
- }
+ int base = 10;
+ bool ok = false;
- uint uc = entity.toUInt(&ok, base);
- if (ok) {
- if (uc >= 0x80 && uc < 0x80 + (sizeof(windowsLatin1ExtendedCharacters)/sizeof(windowsLatin1ExtendedCharacters[0])))
- uc = windowsLatin1ExtendedCharacters[uc - 0x80];
- QString str;
- if (QChar::requiresSurrogates(uc)) {
- str += QChar(QChar::highSurrogate(uc));
- str += QChar(QChar::lowSurrogate(uc));
- } else {
- str = QChar(uc);
+ if (entity.at(0).toLower() == QLatin1Char('x')) { // hex entity?
+ entity = entity.mid(1);
+ base = 16;
+ }
+
+ uint uc = entity.toUInt(&ok, base);
+ if (ok) {
+ if (uc >= 0x80 && uc < 0x80 + (sizeof(windowsLatin1ExtendedCharacters)/sizeof(windowsLatin1ExtendedCharacters[0])))
+ uc = windowsLatin1ExtendedCharacters[uc - 0x80];
+ QString str;
+ if (QChar::requiresSurrogates(uc)) {
+ str += QChar(QChar::highSurrogate(uc));
+ str += QChar(QChar::lowSurrogate(uc));
+ } else {
+ str = QChar(uc);
+ }
+ return str;
}
- return str;
}
}
error:
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 540bbf5d54..023a1b7f52 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1653,6 +1653,7 @@ namespace {
int maxGlyphs;
int currentPosition;
glyph_t previousGlyph;
+ QFontEngine *previousGlyphFontEngine;
QFixed minw;
QFixed softHyphenWidth;
@@ -1686,13 +1687,14 @@ namespace {
if (currentPosition > 0 &&
logClusters[currentPosition - 1] < glyphs.numGlyphs) {
previousGlyph = currentGlyph(); // needed to calculate right bearing later
+ previousGlyphFontEngine = fontEngine;
}
}
- inline void calculateRightBearing(glyph_t glyph)
+ inline void calculateRightBearing(QFontEngine *engine, glyph_t glyph)
{
qreal rb;
- fontEngine->getGlyphBearings(glyph, 0, &rb);
+ engine->getGlyphBearings(glyph, 0, &rb);
// We only care about negative right bearings, so we limit the range
// of the bearing here so that we can assume it's negative in the rest
@@ -1705,13 +1707,13 @@ namespace {
{
if (currentPosition <= 0)
return;
- calculateRightBearing(currentGlyph());
+ calculateRightBearing(fontEngine, currentGlyph());
}
inline void calculateRightBearingForPreviousGlyph()
{
if (previousGlyph > 0)
- calculateRightBearing(previousGlyph);
+ calculateRightBearing(previousGlyphFontEngine, previousGlyph);
}
static const QFixed RightBearingNotCalculated;
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index 085c073bb1..c9747877f7 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -198,8 +198,15 @@ bool QDesktopServices::openUrl(const QUrl &url)
return false;
QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
- if (!platformIntegration)
+ if (Q_UNLIKELY(!platformIntegration)) {
+ QCoreApplication *application = QCoreApplication::instance();
+ if (Q_UNLIKELY(!application))
+ qWarning("QDesktopServices::openUrl: Please instantiate the QGuiApplication object "
+ "first");
+ else if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(application)))
+ qWarning("QDesktopServices::openUrl: Application is not a GUI application");
return false;
+ }
QPlatformServices *platformServices = platformIntegration->services();
if (!platformServices) {
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index 24ada3a81f..612abb9044 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -299,6 +299,11 @@ void QHttpNetworkReply::setSpdyWasUsed(bool spdy)
d_func()->spdyUsed = spdy;
}
+qint64 QHttpNetworkReply::removedContentLength() const
+{
+ return d_func()->removedContentLength;
+}
+
bool QHttpNetworkReply::isRedirecting() const
{
return d_func()->isRedirecting();
@@ -326,6 +331,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
currentlyReceivedDataInWindow(0),
currentlyUploadedDataInWindow(0),
totallyUploadedData(0),
+ removedContentLength(-1),
connection(0),
autoDecompress(false), responseData(), requestIsPrepared(false)
,pipeliningUsed(false), spdyUsed(false), downstreamLimited(false)
@@ -398,12 +404,12 @@ void QHttpNetworkReplyPrivate::removeAutoDecompressHeader()
end = fields.end();
while (it != end) {
if (qstricmp(name.constData(), it->first.constData()) == 0) {
+ removedContentLength = strtoull(it->second.constData(), nullptr, 0);
fields.erase(it);
break;
}
++it;
}
-
}
bool QHttpNetworkReplyPrivate::findChallenge(bool forProxy, QByteArray &challenge) const
diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h
index f3b007f594..faab03f056 100644
--- a/src/network/access/qhttpnetworkreply_p.h
+++ b/src/network/access/qhttpnetworkreply_p.h
@@ -139,6 +139,7 @@ public:
bool isPipeliningUsed() const;
bool isSpdyUsed() const;
void setSpdyWasUsed(bool spdy);
+ qint64 removedContentLength() const;
bool isRedirecting() const;
@@ -255,6 +256,7 @@ public:
qint32 currentlyReceivedDataInWindow; // only for SPDY
qint32 currentlyUploadedDataInWindow; // only for SPDY
qint64 totallyUploadedData; // only for SPDY
+ qint64 removedContentLength;
QPointer<QHttpNetworkConnection> connection;
QPointer<QHttpNetworkConnectionChannel> connectionChannel;
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 1dca7f02fb..e71911cec2 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -234,6 +234,7 @@ QHttpThreadDelegate::QHttpThreadDelegate(QObject *parent) :
, isPipeliningUsed(false)
, isSpdyUsed(false)
, incomingContentLength(-1)
+ , removedContentLength(-1)
, incomingErrorCode(QNetworkReply::NoError)
, downloadBuffer()
, httpConnection(0)
@@ -623,6 +624,7 @@ void QHttpThreadDelegate::headerChangedSlot()
incomingReasonPhrase = httpReply->reasonPhrase();
isPipeliningUsed = httpReply->isPipeliningUsed();
incomingContentLength = httpReply->contentLength();
+ removedContentLength = httpReply->removedContentLength();
isSpdyUsed = httpReply->isSpdyUsed();
emit downloadMetaData(incomingHeaders,
@@ -631,6 +633,7 @@ void QHttpThreadDelegate::headerChangedSlot()
isPipeliningUsed,
downloadBuffer,
incomingContentLength,
+ removedContentLength,
isSpdyUsed);
}
diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h
index 64c58cf648..6d1ea11f29 100644
--- a/src/network/access/qhttpthreaddelegate_p.h
+++ b/src/network/access/qhttpthreaddelegate_p.h
@@ -112,6 +112,7 @@ public:
bool isPipeliningUsed;
bool isSpdyUsed;
qint64 incomingContentLength;
+ qint64 removedContentLength;
QNetworkReply::NetworkError incomingErrorCode;
QString incomingErrorDetail;
#ifndef QT_NO_BEARERMANAGEMENT
@@ -141,7 +142,7 @@ signals:
void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *);
#endif
void downloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &, bool,
- QSharedPointer<char>, qint64, bool);
+ QSharedPointer<char>, qint64, qint64, bool);
void downloadProgress(qint64, qint64);
void downloadData(const QByteArray &);
void error(QNetworkReply::NetworkError, const QString &);
diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h
index 7f39c942a3..4b5422ce29 100644
--- a/src/network/access/qnetworkaccessbackend_p.h
+++ b/src/network/access/qnetworkaccessbackend_p.h
@@ -63,7 +63,6 @@ class QNetworkProxyQuery;
class QNetworkRequest;
class QStringList;
class QUrl;
-class QUrlInfo;
class QSslConfiguration;
class QNetworkAccessManagerPrivate;
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 6f5e68d9c2..00f3468ebd 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -803,10 +803,11 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
Qt::QueuedConnection);
QObject::connect(delegate, SIGNAL(downloadMetaData(QList<QPair<QByteArray,QByteArray> >,
int, QString, bool,
- QSharedPointer<char>, qint64, bool)),
+ QSharedPointer<char>, qint64, qint64,
+ bool)),
q, SLOT(replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,
int, QString, bool,
- QSharedPointer<char>, qint64, bool)),
+ QSharedPointer<char>, qint64, qint64, bool)),
Qt::QueuedConnection);
QObject::connect(delegate, SIGNAL(downloadProgress(qint64,qint64)),
q, SLOT(replyDownloadProgressSlot(qint64,qint64)),
@@ -911,6 +912,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
delegate->isPipeliningUsed,
QSharedPointer<char>(),
delegate->incomingContentLength,
+ delegate->removedContentLength,
delegate->isSpdyUsed);
replyDownloadData(delegate->synchronousDownloadData);
httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail);
@@ -922,6 +924,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
delegate->isPipeliningUsed,
QSharedPointer<char>(),
delegate->incomingContentLength,
+ delegate->removedContentLength,
delegate->isSpdyUsed);
replyDownloadData(delegate->synchronousDownloadData);
}
@@ -1149,7 +1152,9 @@ void QNetworkReplyHttpImplPrivate::checkForRedirect(const int statusCode)
void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &hm,
int sc, const QString &rp, bool pu,
QSharedPointer<char> db,
- qint64 contentLength, bool spdyWasUsed)
+ qint64 contentLength,
+ qint64 removedContentLength,
+ bool spdyWasUsed)
{
Q_Q(QNetworkReplyHttpImpl);
Q_UNUSED(contentLength);
@@ -1195,6 +1200,8 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByte
q->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
q->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase);
+ if (removedContentLength != -1)
+ q->setAttribute(QNetworkRequest::OriginalContentLengthAttribute, removedContentLength);
// is it a redirection?
if (!isHttpRedirectResponse())
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index 868fa617b6..255c23006e 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -114,7 +114,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void replyFinished())
Q_PRIVATE_SLOT(d_func(), void replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,
int, QString, bool, QSharedPointer<char>,
- qint64, bool))
+ qint64, qint64, bool))
Q_PRIVATE_SLOT(d_func(), void replyDownloadProgressSlot(qint64,qint64))
Q_PRIVATE_SLOT(d_func(), void httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *))
Q_PRIVATE_SLOT(d_func(), void httpError(QNetworkReply::NetworkError, const QString &))
@@ -280,7 +280,7 @@ public:
void replyDownloadData(QByteArray);
void replyFinished();
void replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &,
- bool, QSharedPointer<char>, qint64, bool);
+ bool, QSharedPointer<char>, qint64, qint64, bool);
void replyDownloadProgressSlot(qint64,qint64);
void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth);
void httpError(QNetworkReply::NetworkError error, const QString &errorString);
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index 29362b81e2..bc2507ca51 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -282,6 +282,13 @@ QT_BEGIN_NAMESPACE
that is redirecting from "https" to "http" protocol, are not allowed.
(This value was introduced in 5.6.)
+ \value OriginalContentLengthAttribute
+ Replies only, type QMetaType::Int
+ Holds the original content-length attribute before being invalidated and
+ removed from the header when the data is compressed and the request was
+ marked to be decompressed automatically.
+ (This value was introduced in 5.9.)
+
\value User
Special type. Additional information can be passed in
QVariants with types ranging from User to UserMax. The default
diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h
index ad8f5bddd9..9a3a7f0fb5 100644
--- a/src/network/access/qnetworkrequest.h
+++ b/src/network/access/qnetworkrequest.h
@@ -91,6 +91,7 @@ public:
FollowRedirectsAttribute,
HTTP2AllowedAttribute,
HTTP2WasUsedAttribute,
+ OriginalContentLengthAttribute,
User = 1000,
UserMax = 32767
diff --git a/src/network/bearer/qnetworkconfiguration.cpp b/src/network/bearer/qnetworkconfiguration.cpp
index 533a27357c..d2feffb316 100644
--- a/src/network/bearer/qnetworkconfiguration.cpp
+++ b/src/network/bearer/qnetworkconfiguration.cpp
@@ -326,6 +326,44 @@ bool QNetworkConfiguration::isValid() const
}
/*!
+ \since 5.9
+
+ Returns the connect timeout of this configuration.
+
+ \sa setConnectTimeout
+*/
+int QNetworkConfiguration::connectTimeout() const
+{
+ if (!d)
+ return QNetworkConfigurationPrivate::DefaultTimeout;
+ QMutexLocker locker(&d->mutex);
+ return d->timeout;
+}
+
+/*!
+ \since 5.9
+
+ Sets the connect timeout of this configuration.
+ This allows control of the timeout used by \c QAbstractSocket
+ to establish a connection.
+
+ \warning This will have no effect if the bearer plugin doesn't have
+ the CanStartAndStopInterfaces capability.
+
+ Returns true if succeeded.
+
+ \sa connectTimeout
+*/
+bool QNetworkConfiguration::setConnectTimeout(int timeout)
+{
+ if (!d)
+ return false;
+ QMutexLocker locker(&d->mutex);
+ d->timeout = timeout;
+ return true;
+}
+
+/*!
Returns the current state of the configuration.
*/
QNetworkConfiguration::StateFlags QNetworkConfiguration::state() const
diff --git a/src/network/bearer/qnetworkconfiguration.h b/src/network/bearer/qnetworkconfiguration.h
index 208f9f4692..e7b74034fc 100644
--- a/src/network/bearer/qnetworkconfiguration.h
+++ b/src/network/bearer/qnetworkconfiguration.h
@@ -120,6 +120,9 @@ public:
QString name() const;
bool isValid() const;
+ int connectTimeout() const;
+ bool setConnectTimeout(int timeout);
+
private:
friend class QNetworkConfigurationPrivate;
friend class QNetworkConfigurationManager;
diff --git a/src/network/bearer/qnetworkconfiguration_p.h b/src/network/bearer/qnetworkconfiguration_p.h
index 12d9676b59..2fdb490ea0 100644
--- a/src/network/bearer/qnetworkconfiguration_p.h
+++ b/src/network/bearer/qnetworkconfiguration_p.h
@@ -69,7 +69,8 @@ public:
type(QNetworkConfiguration::Invalid),
purpose(QNetworkConfiguration::UnknownPurpose),
bearerType(QNetworkConfiguration::BearerUnknown),
- isValid(false), roamingSupported(false)
+ isValid(false), roamingSupported(false),
+ timeout(DefaultTimeout)
{}
virtual ~QNetworkConfigurationPrivate()
{
@@ -91,6 +92,9 @@ public:
bool isValid;
bool roamingSupported;
+ int timeout;
+
+ static Q_CONSTEXPR int DefaultTimeout = 30000;
private:
Q_DISABLE_COPY(QNetworkConfigurationPrivate)
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri
index 005f000c25..a80b2d387e 100644
--- a/src/network/kernel/kernel.pri
+++ b/src/network/kernel/kernel.pri
@@ -56,8 +56,7 @@ win32: {
mac {
LIBS_PRIVATE += -framework CoreFoundation
- !uikit: LIBS_PRIVATE += -framework CoreServices
- !if(watchos:CONFIG(device, simulator|device)): LIBS_PRIVATE += -framework SystemConfiguration
+ !uikit: LIBS_PRIVATE += -framework CoreServices -framework SystemConfiguration
}
osx:SOURCES += kernel/qnetworkproxy_mac.cpp
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index 7e3d2c5d6e..2a905101a4 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -201,10 +201,10 @@ void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_)
static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr, QString *scopeId)
{
- QString tmp = address;
+ QStringRef tmp(&address);
int scopeIdPos = tmp.lastIndexOf(QLatin1Char('%'));
if (scopeIdPos != -1) {
- *scopeId = tmp.mid(scopeIdPos + 1);
+ *scopeId = tmp.mid(scopeIdPos + 1).toString();
tmp.chop(tmp.size() - scopeIdPos);
} else {
scopeId->clear();
@@ -1086,7 +1086,7 @@ QPair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet)
return invalid;
int slash = subnet.indexOf(QLatin1Char('/'));
- QString netStr = subnet;
+ QStringRef netStr(&subnet);
if (slash != -1)
netStr.truncate(slash);
@@ -1117,7 +1117,7 @@ QPair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet)
netmask = 128;
QHostAddress net;
- if (!net.setAddress(netStr))
+ if (!net.setAddress(netStr.toString()))
return invalid; // failed to parse the IP
clearBits(net.d->a6.c, netmask, 128);
@@ -1128,7 +1128,7 @@ QPair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet)
return invalid; // invalid netmask
// parse the address manually
- auto parts = netStr.splitRef(QLatin1Char('.'));
+ auto parts = netStr.split(QLatin1Char('.'));
if (parts.isEmpty() || parts.count() > 4)
return invalid; // invalid IPv4 address
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 57c40194a3..271b5848c5 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -491,7 +491,6 @@
#ifndef QABSTRACTSOCKET_BUFFERSIZE
#define QABSTRACTSOCKET_BUFFERSIZE 32768
#endif
-#define QT_CONNECT_TIMEOUT 30000
#define QT_TRANSFER_TIMEOUT 120000
QT_BEGIN_NAMESPACE
@@ -1142,7 +1141,15 @@ void QAbstractSocketPrivate::_q_connectToNextAddress()
q, SLOT(_q_abortConnectionAttempt()),
Qt::DirectConnection);
}
- connectTimer->start(QT_CONNECT_TIMEOUT);
+ int connectTimeout = QNetworkConfigurationPrivate::DefaultTimeout;
+#ifndef QT_NO_BEARERMANAGEMENT
+ QSharedPointer<QNetworkSession> networkSession = qvariant_cast< QSharedPointer<QNetworkSession> >(q->property("_q_networksession"));
+ if (networkSession) {
+ QNetworkConfiguration networkConfiguration = networkSession->configuration();
+ connectTimeout = networkConfiguration.connectTimeout();
+ }
+#endif
+ connectTimer->start(connectTimeout);
}
// Wait for a write notification that will eventually call
@@ -1279,11 +1286,11 @@ bool QAbstractSocketPrivate::readFromSocket()
}
if (!socketEngine->isValid()) {
- setErrorAndEmit(socketEngine->error(), socketEngine->errorString());
#if defined(QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocketPrivate::readFromSocket() read failed: %s",
- q->errorString().toLatin1().constData());
+ socketEngine->errorString().toLatin1().constData());
#endif
+ setErrorAndEmit(socketEngine->error(), socketEngine->errorString());
resetSocketLayer();
return false;
}
@@ -2100,6 +2107,10 @@ bool QAbstractSocket::waitForConnected(int msecs)
QElapsedTimer stopWatch;
stopWatch.start();
+#ifndef QT_NO_BEARERMANAGEMENT
+ QSharedPointer<QNetworkSession> networkSession = qvariant_cast< QSharedPointer<QNetworkSession> >(property("_q_networksession"));
+#endif
+
if (d->state == HostLookupState) {
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocket::waitForConnected(%i) doing host name lookup", msecs);
@@ -2107,10 +2118,7 @@ bool QAbstractSocket::waitForConnected(int msecs)
QHostInfo::abortHostLookup(d->hostLookupId);
d->hostLookupId = -1;
#ifndef QT_NO_BEARERMANAGEMENT
- QSharedPointer<QNetworkSession> networkSession;
- QVariant v(property("_q_networksession"));
- if (v.isValid()) {
- networkSession = qvariant_cast< QSharedPointer<QNetworkSession> >(v);
+ if (networkSession) {
d->_q_startConnecting(QHostInfoPrivate::fromName(d->hostName, networkSession));
} else
#endif
@@ -2128,14 +2136,21 @@ bool QAbstractSocket::waitForConnected(int msecs)
if (state() == UnconnectedState)
return false; // connect not im progress anymore!
+ int connectTimeout = QNetworkConfigurationPrivate::DefaultTimeout;
+#ifndef QT_NO_BEARERMANAGEMENT
+ if (networkSession) {
+ QNetworkConfiguration networkConfiguration = networkSession->configuration();
+ connectTimeout = networkConfiguration.connectTimeout();
+ }
+#endif
bool timedOut = true;
#if defined (QABSTRACTSOCKET_DEBUG)
int attempt = 1;
#endif
while (state() == ConnectingState && (msecs == -1 || stopWatch.elapsed() < msecs)) {
int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
- if (msecs != -1 && timeout > QT_CONNECT_TIMEOUT)
- timeout = QT_CONNECT_TIMEOUT;
+ if (msecs != -1 && timeout > connectTimeout)
+ timeout = connectTimeout;
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocket::waitForConnected(%i) waiting %.2f secs for connection attempt #%i",
msecs, timeout / 1000.0, attempt++);
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 5a9641a9fe..80147b47ba 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -51,6 +51,7 @@
#include <qdebug.h>
#include <qdatetime.h>
#include <qnetworkinterface.h>
+#include <qoperatingsystemversion.h>
//#define QNATIVESOCKETENGINE_DEBUG
#if defined(QNATIVESOCKETENGINE_DEBUG)
@@ -334,11 +335,9 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
return false;
}
- QSysInfo::WinVersion osver = QSysInfo::windowsVersion();
-
//Windows XP and 2003 support IPv6 but not dual stack sockets
int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol
- || (socketProtocol == QAbstractSocket::AnyIPProtocol && osver >= QSysInfo::WV_6_0)) ? AF_INET6 : AF_INET;
+ || (socketProtocol == QAbstractSocket::AnyIPProtocol)) ? AF_INET6 : AF_INET;
int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
// MSDN KB179942 states that on winnt 4 WSA_FLAG_OVERLAPPED is needed if socket is to be non blocking
@@ -350,14 +349,11 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
#define WSA_FLAG_NO_HANDLE_INHERIT 0x80
#endif
- SOCKET socket = INVALID_SOCKET;
- // Windows 7 or later, try the new API
- if ((osver & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_1)
- socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED);
+ SOCKET socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED);
// previous call fails if the windows 7 service pack 1 or hot fix isn't installed.
- // Try the old API if the new one failed on Windows 7, or always on earlier versions
- if (socket == INVALID_SOCKET && ((osver & QSysInfo::WV_NT_based) <= QSysInfo::WV_6_1)) {
+ // Try the old API if the new one failed on Windows 7
+ if (socket == INVALID_SOCKET && QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8) {
socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
#ifdef HANDLE_FLAG_INHERIT
if (socket != INVALID_SOCKET) {
diff --git a/src/network/socket/qsctpserver.h b/src/network/socket/qsctpserver.h
index f39257485d..1afdab28a0 100644
--- a/src/network/socket/qsctpserver.h
+++ b/src/network/socket/qsctpserver.h
@@ -45,7 +45,7 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_SCTP
+#if !defined(QT_NO_SCTP) || defined(Q_CLANG_QDOC)
class QSctpServerPrivate;
class QSctpSocket;
diff --git a/src/network/socket/qsctpsocket.h b/src/network/socket/qsctpsocket.h
index 3e5a545c4b..9bed1890ff 100644
--- a/src/network/socket/qsctpsocket.h
+++ b/src/network/socket/qsctpsocket.h
@@ -45,7 +45,7 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_SCTP
+#if !defined(QT_NO_SCTP) || defined(Q_CLANG_QDOC)
class QSctpSocketPrivate;
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index a1a8e4649d..89261ce789 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -54,6 +54,7 @@
#include "qurl.h"
#include "qauthenticator.h"
#include "private/qiodevice_p.h"
+#include "private/qringbuffer_p.h"
#include <qendian.h>
#include <qnetworkinterface.h>
@@ -280,7 +281,7 @@ struct QSocks5Data
struct QSocks5ConnectData : public QSocks5Data
{
- QByteArray readBuffer;
+ QRingBuffer readBuffer;
};
struct QSocks5BindData : public QSocks5Data
@@ -1193,7 +1194,7 @@ void QSocks5SocketEnginePrivate::_q_controlSocketReadNotification()
}
if (buf.size()) {
QSOCKS5_DEBUG << dump(buf);
- connectData->readBuffer += buf;
+ connectData->readBuffer.append(buf);
emitReadNotification();
}
break;
@@ -1513,7 +1514,7 @@ qint64 QSocks5SocketEngine::read(char *data, qint64 maxlen)
Q_D(QSocks5SocketEngine);
QSOCKS5_Q_DEBUG << "read( , maxlen = " << maxlen << ')';
if (d->mode == QSocks5SocketEnginePrivate::ConnectMode) {
- if (d->connectData->readBuffer.size() == 0) {
+ if (d->connectData->readBuffer.isEmpty()) {
if (d->data->controlSocket->state() == QAbstractSocket::UnconnectedState) {
//imitate remote closed
close();
@@ -1525,9 +1526,7 @@ qint64 QSocks5SocketEngine::read(char *data, qint64 maxlen)
return 0; // nothing to be read
}
}
- qint64 copy = qMin<qint64>(d->connectData->readBuffer.size(), maxlen);
- memcpy(data, d->connectData->readBuffer.constData(), copy);
- d->connectData->readBuffer.remove(0, copy);
+ const qint64 copy = d->connectData->readBuffer.read(data, maxlen);
QSOCKS5_DEBUG << "read" << dump(QByteArray(data, copy));
return copy;
#ifndef QT_NO_UDPSOCKET
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index 88fed69d3a..2a0d746fde 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -154,7 +154,7 @@ DEFINEFUNC(int, BN_num_bits, const BIGNUM *a, a, return 0, return)
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return)
#endif
-DEFINEFUNC2(BN_ULONG, BN_mod_word, const BIGNUM *a, a, BN_ULONG w, w, return -1, return)
+DEFINEFUNC2(BN_ULONG, BN_mod_word, const BIGNUM *a, a, BN_ULONG w, w, return static_cast<BN_ULONG>(-1), return)
#ifndef OPENSSL_NO_EC
DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return 0, return)
DEFINEFUNC(int, EC_GROUP_get_degree, const EC_GROUP* g, g, return 0, return)
diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp
index f5dc9fcdcd..ca65f8a015 100644
--- a/src/network/ssl/qsslsocket_winrt.cpp
+++ b/src/network/ssl/qsslsocket_winrt.cpp
@@ -181,13 +181,7 @@ long QSslSocketPrivate::sslLibraryVersionNumber()
QString QSslSocketPrivate::sslLibraryVersionString()
{
- switch (QSysInfo::windowsVersion()) {
- case QSysInfo::WV_WINDOWS8_1:
- return QStringLiteral("Windows Runtime 8.1 SSL library");
- default:
- break;
- }
- return QStringLiteral("Windows Runtime SSL library");
+ return QStringLiteral("Windows Runtime, ") + QSysInfo::prettyProductName();
}
long QSslSocketPrivate::sslLibraryBuildVersionNumber()
diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h
index a97ddb2b27..ab418c191a 100644
--- a/src/opengl/qgl.h
+++ b/src/opengl/qgl.h
@@ -51,6 +51,15 @@
#include <QtGui/QSurfaceFormat>
+#if defined(Q_CLANG_QDOC)
+#undef GLint
+typedef int GLint;
+#undef GLuint
+typedef unsigned int GLuint;
+#undef GLenum
+typedef unsigned int GLenum;
+#endif
+
QT_BEGIN_NAMESPACE
diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp b/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp
index 5c72dbe7e2..a1575677f5 100644
--- a/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp
+++ b/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp
@@ -47,7 +47,11 @@
#include <QLoggingCategory>
#include <QtCore/private/qcore_unix_p.h>
+#ifdef Q_OS_FREEBSD
+#include <dev/evdev/input.h>
+#else
#include <linux/input.h>
+#endif
#include <fcntl.h>
/* android (and perhaps some other linux-derived stuff) don't define everything
diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp
index da41cfeabf..020d035bf7 100644
--- a/src/platformsupport/eglconvenience/qeglconvenience.cpp
+++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp
@@ -100,18 +100,24 @@ QVector<EGLint> q_createConfigAttributesFromFormat(const QSurfaceFormat &format)
configAttributes.append(EGL_ALPHA_SIZE);
configAttributes.append(alphaSize > 0 ? alphaSize : 0);
- configAttributes.append(EGL_DEPTH_SIZE);
- configAttributes.append(depthSize > 0 ? depthSize : 0);
-
- configAttributes.append(EGL_STENCIL_SIZE);
- configAttributes.append(stencilSize > 0 ? stencilSize : 0);
-
configAttributes.append(EGL_SAMPLES);
configAttributes.append(sampleCount > 0 ? sampleCount : 0);
configAttributes.append(EGL_SAMPLE_BUFFERS);
configAttributes.append(sampleCount > 0);
+ if (format.renderableType() != QSurfaceFormat::OpenVG) {
+ configAttributes.append(EGL_DEPTH_SIZE);
+ configAttributes.append(depthSize > 0 ? depthSize : 0);
+
+ configAttributes.append(EGL_STENCIL_SIZE);
+ configAttributes.append(stencilSize > 0 ? stencilSize : 0);
+ } else {
+ // OpenVG needs alpha mask for clipping
+ configAttributes.append(EGL_ALPHA_MASK_SIZE);
+ configAttributes.append(8);
+ }
+
return configAttributes;
}
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
index 6a3bc25418..2d3d91b4fa 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
@@ -167,6 +167,13 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont
: EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
}
}
+
+ // Special Options for OpenVG surfaces
+ if (m_format.renderableType() == QSurfaceFormat::OpenVG) {
+ contextAttrs.append(EGL_ALPHA_MASK_SIZE);
+ contextAttrs.append(8);
+ }
+
contextAttrs.append(EGL_NONE);
m_contextAttrs = contextAttrs;
diff --git a/src/platformsupport/fbconvenience/qfbcursor.cpp b/src/platformsupport/fbconvenience/qfbcursor.cpp
index 004c586de3..7daf3f4d0c 100644
--- a/src/platformsupport/fbconvenience/qfbcursor.cpp
+++ b/src/platformsupport/fbconvenience/qfbcursor.cpp
@@ -60,8 +60,8 @@ QFbCursor::QFbCursor(QFbScreen *screen)
mScreen(screen),
mDirty(false),
mOnScreen(false),
- mGraphic(0),
- mDeviceListener(0)
+ mCursorImage(nullptr),
+ mDeviceListener(nullptr)
{
QByteArray hideCursorVal = qgetenv("QT_QPA_FB_HIDECURSOR");
if (!hideCursorVal.isEmpty())
@@ -69,7 +69,7 @@ QFbCursor::QFbCursor(QFbScreen *screen)
if (!mVisible)
return;
- mGraphic = new QPlatformCursorImage(0, 0, 0, 0, 0, 0);
+ mCursorImage = new QPlatformCursorImage(0, 0, 0, 0, 0, 0);
setCursor(Qt::ArrowCursor);
mDeviceListener = new QFbCursorDeviceListener(this);
@@ -85,8 +85,8 @@ QFbCursor::~QFbCursor()
QRect QFbCursor::getCurrentRect()
{
- QRect rect = mGraphic->image()->rect().translated(-mGraphic->hotspot().x(),
- -mGraphic->hotspot().y());
+ QRect rect = mCursorImage->image()->rect().translated(-mCursorImage->hotspot().x(),
+ -mCursorImage->hotspot().y());
rect.translate(m_pos);
QPoint mScreenOffset = mScreen->geometry().topLeft();
rect.translate(-mScreenOffset); // global to local translation
@@ -133,7 +133,7 @@ QRect QFbCursor::drawCursor(QPainter & painter)
return QRect();
mPrevRect = mCurrentRect;
- painter.drawImage(mPrevRect, *mGraphic->image());
+ painter.drawImage(mPrevRect, *mCursorImage->image());
mOnScreen = true;
return mPrevRect;
}
@@ -149,17 +149,17 @@ QRect QFbCursor::dirtyRect()
void QFbCursor::setCursor(Qt::CursorShape shape)
{
- mGraphic->set(shape);
+ mCursorImage->set(shape);
}
void QFbCursor::setCursor(const QImage &image, int hotx, int hoty)
{
- mGraphic->set(image, hotx, hoty);
+ mCursorImage->set(image, hotx, hoty);
}
void QFbCursor::setCursor(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY)
{
- mGraphic->set(data, mask, width, height, hotX, hotY);
+ mCursorImage->set(data, mask, width, height, hotX, hotY);
}
#ifndef QT_NO_CURSOR
diff --git a/src/platformsupport/fbconvenience/qfbcursor_p.h b/src/platformsupport/fbconvenience/qfbcursor_p.h
index f08babd45b..beda10a5f3 100644
--- a/src/platformsupport/fbconvenience/qfbcursor_p.h
+++ b/src/platformsupport/fbconvenience/qfbcursor_p.h
@@ -87,11 +87,11 @@ public:
virtual QRect drawCursor(QPainter &painter);
// input methods
- void pointerEvent(const QMouseEvent &event) Q_DECL_OVERRIDE;
- QPoint pos() const Q_DECL_OVERRIDE;
- void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
+ void pointerEvent(const QMouseEvent &event) override;
+ QPoint pos() const override;
+ void setPos(const QPoint &pos) override;
#ifndef QT_NO_CURSOR
- void changeCursor(QCursor *widgetCursor, QWindow *window) Q_DECL_OVERRIDE;
+ void changeCursor(QCursor *widgetCursor, QWindow *window) override;
#endif
virtual void setDirty();
@@ -113,7 +113,7 @@ private:
QRect mPrevRect; // last place the cursor was drawn
bool mDirty;
bool mOnScreen;
- QPlatformCursorImage *mGraphic;
+ QPlatformCursorImage *mCursorImage;
QFbCursorDeviceListener *mDeviceListener;
QPoint m_pos;
};
@@ -121,4 +121,3 @@ private:
QT_END_NAMESPACE
#endif // QFBCURSOR_P_H
-
diff --git a/src/platformsupport/fbconvenience/qfbscreen.cpp b/src/platformsupport/fbconvenience/qfbscreen.cpp
index 216f2722a4..2b4498157c 100644
--- a/src/platformsupport/fbconvenience/qfbscreen.cpp
+++ b/src/platformsupport/fbconvenience/qfbscreen.cpp
@@ -51,19 +51,23 @@
QT_BEGIN_NAMESPACE
-QFbScreen::QFbScreen() : mUpdatePending(false), mCursor(0), mGeometry(), mDepth(16), mFormat(QImage::Format_RGB16), mScreenImage(0), mCompositePainter(0), mIsUpToDate(false)
+QFbScreen::QFbScreen()
+ : mUpdatePending(false),
+ mCursor(0),
+ mDepth(16),
+ mFormat(QImage::Format_RGB16),
+ mPainter(nullptr)
{
}
QFbScreen::~QFbScreen()
{
- delete mCompositePainter;
- delete mScreenImage;
+ delete mPainter;
}
void QFbScreen::initializeCompositor()
{
- mScreenImage = new QImage(mGeometry.size(), mFormat);
+ mScreenImage = QImage(mGeometry.size(), mFormat);
scheduleUpdate();
}
@@ -93,7 +97,6 @@ void QFbScreen::addWindow(QFbWindow *window)
}
}
}
- invalidateRectCache();
setDirty(window->geometry());
QWindow *w = topWindow();
QWindowSystemInterface::handleWindowActivated(w);
@@ -103,7 +106,6 @@ void QFbScreen::addWindow(QFbWindow *window)
void QFbScreen::removeWindow(QFbWindow *window)
{
mWindowStack.removeOne(window);
- invalidateRectCache();
setDirty(window->geometry());
QWindow *w = topWindow();
QWindowSystemInterface::handleWindowActivated(w);
@@ -116,7 +118,6 @@ void QFbScreen::raise(QFbWindow *window)
if (index <= 0)
return;
mWindowStack.move(index, 0);
- invalidateRectCache();
setDirty(window->geometry());
QWindow *w = topWindow();
QWindowSystemInterface::handleWindowActivated(w);
@@ -129,7 +130,6 @@ void QFbScreen::lower(QFbWindow *window)
if (index == -1 || index == (mWindowStack.size() - 1))
return;
mWindowStack.move(index, mWindowStack.size() - 1);
- invalidateRectCache();
setDirty(window->geometry());
QWindow *w = topWindow();
QWindowSystemInterface::handleWindowActivated(w);
@@ -142,7 +142,7 @@ QWindow *QFbScreen::topWindow() const
if (fbw->window()->type() == Qt::Window || fbw->window()->type() == Qt::Dialog)
return fbw->window();
}
- return 0;
+ return nullptr;
}
QWindow *QFbScreen::topLevelAt(const QPoint & p) const
@@ -151,14 +151,19 @@ QWindow *QFbScreen::topLevelAt(const QPoint & p) const
if (fbw->geometry().contains(p, false) && fbw->window()->isVisible())
return fbw->window();
}
- return 0;
+ return nullptr;
+}
+
+int QFbScreen::windowCount() const
+{
+ return mWindowStack.count();
}
void QFbScreen::setDirty(const QRect &rect)
{
- QRect intersection = rect.intersected(mGeometry);
- QPoint screenOffset = mGeometry.topLeft();
- mRepaintRegion += intersection.translated(-screenOffset); // global to local translation
+ const QRect intersection = rect.intersected(mGeometry);
+ const QPoint screenOffset = mGeometry.topLeft();
+ mRepaintRegion += intersection.translated(-screenOffset); // global to local translation
scheduleUpdate();
}
@@ -177,141 +182,81 @@ void QFbScreen::setPhysicalSize(const QSize &size)
void QFbScreen::setGeometry(const QRect &rect)
{
- delete mCompositePainter;
- mCompositePainter = 0;
- delete mScreenImage;
+ delete mPainter;
+ mPainter = nullptr;
mGeometry = rect;
- mScreenImage = new QImage(mGeometry.size(), mFormat);
- invalidateRectCache();
+ mScreenImage = QImage(mGeometry.size(), mFormat);
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
resizeMaximizedWindows();
}
-void QFbScreen::generateRects()
+bool QFbScreen::initialize()
{
- mCachedRects.clear();
- QPoint screenOffset = mGeometry.topLeft();
- QRegion remainingScreen(mGeometry.translated(-screenOffset)); // global to local translation
-
- for (int i = 0; i < mWindowStack.length(); i++) {
- if (remainingScreen.isEmpty())
- break;
-#if 0
- if (!mWindowStack[i]->isVisible())
- continue;
- if (mWindowStack[i]->isMinimized())
- continue;
-
- if (!mWindowStack[i]->testAttribute(Qt::WA_TranslucentBackground)) {
- QRect localGeometry = mWindowStack.at(i)->geometry().translated(-screenOffset); // global to local translation
- remainingScreen -= localGeometry;
- QRegion windowRegion(localGeometry);
- windowRegion -= remainingScreen;
- for (const QRect &rect : windowRegion)
- mCachedRects += QPair<QRect, int>(rect, i);
- }
-#endif
- }
- mCachedRects.reserve(mCachedRects.count() + remainingScreen.rectCount());
- for (const QRect &rect : remainingScreen)
- mCachedRects += QPair<QRect, int>(rect, -1);
- mIsUpToDate = true;
+ return true;
}
QRegion QFbScreen::doRedraw()
{
- QPoint screenOffset = mGeometry.topLeft();
+ const QPoint screenOffset = mGeometry.topLeft();
QRegion touchedRegion;
if (mCursor && mCursor->isDirty() && mCursor->isOnScreen()) {
- QRect lastCursor = mCursor->dirtyRect();
+ const QRect lastCursor = mCursor->dirtyRect();
mRepaintRegion += lastCursor;
}
- if (mRepaintRegion.isEmpty() && (!mCursor || !mCursor->isDirty())) {
+ if (mRepaintRegion.isEmpty() && (!mCursor || !mCursor->isDirty()))
return touchedRegion;
- }
- QVector<QRect> rects = mRepaintRegion.rects();
-
- if (!mIsUpToDate)
- generateRects();
-
- if (!mCompositePainter)
- mCompositePainter = new QPainter(mScreenImage);
+ if (!mPainter)
+ mPainter = new QPainter(&mScreenImage);
+ const QVector<QRect> rects = mRepaintRegion.rects();
+ const QRect screenRect = mGeometry.translated(-screenOffset);
for (int rectIndex = 0; rectIndex < mRepaintRegion.rectCount(); rectIndex++) {
- QRegion rectRegion = rects[rectIndex];
+ const QRect rect = rects[rectIndex].intersected(screenRect);
+ if (rect.isEmpty())
+ continue;
- for (int i = 0; i < mCachedRects.length(); i++) {
- QRect screenSubRect = mCachedRects[i].first;
- int layer = mCachedRects[i].second;
- QRegion intersect = rectRegion.intersected(screenSubRect);
+ mPainter->setCompositionMode(QPainter::CompositionMode_Source);
+ mPainter->fillRect(rect, mScreenImage.hasAlphaChannel() ? Qt::transparent : Qt::black);
- if (intersect.isEmpty())
+ for (int layerIndex = mWindowStack.size() - 1; layerIndex != -1; layerIndex--) {
+ if (!mWindowStack[layerIndex]->window()->isVisible())
continue;
- rectRegion -= intersect;
-
- // we only expect one rectangle, but defensive coding...
- for (const QRect &rect : intersect) {
- bool firstLayer = true;
- if (layer == -1) {
- mCompositePainter->setCompositionMode(QPainter::CompositionMode_Source);
- mCompositePainter->fillRect(rect, mScreenImage->hasAlphaChannel() ? Qt::transparent : Qt::black);
- firstLayer = false;
- layer = mWindowStack.size() - 1;
- }
-
- for (int layerIndex = layer; layerIndex != -1; layerIndex--) {
- if (!mWindowStack[layerIndex]->window()->isVisible())
- continue;
- // if (mWindowStack[layerIndex]->isMinimized())
- // continue;
-
- QRect windowRect = mWindowStack[layerIndex]->geometry().translated(-screenOffset);
- QRect windowIntersect = rect.translated(-windowRect.left(),
- -windowRect.top());
-
-
- QFbBackingStore *backingStore = mWindowStack[layerIndex]->backingStore();
-
- if (backingStore) {
- backingStore->lock();
- mCompositePainter->drawImage(rect, backingStore->image(), windowIntersect);
- backingStore->unlock();
- }
- if (firstLayer) {
- firstLayer = false;
- }
- }
+ const QRect windowRect = mWindowStack[layerIndex]->geometry().translated(-screenOffset);
+ const QRect windowIntersect = rect.translated(-windowRect.left(), -windowRect.top());
+ QFbBackingStore *backingStore = mWindowStack[layerIndex]->backingStore();
+ if (backingStore) {
+ backingStore->lock();
+ mPainter->drawImage(rect, backingStore->image(), windowIntersect);
+ backingStore->unlock();
}
}
}
- QRect cursorRect;
if (mCursor && (mCursor->isDirty() || mRepaintRegion.intersects(mCursor->lastPainted()))) {
- mCompositePainter->setCompositionMode(QPainter::CompositionMode_SourceOver);
- cursorRect = mCursor->drawCursor(*mCompositePainter);
- touchedRegion += cursorRect;
+ mPainter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+ touchedRegion += mCursor->drawCursor(*mPainter);
}
touchedRegion += mRepaintRegion;
mRepaintRegion = QRegion();
-
-
-// qDebug() << "QFbScreen::doRedraw" << mWindowStack.size() << mScreenImage->size() << touchedRegion;
-
return touchedRegion;
}
QFbWindow *QFbScreen::windowForId(WId wid) const
{
- for (int i = 0; i < mWindowStack.count(); ++i)
+ for (int i = 0; i < mWindowStack.count(); ++i) {
if (mWindowStack[i]->winId() == wid)
return mWindowStack[i];
+ }
+ return nullptr;
+}
+QFbScreen::Flags QFbScreen::flags() const
+{
return 0;
}
QT_END_NAMESPACE
-
diff --git a/src/platformsupport/fbconvenience/qfbscreen_p.h b/src/platformsupport/fbconvenience/qfbscreen_p.h
index e9b570aa1c..1c27a941cc 100644
--- a/src/platformsupport/fbconvenience/qfbscreen_p.h
+++ b/src/platformsupport/fbconvenience/qfbscreen_p.h
@@ -66,10 +66,18 @@ class QFbBackingStore;
class QFbScreen : public QObject, public QPlatformScreen
{
Q_OBJECT
+
public:
+ enum Flag {
+ DontForceFirstWindowToFullScreen = 0x01
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
QFbScreen();
~QFbScreen();
+ virtual bool initialize();
+
QRect geometry() const Q_DECL_OVERRIDE { return mGeometry; }
int depth() const Q_DECL_OVERRIDE { return mDepth; }
QImage::Format format() const Q_DECL_OVERRIDE { return mFormat; }
@@ -85,6 +93,8 @@ public:
virtual void raise(QFbWindow *window);
virtual void lower(QFbWindow *window);
virtual void topWindowChanged(QWindow *) {}
+ virtual int windowCount() const;
+ virtual Flags flags() const;
void addPendingBackingStore(QFbBackingStore *bs) { mPendingBackingStores << bs; }
@@ -112,20 +122,17 @@ protected:
int mDepth;
QImage::Format mFormat;
QSizeF mPhysicalSize;
- QImage *mScreenImage;
+ QImage mScreenImage;
private:
- void invalidateRectCache() { mIsUpToDate = false; }
- void generateRects();
-
- QPainter *mCompositePainter;
- QVector<QPair<QRect, int> > mCachedRects;
+ QPainter *mPainter;
QList<QFbBackingStore*> mPendingBackingStores;
friend class QFbWindow;
- bool mIsUpToDate;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QFbScreen::Flags)
+
QT_END_NAMESPACE
#endif // QFBSCREEN_P_H
diff --git a/src/platformsupport/fbconvenience/qfbwindow.cpp b/src/platformsupport/fbconvenience/qfbwindow.cpp
index 2d5570fe5d..0be1dad04a 100644
--- a/src/platformsupport/fbconvenience/qfbwindow.cpp
+++ b/src/platformsupport/fbconvenience/qfbwindow.cpp
@@ -66,7 +66,6 @@ void QFbWindow::setGeometry(const QRect &rect)
// store previous geometry for screen update
mOldGeometry = geometry();
- platformScreen()->invalidateRectCache();
QWindowSystemInterface::handleGeometryChange(window(), rect);
QPlatformWindow::setGeometry(rect);
@@ -74,8 +73,13 @@ void QFbWindow::setGeometry(const QRect &rect)
void QFbWindow::setVisible(bool visible)
{
+ QFbScreen *fbScreen = platformScreen();
if (visible) {
- if (mWindowState & Qt::WindowFullScreen)
+ bool convOk = false;
+ static bool envDisableForceFullScreen = qEnvironmentVariableIntValue("QT_QPA_FB_FORCE_FULLSCREEN", &convOk) == 0 && convOk;
+ const bool platformDisableForceFullScreen = fbScreen->flags().testFlag(QFbScreen::DontForceFirstWindowToFullScreen);
+ const bool forceFullScreen = !envDisableForceFullScreen && !platformDisableForceFullScreen && fbScreen->windowCount() == 0;
+ if (forceFullScreen || (mWindowState & Qt::WindowFullScreen))
setGeometry(platformScreen()->geometry());
else if (mWindowState & Qt::WindowMaximized)
setGeometry(platformScreen()->availableGeometry());
@@ -83,9 +87,9 @@ void QFbWindow::setVisible(bool visible)
QPlatformWindow::setVisible(visible);
if (visible)
- platformScreen()->addWindow(this);
+ fbScreen->addWindow(this);
else
- platformScreen()->removeWindow(this);
+ fbScreen->removeWindow(this);
}
@@ -93,14 +97,11 @@ void QFbWindow::setWindowState(Qt::WindowState state)
{
QPlatformWindow::setWindowState(state);
mWindowState = state;
- platformScreen()->invalidateRectCache();
}
-
void QFbWindow::setWindowFlags(Qt::WindowFlags flags)
{
mWindowFlags = flags;
- platformScreen()->invalidateRectCache();
}
Qt::WindowFlags QFbWindow::windowFlags() const
@@ -120,20 +121,15 @@ void QFbWindow::lower()
void QFbWindow::repaint(const QRegion &region)
{
- QRect currentGeometry = geometry();
-
- QRect dirtyClient = region.boundingRect();
- QRect dirtyRegion(currentGeometry.left() + dirtyClient.left(),
- currentGeometry.top() + dirtyClient.top(),
- dirtyClient.width(),
- dirtyClient.height());
- QRect mOldGeometryLocal = mOldGeometry;
+ const QRect currentGeometry = geometry();
+ const QRect dirtyClient = region.boundingRect();
+ const QRect dirtyRegion = dirtyClient.translated(currentGeometry.topLeft());
+ const QRect oldGeometryLocal = mOldGeometry;
mOldGeometry = currentGeometry;
// If this is a move, redraw the previous location
- if (mOldGeometryLocal != currentGeometry)
- platformScreen()->setDirty(mOldGeometryLocal);
+ if (oldGeometryLocal != currentGeometry)
+ platformScreen()->setDirty(oldGeometryLocal);
platformScreen()->setDirty(dirtyRegion);
}
QT_END_NAMESPACE
-
diff --git a/src/platformsupport/fontdatabases/fontdatabases.pro b/src/platformsupport/fontdatabases/fontdatabases.pro
index 9376c3b702..49dead4668 100644
--- a/src/platformsupport/fontdatabases/fontdatabases.pro
+++ b/src/platformsupport/fontdatabases/fontdatabases.pro
@@ -7,7 +7,7 @@ CONFIG += static internal_module
DEFINES += QT_NO_CAST_FROM_ASCII
PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h
-darwin:!if(watchos:CONFIG(simulator, simulator|device)) {
+darwin {
include($$PWD/mac/coretext.pri)
} else {
qtConfig(freetype) {
diff --git a/src/platformsupport/fontdatabases/mac/coretext.pri b/src/platformsupport/fontdatabases/mac/coretext.pri
index 1caeb2c1ac..06f1971696 100644
--- a/src/platformsupport/fontdatabases/mac/coretext.pri
+++ b/src/platformsupport/fontdatabases/mac/coretext.pri
@@ -11,6 +11,21 @@ uikit: \
# On iOS/tvOS/watchOS CoreText and CoreGraphics are stand-alone frameworks
LIBS_PRIVATE += -framework CoreText -framework CoreGraphics
else: \
- # On Mac OS they are part of the ApplicationServices umbrella framework,
- # even in 10.8 where they were also made available stand-alone.
- LIBS_PRIVATE += -framework ApplicationServices
+ # On macOS they are re-exported by the AppKit framework
+ LIBS_PRIVATE += -framework AppKit
+
+# CoreText is documented to be available on watchOS, but the headers aren't present
+# in the watchOS Simulator SDK like they are supposed to be. Work around the problem
+# by adding the device SDK's headers to the search path as a fallback.
+# rdar://25314492, rdar://27844864
+watchos:simulator {
+ simulator_system_frameworks = $$xcodeSDKInfo(Path, $${simulator.sdk})/System/Library/Frameworks
+ device_system_frameworks = $$xcodeSDKInfo(Path, $${device.sdk})/System/Library/Frameworks
+ for (arch, QMAKE_APPLE_SIMULATOR_ARCHS) {
+ QMAKE_CXXFLAGS += \
+ -Xarch_$${arch} \
+ -F$$simulator_system_frameworks \
+ -Xarch_$${arch} \
+ -F$$device_system_frameworks
+ }
+}
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
index 1c615e06ed..a5779fc291 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
@@ -591,12 +591,7 @@ namespace {
*/
QWindowsFontEngineData::QWindowsFontEngineData()
- : clearTypeEnabled(false)
- , fontSmoothingGamma(QWindowsFontDatabase::fontSmoothingGamma())
-#if !defined(QT_NO_DIRECTWRITE)
- , directWriteFactory(0)
- , directWriteGdiInterop(0)
-#endif
+ : fontSmoothingGamma(QWindowsFontDatabase::fontSmoothingGamma())
{
// from qapplication_win.cpp
UINT result = 0;
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
index 325f522335..15172c09da 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
@@ -74,12 +74,12 @@ public:
uint pow_gamma[256];
- bool clearTypeEnabled;
+ bool clearTypeEnabled = false;
qreal fontSmoothingGamma;
- HDC hdc;
+ HDC hdc = 0;
#if !defined(QT_NO_DIRECTWRITE)
- IDWriteFactory *directWriteFactory;
- IDWriteGdiInterop *directWriteGdiInterop;
+ IDWriteFactory *directWriteFactory = nullptr;
+ IDWriteGdiInterop *directWriteGdiInterop = nullptr;
#endif
};
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
index 0cd473e020..2b7351d124 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
@@ -239,21 +239,9 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name,
: QFontEngine(Win),
m_fontEngineData(fontEngineData),
_name(name),
- hfont(0),
m_logfont(lf),
ttf(0),
- hasOutline(0),
- cmap(0),
- cmapSize(0),
- lbearing(SHRT_MIN),
- rbearing(SHRT_MIN),
- x_height(-1),
- synthesized_flags(-1),
- lineWidth(-1),
- widthCache(0),
- widthCacheSize(0),
- designAdvances(0),
- designAdvancesSize(0)
+ hasOutline(0)
{
qCDebug(lcQpaFonts) << __FUNCTION__ << name << lf.lfHeight;
hfont = CreateFontIndirect(&m_logfont);
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
index 709de7d11d..5119adc0eb 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
@@ -145,29 +145,29 @@ private:
const QString _name;
QString uniqueFamilyName;
- HFONT hfont;
+ HFONT hfont = 0;
const LOGFONT m_logfont;
uint ttf : 1;
uint hasOutline : 1;
uint hasUnreliableOutline : 1;
uint cffTable : 1;
TEXTMETRIC tm;
- const unsigned char *cmap;
- int cmapSize;
+ const unsigned char *cmap = nullptr;
+ int cmapSize = 0;
QByteArray cmapTable;
- mutable qreal lbearing;
- mutable qreal rbearing;
+ mutable qreal lbearing = SHRT_MIN;
+ mutable qreal rbearing = SHRT_MIN;
QFixed designToDevice;
- int unitsPerEm;
- QFixed x_height;
+ int unitsPerEm = 0;
+ QFixed x_height = -1;
FaceId _faceId;
- mutable int synthesized_flags;
- mutable QFixed lineWidth;
- mutable unsigned char *widthCache;
- mutable uint widthCacheSize;
- mutable QFixed *designAdvances;
- mutable int designAdvancesSize;
+ mutable int synthesized_flags = -1;
+ mutable QFixed lineWidth = -1;
+ mutable unsigned char *widthCache = nullptr;
+ mutable uint widthCacheSize = 0;
+ mutable QFixed *designAdvances = nullptr;
+ mutable int designAdvancesSize = 0;
};
class QWindowsMultiFontEngine : public QFontEngineMulti
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp
index 7022615511..f8fcff952a 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp
@@ -110,9 +110,7 @@ static inline HBITMAP createDIB(HDC hdc, int width, int height,
QWindowsNativeImage::QWindowsNativeImage(int width, int height,
QImage::Format format) :
- m_hdc(createDC()),
- m_bitmap(0),
- m_null_bitmap(0)
+ m_hdc(createDC())
{
if (width != 0 && height != 0) {
uchar *bits;
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h
index c27c0d1e98..6c47a527d2 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage_p.h
@@ -80,8 +80,8 @@ private:
const HDC m_hdc;
QImage m_image;
- HBITMAP m_bitmap;
- HBITMAP m_null_bitmap;
+ HBITMAP m_bitmap = 0;
+ HBITMAP m_null_bitmap = 0;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h
index bc0485232d..17bf0fb797 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h
@@ -52,7 +52,11 @@
//
#include "qnamespace.h"
+#ifdef Q_OS_FREEBSD
+#include <dev/evdev/input.h>
+#else
#include "linux/input.h"
+#endif
// no QT_BEGIN_NAMESPACE, since we include it internally...
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
index 0eb6fc0847..5c87cb7c9c 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
@@ -49,7 +49,11 @@
#include <qpa/qwindowsysteminterface.h>
#include <private/qcore_unix_p.h>
+#ifdef Q_OS_FREEBSD
+#include <dev/evdev/input.h>
+#else
#include <linux/input.h>
+#endif
QT_BEGIN_NAMESPACE
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
index d5ea04bee8..9b4bcf1575 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
@@ -53,8 +53,12 @@
#include <errno.h>
+#ifdef Q_OS_FREEBSD
+#include <dev/evdev/input.h>
+#else
#include <linux/kd.h>
#include <linux/input.h>
+#endif
#define TEST_BIT(array, bit) (array[bit/8] & (1<<(bit%8)))
diff --git a/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp b/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp
index dc03daedda..86f8a00b13 100644
--- a/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp
+++ b/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp
@@ -45,7 +45,11 @@
#include <QLoggingCategory>
#include <QtCore/private/qcore_unix_p.h>
#include <qpa/qwindowsysteminterface.h>
+#ifdef Q_OS_FREEBSD
+#include <dev/evdev/input.h>
+#else
#include <linux/input.h>
+#endif
QT_BEGIN_NAMESPACE
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
index d53a317fc5..6870fd3dde 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
@@ -48,7 +48,11 @@
#include <QtCore/private/qcore_unix_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/private/qguiapplication_p.h>
+#ifdef Q_OS_FREEBSD
+#include <dev/evdev/input.h>
+#else
#include <linux/input.h>
+#endif
#if QT_CONFIG(mtdev)
extern "C" {
diff --git a/src/platformsupport/kmsconvenience/kmsconvenience.pro b/src/platformsupport/kmsconvenience/kmsconvenience.pro
new file mode 100644
index 0000000000..d0ff0d4efb
--- /dev/null
+++ b/src/platformsupport/kmsconvenience/kmsconvenience.pro
@@ -0,0 +1,20 @@
+TARGET = QtKmsSupport
+MODULE = kms_support
+
+QT = core-private gui-private
+CONFIG += static internal_module
+
+DEFINES += QT_NO_CAST_FROM_ASCII
+PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h
+
+HEADERS +=
+ qkmsdevice_p.h
+
+SOURCES += \
+ qkmsdevice.cpp
+
+QMAKE_USE += drm
+
+LIBS_PRIVATE += $$QMAKE_LIBS_DYNLOAD
+
+load(qt_module)
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
new file mode 100644
index 0000000000..319c7f3d9b
--- /dev/null
+++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
@@ -0,0 +1,651 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkmsdevice_p.h"
+
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonObject>
+#include <QtCore/QJsonArray>
+#include <QtCore/QFile>
+#include <QtCore/QLoggingCategory>
+
+#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(qLcKmsDebug, "qt.qpa.eglfs.kms")
+
+enum OutputConfiguration {
+ OutputConfigOff,
+ OutputConfigPreferred,
+ OutputConfigCurrent,
+ OutputConfigMode,
+ OutputConfigModeline
+};
+
+int QKmsDevice::crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector)
+{
+ for (int i = 0; i < connector->count_encoders; i++) {
+ drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->encoders[i]);
+ if (!encoder) {
+ qWarning("Failed to get encoder");
+ continue;
+ }
+
+ quint32 possibleCrtcs = encoder->possible_crtcs;
+ drmModeFreeEncoder(encoder);
+
+ for (int j = 0; j < resources->count_crtcs; j++) {
+ bool isPossible = possibleCrtcs & (1 << j);
+ bool isAvailable = !(m_crtc_allocator & 1 << resources->crtcs[j]);
+
+ if (isPossible && isAvailable)
+ return j;
+ }
+ }
+
+ return -1;
+}
+
+static const char * const connector_type_names[] = { // must match DRM_MODE_CONNECTOR_*
+ "None",
+ "VGA",
+ "DVI",
+ "DVI",
+ "DVI",
+ "Composite",
+ "TV",
+ "LVDS",
+ "CTV",
+ "DIN",
+ "DP",
+ "HDMI",
+ "HDMI",
+ "TV",
+ "eDP",
+ "Virtual",
+ "DSI"
+};
+
+static QByteArray nameForConnector(const drmModeConnectorPtr connector)
+{
+ QByteArray connectorName("UNKNOWN");
+
+ if (connector->connector_type < ARRAY_LENGTH(connector_type_names))
+ connectorName = connector_type_names[connector->connector_type];
+
+ connectorName += QByteArray::number(connector->connector_type_id);
+
+ return connectorName;
+}
+
+static bool parseModeline(const QByteArray &text, drmModeModeInfoPtr mode)
+{
+ char hsync[16];
+ char vsync[16];
+ float fclock;
+
+ mode->type = DRM_MODE_TYPE_USERDEF;
+ mode->hskew = 0;
+ mode->vscan = 0;
+ mode->vrefresh = 0;
+ mode->flags = 0;
+
+ if (sscanf(text.constData(), "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s",
+ &fclock,
+ &mode->hdisplay,
+ &mode->hsync_start,
+ &mode->hsync_end,
+ &mode->htotal,
+ &mode->vdisplay,
+ &mode->vsync_start,
+ &mode->vsync_end,
+ &mode->vtotal, hsync, vsync) != 11)
+ return false;
+
+ mode->clock = fclock * 1000;
+
+ if (strcmp(hsync, "+hsync") == 0)
+ mode->flags |= DRM_MODE_FLAG_PHSYNC;
+ else if (strcmp(hsync, "-hsync") == 0)
+ mode->flags |= DRM_MODE_FLAG_NHSYNC;
+ else
+ return false;
+
+ if (strcmp(vsync, "+vsync") == 0)
+ mode->flags |= DRM_MODE_FLAG_PVSYNC;
+ else if (strcmp(vsync, "-vsync") == 0)
+ mode->flags |= DRM_MODE_FLAG_NVSYNC;
+ else
+ return false;
+
+ return true;
+}
+
+QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
+ drmModeConnectorPtr connector,
+ VirtualDesktopInfo *vinfo)
+{
+ const QByteArray connectorName = nameForConnector(connector);
+
+ const int crtc = crtcForConnector(resources, connector);
+ if (crtc < 0) {
+ qWarning() << "No usable crtc/encoder pair for connector" << connectorName;
+ return Q_NULLPTR;
+ }
+
+ OutputConfiguration configuration;
+ QSize configurationSize;
+ drmModeModeInfo configurationModeline;
+
+ auto userConfig = m_screenConfig->outputSettings();
+ auto userConnectorConfig = userConfig.value(QString::fromUtf8(connectorName));
+ // default to the preferred mode unless overridden in the config
+ const QByteArray mode = userConnectorConfig.value(QStringLiteral("mode"), QStringLiteral("preferred"))
+ .toByteArray().toLower();
+ if (mode == "off") {
+ configuration = OutputConfigOff;
+ } else if (mode == "preferred") {
+ configuration = OutputConfigPreferred;
+ } else if (mode == "current") {
+ configuration = OutputConfigCurrent;
+ } else if (sscanf(mode.constData(), "%dx%d", &configurationSize.rwidth(), &configurationSize.rheight()) == 2) {
+ configuration = OutputConfigMode;
+ } else if (parseModeline(mode, &configurationModeline)) {
+ configuration = OutputConfigModeline;
+ } else {
+ qWarning("Invalid mode \"%s\" for output %s", mode.constData(), connectorName.constData());
+ configuration = OutputConfigPreferred;
+ }
+ if (vinfo) {
+ *vinfo = VirtualDesktopInfo();
+ vinfo->virtualIndex = userConnectorConfig.value(QStringLiteral("virtualIndex"), INT_MAX).toInt();
+ if (userConnectorConfig.contains(QStringLiteral("virtualPos"))) {
+ const QByteArray vpos = userConnectorConfig.value(QStringLiteral("virtualPos")).toByteArray();
+ const QByteArrayList vposComp = vpos.split(',');
+ if (vposComp.count() == 2)
+ vinfo->virtualPos = QPoint(vposComp[0].trimmed().toInt(), vposComp[1].trimmed().toInt());
+ }
+ }
+
+ const uint32_t crtc_id = resources->crtcs[crtc];
+
+ if (configuration == OutputConfigOff) {
+ qCDebug(qLcKmsDebug) << "Turning off output" << connectorName;
+ drmModeSetCrtc(m_dri_fd, crtc_id, 0, 0, 0, 0, 0, Q_NULLPTR);
+ return Q_NULLPTR;
+ }
+
+ // Skip disconnected output
+ if (configuration == OutputConfigPreferred && connector->connection == DRM_MODE_DISCONNECTED) {
+ qCDebug(qLcKmsDebug) << "Skipping disconnected output" << connectorName;
+ return Q_NULLPTR;
+ }
+
+ // Get the current mode on the current crtc
+ drmModeModeInfo crtc_mode;
+ memset(&crtc_mode, 0, sizeof crtc_mode);
+ if (drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->connector_id)) {
+ drmModeCrtcPtr crtc = drmModeGetCrtc(m_dri_fd, encoder->crtc_id);
+ drmModeFreeEncoder(encoder);
+
+ if (!crtc)
+ return Q_NULLPTR;
+
+ if (crtc->mode_valid)
+ crtc_mode = crtc->mode;
+
+ drmModeFreeCrtc(crtc);
+ }
+
+ QList<drmModeModeInfo> modes;
+ modes.reserve(connector->count_modes);
+ qCDebug(qLcKmsDebug) << connectorName << "mode count:" << connector->count_modes;
+ for (int i = 0; i < connector->count_modes; i++) {
+ const drmModeModeInfo &mode = connector->modes[i];
+ qCDebug(qLcKmsDebug) << "mode" << i << mode.hdisplay << "x" << mode.vdisplay
+ << '@' << mode.vrefresh << "hz";
+ modes << connector->modes[i];
+ }
+
+ int preferred = -1;
+ int current = -1;
+ int configured = -1;
+ int best = -1;
+
+ for (int i = modes.size() - 1; i >= 0; i--) {
+ const drmModeModeInfo &m = modes.at(i);
+
+ if (configuration == OutputConfigMode &&
+ m.hdisplay == configurationSize.width() &&
+ m.vdisplay == configurationSize.height()) {
+ configured = i;
+ }
+
+ if (!memcmp(&crtc_mode, &m, sizeof m))
+ current = i;
+
+ if (m.type & DRM_MODE_TYPE_PREFERRED)
+ preferred = i;
+
+ best = i;
+ }
+
+ if (configuration == OutputConfigModeline) {
+ modes << configurationModeline;
+ configured = modes.size() - 1;
+ }
+
+ if (current < 0 && crtc_mode.clock != 0) {
+ modes << crtc_mode;
+ current = mode.size() - 1;
+ }
+
+ if (configuration == OutputConfigCurrent)
+ configured = current;
+
+ int selected_mode = -1;
+
+ if (configured >= 0)
+ selected_mode = configured;
+ else if (preferred >= 0)
+ selected_mode = preferred;
+ else if (current >= 0)
+ selected_mode = current;
+ else if (best >= 0)
+ selected_mode = best;
+
+ if (selected_mode < 0) {
+ qWarning() << "No modes available for output" << connectorName;
+ return Q_NULLPTR;
+ } else {
+ int width = modes[selected_mode].hdisplay;
+ int height = modes[selected_mode].vdisplay;
+ int refresh = modes[selected_mode].vrefresh;
+ qCDebug(qLcKmsDebug) << "Selected mode" << selected_mode << ":" << width << "x" << height
+ << '@' << refresh << "hz for output" << connectorName;
+ }
+
+ // physical size from connector < config values < env vars
+ int pwidth = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_WIDTH");
+ if (!pwidth)
+ pwidth = qEnvironmentVariableIntValue("QT_QPA_PHYSICAL_WIDTH");
+ int pheight = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_HEIGHT");
+ if (!pheight)
+ pheight = qEnvironmentVariableIntValue("QT_QPA_PHYSICAL_HEIGHT");
+ QSizeF physSize(pwidth, pheight);
+ if (physSize.isEmpty()) {
+ physSize = QSize(userConnectorConfig.value(QStringLiteral("physicalWidth")).toInt(),
+ userConnectorConfig.value(QStringLiteral("physicalHeight")).toInt());
+ if (physSize.isEmpty()) {
+ physSize.setWidth(connector->mmWidth);
+ physSize.setHeight(connector->mmHeight);
+ }
+ }
+ qCDebug(qLcKmsDebug) << "Physical size is" << physSize << "mm" << "for output" << connectorName;
+
+ QKmsOutput output = {
+ QString::fromUtf8(connectorName),
+ connector->connector_id,
+ crtc_id,
+ physSize,
+ selected_mode,
+ false,
+ drmModeGetCrtc(m_dri_fd, crtc_id),
+ modes,
+ connector->subpixel,
+ connectorProperty(connector, QByteArrayLiteral("DPMS")),
+ false,
+ 0,
+ false
+ };
+
+ bool ok;
+ int idx = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_PLANE_INDEX", &ok);
+ if (ok) {
+ drmModePlaneRes *planeResources = drmModeGetPlaneResources(m_dri_fd);
+ if (planeResources) {
+ if (idx >= 0 && idx < int(planeResources->count_planes)) {
+ drmModePlane *plane = drmModeGetPlane(m_dri_fd, planeResources->planes[idx]);
+ if (plane) {
+ output.wants_plane = true;
+ output.plane_id = plane->plane_id;
+ qCDebug(qLcKmsDebug, "Forcing plane index %d, plane id %u (belongs to crtc id %u)",
+ idx, plane->plane_id, plane->crtc_id);
+ drmModeFreePlane(plane);
+ }
+ } else {
+ qWarning("Invalid plane index %d, must be between 0 and %u", idx, planeResources->count_planes - 1);
+ }
+ }
+ }
+
+ m_crtc_allocator |= (1 << output.crtc_id);
+ m_connector_allocator |= (1 << output.connector_id);
+
+ return createScreen(output);
+}
+
+drmModePropertyPtr QKmsDevice::connectorProperty(drmModeConnectorPtr connector, const QByteArray &name)
+{
+ drmModePropertyPtr prop;
+
+ for (int i = 0; i < connector->count_props; i++) {
+ prop = drmModeGetProperty(m_dri_fd, connector->props[i]);
+ if (!prop)
+ continue;
+ if (strcmp(prop->name, name.constData()) == 0)
+ return prop;
+ drmModeFreeProperty(prop);
+ }
+
+ return Q_NULLPTR;
+}
+
+QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path)
+ : m_screenConfig(screenConfig)
+ , m_path(path)
+ , m_dri_fd(-1)
+ , m_crtc_allocator(0)
+ , m_connector_allocator(0)
+{
+ if (m_path.isEmpty()) {
+ m_path = m_screenConfig->devicePath();
+ qCDebug(qLcKmsDebug, "Using DRM device %s specified in config file", qPrintable(m_path));
+ if (m_path.isEmpty())
+ qFatal("No DRM device given");
+ } else {
+ qCDebug(qLcKmsDebug, "Using backend-provided DRM device %s", qPrintable(m_path));
+ }
+}
+
+QKmsDevice::~QKmsDevice()
+{
+}
+
+struct OrderedScreen
+{
+ OrderedScreen() : screen(nullptr) { }
+ OrderedScreen(QPlatformScreen *screen, const QKmsDevice::VirtualDesktopInfo &vinfo)
+ : screen(screen), vinfo(vinfo) { }
+ QPlatformScreen *screen;
+ QKmsDevice::VirtualDesktopInfo vinfo;
+};
+
+QDebug operator<<(QDebug dbg, const OrderedScreen &s)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "OrderedScreen(" << s.screen << " : " << s.vinfo.virtualIndex
+ << " / " << s.vinfo.virtualPos << ")";
+ return dbg;
+}
+
+static bool orderedScreenLessThan(const OrderedScreen &a, const OrderedScreen &b)
+{
+ return a.vinfo.virtualIndex < b.vinfo.virtualIndex;
+}
+
+void QKmsDevice::createScreens()
+{
+ drmModeResPtr resources = drmModeGetResources(m_dri_fd);
+ if (!resources) {
+ qWarning("drmModeGetResources failed");
+ return;
+ }
+
+ QVector<OrderedScreen> screens;
+
+ int wantedConnectorIndex = -1;
+ bool ok;
+ int idx = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_CONNECTOR_INDEX", &ok);
+ if (ok) {
+ if (idx >= 0 && idx < resources->count_connectors)
+ wantedConnectorIndex = idx;
+ else
+ qWarning("Invalid connector index %d, must be between 0 and %u", idx, resources->count_connectors - 1);
+ }
+
+ for (int i = 0; i < resources->count_connectors; i++) {
+ if (wantedConnectorIndex >= 0 && i != wantedConnectorIndex)
+ continue;
+
+ drmModeConnectorPtr connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]);
+ if (!connector)
+ continue;
+
+ VirtualDesktopInfo vinfo;
+ QPlatformScreen *screen = createScreenForConnector(resources, connector, &vinfo);
+ if (screen)
+ screens.append(OrderedScreen(screen, vinfo));
+
+ drmModeFreeConnector(connector);
+ }
+
+ drmModeFreeResources(resources);
+
+ // Use stable sort to preserve the original order for outputs with unspecified indices.
+ std::stable_sort(screens.begin(), screens.end(), orderedScreenLessThan);
+ qCDebug(qLcKmsDebug) << "Sorted screen list:" << screens;
+
+ QPoint pos(0, 0);
+ QList<QPlatformScreen *> siblings;
+ QVector<QPoint> virtualPositions;
+
+ for (const OrderedScreen &orderedScreen : screens) {
+ QPlatformScreen *s = orderedScreen.screen;
+ QPoint virtualPos(0, 0);
+ // set up a horizontal or vertical virtual desktop
+ if (orderedScreen.vinfo.virtualPos.isNull()) {
+ virtualPos = pos;
+ if (m_screenConfig->virtualDesktopLayout() == QKmsScreenConfig::VirtualDesktopLayoutVertical)
+ pos.ry() += s->geometry().height();
+ else
+ pos.rx() += s->geometry().width();
+ } else {
+ virtualPos = orderedScreen.vinfo.virtualPos;
+ }
+ qCDebug(qLcKmsDebug) << "Adding screen" << s << "to QPA with geometry" << s->geometry();
+ // The order in qguiapp's screens list will match the order set by
+ // virtualIndex. This is not only handy but also required since for instance
+ // evdevtouch relies on it when performing touch device - screen mapping.
+ if (!m_screenConfig->separateScreens()) {
+ siblings.append(s);
+ virtualPositions.append(virtualPos);
+ } else {
+ registerScreen(s, virtualPos, QList<QPlatformScreen *>() << s);
+ }
+ }
+
+ if (!m_screenConfig->separateScreens()) {
+ // enable the virtual desktop
+ for (int i = 0; i < siblings.count(); ++i)
+ registerScreen(siblings[i], virtualPositions[i], siblings);
+ }
+}
+
+int QKmsDevice::fd() const
+{
+ return m_dri_fd;
+}
+
+QString QKmsDevice::devicePath() const
+{
+ return m_path;
+}
+
+void QKmsDevice::setFd(int fd)
+{
+ m_dri_fd = fd;
+}
+
+QKmsScreenConfig *QKmsDevice::screenConfig() const
+{
+ return m_screenConfig;
+}
+
+QKmsScreenConfig::QKmsScreenConfig()
+ : m_hwCursor(true)
+ , m_separateScreens(false)
+ , m_pbuffers(false)
+ , m_virtualDesktopLayout(VirtualDesktopLayoutHorizontal)
+{
+ loadConfig();
+}
+
+void QKmsScreenConfig::loadConfig()
+{
+ QByteArray json = qgetenv("QT_QPA_EGLFS_KMS_CONFIG");
+ if (json.isEmpty()) {
+ json = qgetenv("QT_QPA_KMS_CONFIG");
+ if (json.isEmpty())
+ return;
+ }
+
+ qCDebug(qLcKmsDebug) << "Loading KMS setup from" << json;
+
+ QFile file(QString::fromUtf8(json));
+ if (!file.open(QFile::ReadOnly)) {
+ qCWarning(qLcKmsDebug) << "Could not open config file"
+ << json << "for reading";
+ return;
+ }
+
+ const QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
+ if (!doc.isObject()) {
+ qCWarning(qLcKmsDebug) << "Invalid config file" << json
+ << "- no top-level JSON object";
+ return;
+ }
+
+ const QJsonObject object = doc.object();
+
+ m_hwCursor = object.value(QLatin1String("hwcursor")).toBool(m_hwCursor);
+ m_pbuffers = object.value(QLatin1String("pbuffers")).toBool(m_pbuffers);
+ m_devicePath = object.value(QLatin1String("device")).toString();
+ m_separateScreens = object.value(QLatin1String("separateScreens")).toBool(m_separateScreens);
+
+ const QString vdOriString = object.value(QLatin1String("virtualDesktopLayout")).toString();
+ if (!vdOriString.isEmpty()) {
+ if (vdOriString == QLatin1String("horizontal"))
+ m_virtualDesktopLayout = VirtualDesktopLayoutHorizontal;
+ else if (vdOriString == QLatin1String("vertical"))
+ m_virtualDesktopLayout = VirtualDesktopLayoutVertical;
+ else
+ qCWarning(qLcKmsDebug) << "Unknown virtualDesktopOrientation value" << vdOriString;
+ }
+
+ const QJsonArray outputs = object.value(QLatin1String("outputs")).toArray();
+ for (int i = 0; i < outputs.size(); i++) {
+ const QVariantMap outputSettings = outputs.at(i).toObject().toVariantMap();
+
+ if (outputSettings.contains(QStringLiteral("name"))) {
+ const QString name = outputSettings.value(QStringLiteral("name")).toString();
+
+ if (m_outputSettings.contains(name)) {
+ qCDebug(qLcKmsDebug) << "Output" << name << "configured multiple times!";
+ }
+
+ m_outputSettings.insert(name, outputSettings);
+ }
+ }
+
+ qCDebug(qLcKmsDebug) << "Requested configuration (some settings may be ignored):\n"
+ << "\thwcursor:" << m_hwCursor << "\n"
+ << "\tpbuffers:" << m_pbuffers << "\n"
+ << "\tseparateScreens:" << m_separateScreens << "\n"
+ << "\tvirtualDesktopLayout:" << m_virtualDesktopLayout << "\n"
+ << "\toutputs:" << m_outputSettings;
+}
+
+void QKmsOutput::restoreMode(QKmsDevice *device)
+{
+ if (mode_set && saved_crtc) {
+ drmModeSetCrtc(device->fd(),
+ saved_crtc->crtc_id,
+ saved_crtc->buffer_id,
+ 0, 0,
+ &connector_id, 1,
+ &saved_crtc->mode);
+ mode_set = false;
+ }
+}
+
+void QKmsOutput::cleanup(QKmsDevice *device)
+{
+ if (dpms_prop) {
+ drmModeFreeProperty(dpms_prop);
+ dpms_prop = nullptr;
+ }
+
+ restoreMode(device);
+
+ if (saved_crtc) {
+ drmModeFreeCrtc(saved_crtc);
+ saved_crtc = nullptr;
+ }
+}
+
+QPlatformScreen::SubpixelAntialiasingType QKmsOutput::subpixelAntialiasingTypeHint() const
+{
+ switch (subpixel) {
+ default:
+ case DRM_MODE_SUBPIXEL_UNKNOWN:
+ case DRM_MODE_SUBPIXEL_NONE:
+ return QPlatformScreen::Subpixel_None;
+ case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
+ return QPlatformScreen::Subpixel_RGB;
+ case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
+ return QPlatformScreen::Subpixel_BGR;
+ case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
+ return QPlatformScreen::Subpixel_VRGB;
+ case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
+ return QPlatformScreen::Subpixel_VBGR;
+ }
+}
+
+void QKmsOutput::setPowerState(QKmsDevice *device, QPlatformScreen::PowerState state)
+{
+ if (dpms_prop)
+ drmModeConnectorSetProperty(device->fd(), connector_id,
+ dpms_prop->prop_id, (int) state);
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice_p.h b/src/platformsupport/kmsconvenience/qkmsdevice_p.h
new file mode 100644
index 0000000000..c41448bc99
--- /dev/null
+++ b/src/platformsupport/kmsconvenience/qkmsdevice_p.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Pelagicore AG
+** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKMSDEVICE_P_H
+#define QKMSDEVICE_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 <qpa/qplatformscreen.h>
+#include <QtCore/QMap>
+#include <QtCore/QVariant>
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+QT_BEGIN_NAMESPACE
+
+class QKmsDevice;
+
+class QKmsScreenConfig
+{
+public:
+ enum VirtualDesktopLayout {
+ VirtualDesktopLayoutHorizontal,
+ VirtualDesktopLayoutVertical
+ };
+
+ QKmsScreenConfig();
+
+ QString devicePath() const { return m_devicePath; }
+
+ bool hwCursor() const { return m_hwCursor; }
+ bool separateScreens() const { return m_separateScreens; }
+ bool supportsPBuffers() const { return m_pbuffers; }
+ VirtualDesktopLayout virtualDesktopLayout() const { return m_virtualDesktopLayout; }
+
+ QMap<QString, QVariantMap> outputSettings() const { return m_outputSettings; }
+
+private:
+ void loadConfig();
+
+ QString m_devicePath;
+ bool m_hwCursor;
+ bool m_separateScreens;
+ bool m_pbuffers;
+ VirtualDesktopLayout m_virtualDesktopLayout;
+ QMap<QString, QVariantMap> m_outputSettings;
+};
+
+struct QKmsOutput
+{
+ QString name;
+ uint32_t connector_id;
+ uint32_t crtc_id;
+ QSizeF physical_size;
+ int mode; // index of selected mode in list below
+ bool mode_set;
+ drmModeCrtcPtr saved_crtc;
+ QList<drmModeModeInfo> modes;
+ int subpixel;
+ drmModePropertyPtr dpms_prop;
+ bool wants_plane;
+ uint32_t plane_id;
+ bool plane_set;
+
+ void restoreMode(QKmsDevice *device);
+ void cleanup(QKmsDevice *device);
+ QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const;
+ void setPowerState(QKmsDevice *device, QPlatformScreen::PowerState state);
+};
+
+class QKmsDevice
+{
+public:
+ struct VirtualDesktopInfo {
+ VirtualDesktopInfo() : virtualIndex(0) { }
+ int virtualIndex;
+ QPoint virtualPos;
+ };
+
+ QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path = QString());
+ virtual ~QKmsDevice();
+
+ virtual bool open() = 0;
+ virtual void close() = 0;
+ virtual void *nativeDisplay() const = 0;
+
+ void createScreens();
+
+ int fd() const;
+ QString devicePath() const;
+
+ QKmsScreenConfig *screenConfig() const;
+
+protected:
+ virtual QPlatformScreen *createScreen(const QKmsOutput &output) = 0;
+ virtual void registerScreen(QPlatformScreen *screen,
+ const QPoint &virtualPos,
+ const QList<QPlatformScreen *> &virtualSiblings) = 0;
+
+ void setFd(int fd);
+ int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector);
+ QPlatformScreen *createScreenForConnector(drmModeResPtr resources,
+ drmModeConnectorPtr connector,
+ VirtualDesktopInfo *vinfo);
+ drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
+
+ QKmsScreenConfig *m_screenConfig;
+ QString m_path;
+ int m_dri_fd;
+
+ quint32 m_crtc_allocator;
+ quint32 m_connector_allocator;
+
+private:
+ Q_DISABLE_COPY(QKmsDevice)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro
index 09e2922505..7a97a12bae 100644
--- a/src/platformsupport/platformsupport.pro
+++ b/src/platformsupport/platformsupport.pro
@@ -7,7 +7,7 @@ SUBDIRS = \
fbconvenience \
themes
-qtConfig(freetype)|if(darwin:!if(watchos:CONFIG(simulator, simulator|device)))|win32: \
+qtConfig(freetype)|darwin|win32: \
SUBDIRS += fontdatabases
qtConfig(evdev)|qtConfig(tslib)|qtConfig(libinput) {
@@ -24,6 +24,8 @@ qtConfig(egl): \
SUBDIRS += eglconvenience
qtConfig(xlib):qtConfig(opengl):!qtConfig(opengles2): \
SUBDIRS += glxconvenience
+qtConfig(kms): \
+ SUBDIRS += kmsconvenience
qtConfig(accessibility) {
SUBDIRS += accessibility
diff --git a/src/plugins/platforms/bsdfb/qbsdfbscreen.cpp b/src/plugins/platforms/bsdfb/qbsdfbscreen.cpp
index 0ef57d37e5..03c6f0dbe9 100644
--- a/src/plugins/platforms/bsdfb/qbsdfbscreen.cpp
+++ b/src/plugins/platforms/bsdfb/qbsdfbscreen.cpp
@@ -243,7 +243,7 @@ QRegion QBsdFbScreen::doRedraw()
const auto rects = touched.rects();
for (const QRect &rect : rects)
- m_blitter->drawImage(rect, *mScreenImage, rect);
+ m_blitter->drawImage(rect, mScreenImage, rect);
return touched;
}
diff --git a/src/plugins/platforms/cocoa/qcocoaapplication.mm b/src/plugins/platforms/cocoa/qcocoaapplication.mm
index c5ae4bc2bf..3b950efa55 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplication.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplication.mm
@@ -76,6 +76,7 @@
#include "qcocoaintrospection.h"
#include "qcocoaapplicationdelegate.h"
#include "qcocoahelpers.h"
+#include "qcocoawindow.h"
#include <qguiapplication.h>
#include <qdebug.h>
@@ -148,6 +149,21 @@ static const QByteArray q_macLocalEventType = QByteArrayLiteral("mac_generic_NSE
@end
+static void qt_maybeSendKeyEquivalentUpEvent(NSEvent *event)
+{
+ // Cocoa is known for not sending key up events for key
+ // equivalents, regardless of whether it's an actual
+ // recognized key equivalent. We decide to force fate
+ // and forward the key event to the key (focus) window.
+ // However, non-Qt windows will not (and should not) get
+ // any special treatment, only QWindow-owned NSWindows.
+ if (event.type == NSKeyUp && (event.modifierFlags & NSCommandKeyMask)) {
+ NSWindow *targetWindow = event.window;
+ if ([targetWindow.class conformsToProtocol:@protocol(QNSWindowProtocol)])
+ [targetWindow sendEvent:event];
+ }
+}
+
@implementation QT_MANGLE_NAMESPACE(QNSApplication)
- (void)QT_MANGLE_NAMESPACE(qt_sendEvent_original):(NSEvent *)event
@@ -164,16 +180,20 @@ static const QByteArray q_macLocalEventType = QByteArrayLiteral("mac_generic_NSE
// be called instead of sendEvent if redirection occurs.
// 'self' will then be an instance of NSApplication
// (and not QNSApplication)
- if (![NSApp QT_MANGLE_NAMESPACE(qt_filterEvent):event])
+ if (![NSApp QT_MANGLE_NAMESPACE(qt_filterEvent):event]) {
[self QT_MANGLE_NAMESPACE(qt_sendEvent_original):event];
+ qt_maybeSendKeyEquivalentUpEvent(event);
+ }
}
- (void)sendEvent:(NSEvent *)event
{
// This method will be called if
// no redirection occurs
- if (![NSApp QT_MANGLE_NAMESPACE(qt_filterEvent):event])
+ if (![NSApp QT_MANGLE_NAMESPACE(qt_filterEvent):event]) {
[super sendEvent:event];
+ qt_maybeSendKeyEquivalentUpEvent(event);
+ }
}
@end
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index a74995319b..1d7ad772dc 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -57,7 +57,8 @@ QCocoaBackingStore::~QCocoaBackingStore()
QImage::Format QCocoaBackingStore::format() const
{
- if (static_cast<QCocoaWindow *>(window()->handle())->m_drawContentBorderGradient)
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle());
+ if (cocoaWindow && cocoaWindow->m_drawContentBorderGradient)
return QImage::Format_ARGB32_Premultiplied;
return QRasterBackingStore::format();
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm
index 7d11023b78..de4fa95530 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.mm
+++ b/src/plugins/platforms/cocoa/qcocoadrag.mm
@@ -132,7 +132,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o)
QPixmap pm = dragPixmap(m_drag, hotSpot);
QSize pmDeviceIndependentSize = pm.size() / pm.devicePixelRatio();
NSImage *nsimage = qt_mac_create_nsimage(pm);
- [nsimage setSize:pmDeviceIndependentSize.toCGSize()];
+ [nsimage setSize:NSSizeFromCGSize(pmDeviceIndependentSize.toCGSize())];
QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacInternalPasteboardMime::MIME_DND);
m_drag->mimeData()->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy"));
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 234da57f59..41a809cdd2 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -63,6 +63,7 @@
#include <stdlib.h>
#include <qabstracteventdispatcher.h>
#include <qsysinfo.h>
+#include <qoperatingsystemversion.h>
#include <qglobal.h>
#include <QDir>
@@ -164,7 +165,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate);
[mSavePanel setDelegate:self];
#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_11)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_11)
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXElCapitan)
mOpenPanel.accessoryViewDisclosed = YES;
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 01fbb7bad2..fa0365dbf7 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -160,10 +160,8 @@ Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions)
*/
QNSView *qnsview_cast(NSView *view)
{
- if (![view isKindOfClass:[QNSView class]]) {
- qCWarning(lcQpaCocoaWindow) << "NSView is not QNSView, consider checking for Qt::ForeignWindow";
+ if (![view isKindOfClass:[QNSView class]])
return nil;
- }
return static_cast<QNSView *>(view);
}
@@ -235,13 +233,13 @@ QString qt_mac_applicationName()
return appName;
}
-int qt_mac_mainScreenHeight()
+int qt_mac_primaryScreenHeight()
{
QMacAutoReleasePool pool;
NSArray *screens = [NSScreen screens];
if ([screens count] > 0) {
- // The first screen in the screens array is documented
- // to have the (0,0) origin.
+ // The first screen in the screens array is documented to
+ // have the (0,0) origin and is designated the primary screen.
NSRect screenFrame = [[screens objectAtIndex: 0] frame];
return screenFrame.size.height;
}
@@ -250,12 +248,12 @@ int qt_mac_mainScreenHeight()
int qt_mac_flipYCoordinate(int y)
{
- return qt_mac_mainScreenHeight() - y;
+ return qt_mac_primaryScreenHeight() - y;
}
qreal qt_mac_flipYCoordinate(qreal y)
{
- return qt_mac_mainScreenHeight() - y;
+ return qt_mac_primaryScreenHeight() - y;
}
QPointF qt_mac_flipPoint(const NSPoint &p)
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 32f6fe0af1..5cf8e7d237 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
class QCocoaScreen : public QPlatformScreen
{
public:
- QCocoaScreen(int screenIndex);
+ QCocoaScreen(NSScreen *screen);
~QCocoaScreen();
// ----------------------------------------------------
@@ -84,11 +84,20 @@ public:
// ----------------------------------------------------
// Additional methods
void setVirtualSiblings(const QList<QPlatformScreen *> &siblings) { m_siblings = siblings; }
- NSScreen *osScreen() const;
+ NSScreen *nsScreen() const;
void updateGeometry();
+ QPointF mapToNative(const QPointF &pos) const { return flipCoordinate(pos); }
+ QRectF mapToNative(const QRectF &rect) const { return flipCoordinate(rect); }
+ QPointF mapFromNative(const QPointF &pos) const { return flipCoordinate(pos); }
+ QRectF mapFromNative(const QRectF &rect) const { return flipCoordinate(rect); }
+
+private:
+ QPointF flipCoordinate(const QPointF &pos) const;
+ QRectF flipCoordinate(const QRectF &rect) const;
+
public:
- int m_screenIndex;
+ NSScreen *m_nsScreen;
QRect m_geometry;
QRect m_availableGeometry;
QDpi m_logicalDpi;
@@ -144,7 +153,7 @@ public:
QList<int> possibleKeys(const QKeyEvent *event) const Q_DECL_OVERRIDE;
void updateScreens();
- QCocoaScreen *screenAtIndex(int index);
+ QCocoaScreen *screenForNSScreen(NSScreen *nsScreen);
void setToolbar(QWindow *window, NSToolbar *toolbar);
NSToolbar *toolbar(QWindow *window) const;
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 18340f4ee1..6e145682a1 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -69,8 +69,8 @@ static void initResources()
QT_BEGIN_NAMESPACE
-QCocoaScreen::QCocoaScreen(int screenIndex) :
- QPlatformScreen(), m_screenIndex(screenIndex), m_refreshRate(60.0)
+QCocoaScreen::QCocoaScreen(NSScreen *screen)
+ : QPlatformScreen(), m_nsScreen(screen), m_refreshRate(60.0)
{
updateGeometry();
m_cursor = new QCocoaCursor;
@@ -81,46 +81,63 @@ QCocoaScreen::~QCocoaScreen()
delete m_cursor;
}
-NSScreen *QCocoaScreen::osScreen() const
+NSScreen *QCocoaScreen::nsScreen() const
{
- NSArray *screens = [NSScreen screens];
- return ((NSUInteger)m_screenIndex < [screens count]) ? [screens objectAtIndex:m_screenIndex] : nil;
+ return m_nsScreen;
+}
+
+/*!
+ Flips the Y coordinate of the point between quadrant I and IV.
+
+ The native coordinate system on macOS uses quadrant I, with origin
+ in bottom left, and Qt uses quadrant IV, with origin in top left.
+
+ By flippig the Y coordinate, we can map the position between the
+ two coordinate systems.
+*/
+QPointF QCocoaScreen::flipCoordinate(const QPointF &pos) const
+{
+ return QPointF(pos.x(), m_geometry.height() - pos.y());
+}
+
+/*!
+ Flips the Y coordinate of the rectangle between quadrant I and IV.
+
+ The native coordinate system on macOS uses quadrant I, with origin
+ in bottom left, and Qt uses quadrant IV, with origin in top left.
+
+ By flippig the Y coordinate, we can map the rectangle between the
+ two coordinate systems.
+*/
+QRectF QCocoaScreen::flipCoordinate(const QRectF &rect) const
+{
+ return QRectF(flipCoordinate(rect.topLeft() + QPoint(0, rect.height())), rect.size());
}
void QCocoaScreen::updateGeometry()
{
- NSScreen *nsScreen = osScreen();
- if (!nsScreen)
+ if (!m_nsScreen)
return;
- NSRect frameRect = [nsScreen frame];
+ // At this point the geometry is in native coordinates, but the size
+ // is correct, which we take advantage of next when we map the native
+ // coordinates to the Qt coordinate system.
+ m_geometry = QRectF::fromCGRect(NSRectToCGRect(m_nsScreen.frame)).toRect();
+ m_availableGeometry = QRectF::fromCGRect(NSRectToCGRect(m_nsScreen.visibleFrame)).toRect();
- if (m_screenIndex == 0) {
- m_geometry = QRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height);
- // This is the primary screen, the one that contains the menubar. Its origin should be
- // (0, 0), and it's the only one whose available geometry differs from its full geometry.
- NSRect visibleRect = [nsScreen visibleFrame];
- m_availableGeometry = QRect(visibleRect.origin.x,
- frameRect.size.height - (visibleRect.origin.y + visibleRect.size.height), // invert y
- visibleRect.size.width, visibleRect.size.height);
- } else {
- // NSScreen origin is at the bottom-left corner, QScreen is at the top-left corner.
- // When we get the NSScreen frame rect, we need to re-align its origin y coordinate
- // w.r.t. the primary screen, whose origin is (0, 0).
- NSRect r = [[[NSScreen screens] objectAtIndex:0] frame];
- QRect referenceScreenGeometry = QRect(r.origin.x, r.origin.y, r.size.width, r.size.height);
- m_geometry = QRect(frameRect.origin.x,
- referenceScreenGeometry.height() - (frameRect.origin.y + frameRect.size.height),
- frameRect.size.width, frameRect.size.height);
-
- // Not primary screen. See above.
- m_availableGeometry = m_geometry;
- }
+ // The reference screen for the geometry is always the primary screen, but since
+ // we may be in the process of creating and registering the primary screen, we
+ // must special-case that and assign it direcly.
+ QCocoaScreen *primaryScreen = (m_nsScreen == [[NSScreen screens] firstObject]) ?
+ this : static_cast<QCocoaScreen*>(QGuiApplication::primaryScreen()->handle());
+
+ m_geometry = primaryScreen->mapFromNative(m_geometry).toRect();
+ m_availableGeometry = primaryScreen->mapFromNative(m_availableGeometry).toRect();
m_format = QImage::Format_RGB32;
- m_depth = NSBitsPerPixelFromDepth([nsScreen depth]);
+ m_depth = NSBitsPerPixelFromDepth([m_nsScreen depth]);
- NSDictionary *devDesc = [nsScreen deviceDescription];
+ NSDictionary *devDesc = [m_nsScreen deviceDescription];
CGDirectDisplayID dpy = [[devDesc objectForKey:@"NSScreenNumber"] unsignedIntValue];
CGSize size = CGDisplayScreenSize(dpy);
m_physicalSize = QSizeF(size.width, size.height);
@@ -147,8 +164,7 @@ void QCocoaScreen::updateGeometry()
qreal QCocoaScreen::devicePixelRatio() const
{
QMacAutoReleasePool pool;
- NSScreen * screen = osScreen();
- return qreal(screen ? [screen backingScaleFactor] : 1.0);
+ return qreal(m_nsScreen ? [m_nsScreen backingScaleFactor] : 1.0);
}
QPlatformScreen::SubpixelAntialiasingType QCocoaScreen::subpixelAntialiasingTypeHint() const
@@ -427,7 +443,7 @@ void QCocoaIntegration::updateScreens()
// NSScreen documentation says do not cache the array returned from [NSScreen screens].
// However in practice, we can identify a screen by its pointer: if resolution changes,
// the NSScreen object will be the same instance, just with different values.
- if (existingScr->osScreen() == scr) {
+ if (existingScr->nsScreen() == scr) {
screen = existingScr;
break;
}
@@ -435,7 +451,7 @@ void QCocoaIntegration::updateScreens()
remainingScreens.remove(screen);
screen->updateGeometry();
} else {
- screen = new QCocoaScreen(i);
+ screen = new QCocoaScreen(scr);
mScreens.append(screen);
screenAdded(screen);
}
@@ -451,20 +467,27 @@ void QCocoaIntegration::updateScreens()
// Now the leftovers in remainingScreens are no longer current, so we can delete them.
foreach (QCocoaScreen* screen, remainingScreens) {
mScreens.removeOne(screen);
+ // Prevent stale references to NSScreen during destroy
+ screen->m_nsScreen = nil;
destroyScreen(screen);
}
}
-QCocoaScreen *QCocoaIntegration::screenAtIndex(int index)
+QCocoaScreen *QCocoaIntegration::screenForNSScreen(NSScreen *nsScreen)
{
- if (index >= mScreens.count())
+ NSUInteger index = [[NSScreen screens] indexOfObject:nsScreen];
+ if (index == NSNotFound)
+ return 0;
+
+ if (index >= unsigned(mScreens.count()))
updateScreens();
- // It is possible that the screen got removed while updateScreens was called
- // so we do a sanity check to be certain
- if (index >= mScreens.count())
- return 0;
- return mScreens.at(index);
+ for (QCocoaScreen *screen : mScreens) {
+ if (screen->nsScreen() == nsScreen)
+ return screen;
+ }
+
+ return 0;
}
bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 16639fd8b1..bb015c2419 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -96,6 +96,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSWindowHelper);
@property (nonatomic, readonly) QNSWindowHelper *helper;
- (id)initWithContentRect:(NSRect)contentRect
+ screen:(NSScreen*)screen
styleMask:(NSUInteger)windowStyle
qPlatformWindow:(QCocoaWindow *)qpw;
@@ -111,6 +112,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSWindow);
@property (nonatomic, readonly) QNSWindowHelper *helper;
- (id)initWithContentRect:(NSRect)contentRect
+ screen:(NSScreen*)screen
styleMask:(NSUInteger)windowStyle
qPlatformWindow:(QCocoaWindow *)qpw;
@@ -141,6 +143,13 @@ QT_BEGIN_NAMESPACE
// See the qt_on_cocoa manual tests for a working example, located
// in tests/manual/cocoa at the time of writing.
+#ifdef Q_MOC_RUN
+#define Q_NOTIFICATION_HANDLER(notification) Q_INVOKABLE Q_COCOA_NOTIFICATION_##notification
+#else
+#define Q_NOTIFICATION_HANDLER(notification)
+#define Q_NOTIFICATION_PREFIX QT_STRINGIFY2(Q_COCOA_NOTIFICATION_)
+#endif
+
class QCocoaMenuBar;
class QCocoaWindow : public QObject, public QPlatformWindow
@@ -187,12 +196,25 @@ public:
void setEmbeddedInForeignView(bool subwindow);
- void windowWillMove();
- void windowDidMove();
- void windowDidResize();
- void windowDidEndLiveResize();
+ Q_NOTIFICATION_HANDLER(NSWindowWillMoveNotification) void windowWillMove();
+ Q_NOTIFICATION_HANDLER(NSWindowDidMoveNotification) void windowDidMove();
+ Q_NOTIFICATION_HANDLER(NSWindowDidResizeNotification) void windowDidResize();
+ Q_NOTIFICATION_HANDLER(NSViewFrameDidChangeNotification) void viewDidChangeFrame();
+ Q_NOTIFICATION_HANDLER(NSViewGlobalFrameDidChangeNotification) void viewDidChangeGlobalFrame();
+ Q_NOTIFICATION_HANDLER(NSWindowDidEndLiveResizeNotification) void windowDidEndLiveResize();
+ Q_NOTIFICATION_HANDLER(NSWindowDidBecomeKeyNotification) void windowDidBecomeKey();
+ Q_NOTIFICATION_HANDLER(NSWindowDidResignKeyNotification) void windowDidResignKey();
+ Q_NOTIFICATION_HANDLER(NSWindowDidMiniaturizeNotification) void windowDidMiniaturize();
+ Q_NOTIFICATION_HANDLER(NSWindowDidDeminiaturizeNotification) void windowDidDeminiaturize();
+ Q_NOTIFICATION_HANDLER(NSWindowDidEnterFullScreenNotification) void windowDidEnterFullScreen();
+ Q_NOTIFICATION_HANDLER(NSWindowDidExitFullScreenNotification) void windowDidExitFullScreen();
+ Q_NOTIFICATION_HANDLER(NSWindowDidOrderOffScreenNotification) void windowDidOrderOffScreen();
+ Q_NOTIFICATION_HANDLER(NSWindowDidOrderOnScreenAndFinishAnimatingNotification) void windowDidOrderOnScreen();
+ Q_NOTIFICATION_HANDLER(NSWindowDidChangeOcclusionStateNotification) void windowDidChangeOcclusionState();
+ Q_NOTIFICATION_HANDLER(NSWindowDidChangeScreenNotification) void windowDidChangeScreen();
+ Q_NOTIFICATION_HANDLER(NSWindowWillCloseNotification) void windowWillClose();
+
bool windowShouldClose();
- void windowWillClose();
bool windowIsPopupType(Qt::WindowType type = Qt::Widget) const;
void setSynchedWindowStateFromWindow();
@@ -239,19 +261,32 @@ public:
static QPoint bottomLeftClippedByNSWindowOffsetStatic(QWindow *window);
QPoint bottomLeftClippedByNSWindowOffset() const;
+
+ enum RecreationReason {
+ RecreationNotNeeded = 0,
+ ParentChanged = 0x1,
+ MissingWindow = 0x2,
+ WindowModalityChanged = 0x4,
+ ChildNSWindowChanged = 0x8,
+ ContentViewChanged = 0x10,
+ PanelChanged = 0x20,
+ };
+ Q_DECLARE_FLAGS(RecreationReasons, RecreationReason)
+ Q_FLAG(RecreationReasons)
+
protected:
- void recreateWindow(const QPlatformWindow *parentWindow);
- QCocoaNSWindow *createNSWindow();
- void setNSWindow(QCocoaNSWindow *window);
+ bool isChildNSWindow() const;
+ bool isContentView() const;
- bool shouldUseNSPanel();
+ void foreachChildNSWindow(void (^block)(QCocoaWindow *));
+
+ void recreateWindowIfNeeded();
+ QCocoaNSWindow *createNSWindow(bool shouldBeChildNSWindow, bool shouldBePanel);
QRect nativeWindowGeometry() const;
- QCocoaWindow *parentCocoaWindow() const;
void syncWindowState(Qt::WindowState newState);
void reinsertChildWindow(QCocoaWindow *child);
void removeChildWindow(QCocoaWindow *child);
- bool isNativeWindowTypeInconsistent();
// private:
public: // for QNSView
@@ -268,10 +303,6 @@ public: // for QNSView
bool m_viewIsEmbedded; // true if the m_view is actually embedded in a "foreign" NSView hiearchy
bool m_viewIsToBeEmbedded; // true if the m_view is intended to be embedded in a "foreign" NSView hiearchy
- QCocoaWindow *m_parentCocoaWindow;
- bool m_isNSWindowChild; // this window is a non-top level QWindow with a NSWindow.
- QList<QCocoaWindow *> m_childWindows;
-
Qt::WindowFlags m_windowFlags;
bool m_effectivelyMaximized;
Qt::WindowState m_synchedWindowState;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 602da0a175..c8f890a11c 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -130,8 +130,7 @@ static void qt_closePopups()
[forwardView mouseDragged:theEvent];
}
}
-
- if (!pw->m_isNSWindowChild && theEvent.type == NSLeftMouseDown) {
+ if (pw->window()->isTopLevel() && theEvent.type == NSLeftMouseDown) {
pw->m_forwardWindow.clear();
}
}
@@ -202,13 +201,14 @@ static void qt_closePopups()
@synthesize helper = _helper;
- (id)initWithContentRect:(NSRect)contentRect
+ screen:(NSScreen*)screen
styleMask:(NSUInteger)windowStyle
qPlatformWindow:(QCocoaWindow *)qpw
{
self = [super initWithContentRect:contentRect
styleMask:windowStyle
backing:NSBackingStoreBuffered
- defer:NO]; // Deferring window creation breaks OpenGL (the GL context is
+ defer:NO screen:screen]; // Deferring window creation breaks OpenGL (the GL context is
// set up before the window is shown and needs a proper window)
if (self) {
@@ -222,7 +222,7 @@ static void qt_closePopups()
// Prevent child NSWindows from becoming the key window in
// order keep the active apperance of the top-level window.
QCocoaWindow *pw = self.helper.platformWindow;
- if (!pw || pw->m_isNSWindowChild)
+ if (!pw || !pw->window()->isTopLevel())
return NO;
if (pw->shouldRefuseKeyWindowAndFirstResponder())
@@ -241,7 +241,7 @@ static void qt_closePopups()
// Windows with a transient parent (such as combobox popup windows)
// cannot become the main window:
QCocoaWindow *pw = self.helper.platformWindow;
- if (!pw || pw->m_isNSWindowChild || pw->window()->transientParent())
+ if (!pw || !pw->window()->isTopLevel() || pw->window()->transientParent())
canBecomeMain = NO;
return canBecomeMain;
@@ -284,13 +284,14 @@ static void qt_closePopups()
@synthesize helper = _helper;
- (id)initWithContentRect:(NSRect)contentRect
+ screen:(NSScreen*)screen
styleMask:(NSUInteger)windowStyle
qPlatformWindow:(QCocoaWindow *)qpw
{
self = [super initWithContentRect:contentRect
styleMask:windowStyle
backing:NSBackingStoreBuffered
- defer:NO]; // Deferring window creation breaks OpenGL (the GL context is
+ defer:NO screen:screen]; // Deferring window creation breaks OpenGL (the GL context is
// set up before the window is shown and needs a proper window)
if (self) {
@@ -343,6 +344,63 @@ static void qt_closePopups()
@end
+static void qRegisterNotificationCallbacks()
+{
+ static const QLatin1String notificationHandlerPrefix(Q_NOTIFICATION_PREFIX);
+
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+
+ const QMetaObject *metaObject = QMetaType::metaObjectForType(qRegisterMetaType<QCocoaWindow*>());
+ Q_ASSERT(metaObject);
+
+ for (int i = 0; i < metaObject->methodCount(); ++i) {
+ QMetaMethod method = metaObject->method(i);
+ const QString methodTag = QString::fromLatin1(method.tag());
+ if (!methodTag.startsWith(notificationHandlerPrefix))
+ continue;
+
+ const QString notificationName = methodTag.mid(notificationHandlerPrefix.size());
+ [center addObserverForName:notificationName.toNSString() object:nil queue:nil
+ usingBlock:^(NSNotification *notification) {
+
+ NSView *view = nullptr;
+ if ([notification.object isKindOfClass:[NSWindow class]]) {
+ NSWindow *window = notification.object;
+ // Only top level NSWindows should notify their QNSViews
+ if (window.parentWindow)
+ return;
+
+ if (!window.contentView)
+ return;
+
+ view = window.contentView;
+ } else if ([notification.object isKindOfClass:[NSView class]]) {
+ view = notification.object;
+ } else {
+ qCWarning(lcQpaCocoaWindow) << "Unhandled notifcation"
+ << notification.name << "for" << notification.object;
+ return;
+ }
+ Q_ASSERT(view);
+
+ QCocoaWindow *cocoaWindow = nullptr;
+ if (QNSView *qnsView = qnsview_cast(view))
+ cocoaWindow = qnsView.platformWindow;
+
+ // FIXME: Could be a foreign window, look up by iterating top level QWindows
+
+ if (!cocoaWindow)
+ return;
+
+ if (!method.invoke(cocoaWindow, Qt::DirectConnection)) {
+ qCWarning(lcQpaCocoaWindow) << "Failed to invoke NSNotification callback for"
+ << notification.name << "on" << cocoaWindow;
+ }
+ }];
+ }
+}
+Q_CONSTRUCTOR_FUNCTION(qRegisterNotificationCallbacks)
+
const int QCocoaWindow::NoAlertRequest = -1;
QCocoaWindow::QCocoaWindow(QWindow *tlw)
@@ -351,8 +409,6 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
, m_nsWindow(0)
, m_viewIsEmbedded(false)
, m_viewIsToBeEmbedded(false)
- , m_parentCocoaWindow(0)
- , m_isNSWindowChild(false)
, m_effectivelyMaximized(false)
, m_synchedWindowState(Qt::WindowActive)
, m_windowModality(Qt::NonModal)
@@ -405,7 +461,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
[m_view setWantsLayer:enable];
}
setGeometry(tlw->geometry());
- recreateWindow(QPlatformWindow::parent());
+ recreateWindowIfNeeded();
tlw->setGeometry(geometry());
if (tlw->isTopLevel())
setWindowIcon(tlw->icon());
@@ -420,12 +476,10 @@ QCocoaWindow::~QCocoaWindow()
[m_nsWindow makeFirstResponder:nil];
[m_nsWindow setContentView:nil];
[m_nsWindow.helper detachFromPlatformWindow];
- if (m_isNSWindowChild) {
- if (m_parentCocoaWindow)
- m_parentCocoaWindow->removeChildWindow(this);
- } else if ([m_view superview]) {
+ if (m_view.window.parentWindow)
+ [m_view.window.parentWindow removeChildWindow:m_view.window];
+ else if ([m_view superview])
[m_view removeFromSuperview];
- }
removeMonitor();
@@ -440,10 +494,9 @@ QCocoaWindow::~QCocoaWindow()
QCocoaIntegration::instance()->popupWindowStack()->removeAll(this);
}
- foreach (QCocoaWindow *child, m_childWindows) {
- [m_nsWindow removeChildWindow:child->m_nsWindow];
- child->m_parentCocoaWindow = 0;
- }
+ foreachChildNSWindow(^(QCocoaWindow *childWindow) {
+ [m_nsWindow removeChildWindow:childWindow->m_nsWindow];
+ });
[m_view release];
[m_nsWindow release];
@@ -491,7 +544,7 @@ QRect QCocoaWindow::geometry() const
NSRect screenRect = [[m_view window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
NSPoint screenPoint = screenRect.origin;
QPoint position = qt_mac_flipPoint(screenPoint).toPoint();
- QSize size = QRectF::fromCGRect([m_view bounds]).toRect().size();
+ QSize size = QRectF::fromCGRect(NSRectToCGRect([m_view bounds])).toRect().size();
return QRect(position, size);
}
@@ -512,9 +565,9 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
return;
}
- if (m_isNSWindowChild) {
+ if (isChildNSWindow()) {
QPlatformWindow::setGeometry(rect);
- NSWindow *parentNSWindow = m_parentCocoaWindow->m_nsWindow;
+ NSWindow *parentNSWindow = m_view.window.parentWindow;
NSRect parentWindowFrame = [parentNSWindow contentRectForFrameRect:parentNSWindow.frame];
clipWindow(parentWindowFrame);
@@ -536,14 +589,14 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
void QCocoaWindow::clipChildWindows()
{
- foreach (QCocoaWindow *childWindow, m_childWindows) {
+ foreachChildNSWindow(^(QCocoaWindow *childWindow) {
childWindow->clipWindow(m_nsWindow.frame);
- }
+ });
}
void QCocoaWindow::clipWindow(const NSRect &clipRect)
{
- if (!m_isNSWindowChild)
+ if (!isChildNSWindow())
return;
NSRect clippedWindowRect = NSZeroRect;
@@ -568,15 +621,15 @@ void QCocoaWindow::clipWindow(const NSRect &clipRect)
m_hiddenByClipping = false;
if (!m_hiddenByAncestor) {
[m_nsWindow orderFront:nil];
- m_parentCocoaWindow->reinsertChildWindow(this);
+ static_cast<QCocoaWindow *>(QPlatformWindow::parent())->reinsertChildWindow(this);
}
}
}
// recurse
- foreach (QCocoaWindow *childWindow, m_childWindows) {
+ foreachChildNSWindow(^(QCocoaWindow *childWindow) {
childWindow->clipWindow(clippedWindowRect);
- }
+ });
}
void QCocoaWindow::hide(bool becauseOfAncestor)
@@ -593,8 +646,9 @@ void QCocoaWindow::hide(bool becauseOfAncestor)
if (!visible) // Could have been clipped before
return;
- foreach (QCocoaWindow *childWindow, m_childWindows)
+ foreachChildNSWindow(^(QCocoaWindow *childWindow) {
childWindow->hide(true);
+ });
[m_nsWindow orderOut:nil];
}
@@ -604,20 +658,21 @@ void QCocoaWindow::show(bool becauseOfAncestor)
if ([m_nsWindow isVisible])
return;
- if (m_parentCocoaWindow && ![m_parentCocoaWindow->m_nsWindow isVisible]) {
+ if (m_view.window.parentWindow && !m_view.window.parentWindow.visible) {
m_hiddenByAncestor = true; // Parent still hidden, don't show now
} else if ((becauseOfAncestor == m_hiddenByAncestor) // Was NEITHER explicitly hidden
&& !m_hiddenByClipping) { // ... NOR clipped
- if (m_isNSWindowChild) {
+ if (isChildNSWindow()) {
m_hiddenByAncestor = false;
setCocoaGeometry(windowGeometry());
}
if (!m_hiddenByClipping) { // setCocoaGeometry() can change the clipping status
[m_nsWindow orderFront:nil];
- if (m_isNSWindowChild)
- m_parentCocoaWindow->reinsertChildWindow(this);
- foreach (QCocoaWindow *childWindow, m_childWindows)
+ if (isChildNSWindow())
+ static_cast<QCocoaWindow *>(QPlatformWindow::parent())->reinsertChildWindow(this);
+ foreachChildNSWindow(^(QCocoaWindow *childWindow) {
childWindow->show(true);
+ });
}
}
}
@@ -626,7 +681,7 @@ void QCocoaWindow::setVisible(bool visible)
{
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setVisible" << window() << visible;
- if (m_isNSWindowChild && m_hiddenByClipping)
+ if (isChildNSWindow() && m_hiddenByClipping)
return;
m_inSetVisible = true;
@@ -638,8 +693,7 @@ void QCocoaWindow::setVisible(bool visible)
if (visible) {
// We need to recreate if the modality has changed as the style mask will need updating
- if (m_windowModality != window()->modality() || isNativeWindowTypeInconsistent())
- recreateWindow(QPlatformWindow::parent());
+ recreateWindowIfNeeded();
// Register popup windows. The Cocoa platform plugin will forward mouse events
// to them and close them when needed.
@@ -700,8 +754,9 @@ void QCocoaWindow::setVisible(bool visible)
else
[m_nsWindow orderFront:nil];
- foreach (QCocoaWindow *childWindow, m_childWindows)
+ foreachChildNSWindow(^(QCocoaWindow *childWindow) {
childWindow->show(true);
+ });
} else {
show();
}
@@ -879,7 +934,7 @@ void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags)
void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
{
- if (m_nsWindow && !m_isNSWindowChild) {
+ if (m_nsWindow && !isChildNSWindow()) {
NSUInteger styleMask = windowStyleMask(flags);
NSInteger level = this->windowLevel(flags);
// While setting style mask we can have -updateGeometry calls on a content
@@ -983,19 +1038,16 @@ void QCocoaWindow::raise()
// ### handle spaces (see Qt 4 raise_sys in qwidget_mac.mm)
if (!m_nsWindow)
return;
- if (m_isNSWindowChild) {
- QList<QCocoaWindow *> &siblings = m_parentCocoaWindow->m_childWindows;
- siblings.removeOne(this);
- siblings.append(this);
+ if (isChildNSWindow()) {
if (m_hiddenByClipping)
return;
}
if ([m_nsWindow isVisible]) {
- if (m_isNSWindowChild) {
+ if (isChildNSWindow()) {
// -[NSWindow orderFront:] doesn't work with attached windows.
// The only solution is to remove and add the child window.
// This will place it on top of all the other NSWindows.
- NSWindow *parentNSWindow = m_parentCocoaWindow->m_nsWindow;
+ NSWindow *parentNSWindow = m_view.window.parentWindow;
[parentNSWindow removeChildWindow:m_nsWindow];
[parentNSWindow addChildWindow:m_nsWindow ordered:NSWindowAbove];
} else {
@@ -1021,20 +1073,17 @@ void QCocoaWindow::lower()
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::lower" << window();
if (!m_nsWindow)
return;
- if (m_isNSWindowChild) {
- QList<QCocoaWindow *> &siblings = m_parentCocoaWindow->m_childWindows;
- siblings.removeOne(this);
- siblings.prepend(this);
+ if (isChildNSWindow()) {
if (m_hiddenByClipping)
return;
}
if ([m_nsWindow isVisible]) {
- if (m_isNSWindowChild) {
+ if (isChildNSWindow()) {
// -[NSWindow orderBack:] doesn't work with attached windows.
// The only solution is to remove and add all the child windows except this one.
// This will keep the current window at the bottom while adding the others on top of it,
// hopefully in the same order (this is not documented anywhere in the Cocoa documentation).
- NSWindow *parentNSWindow = m_parentCocoaWindow->m_nsWindow;
+ NSWindow *parentNSWindow = m_view.window.parentWindow;
NSArray *children = [parentNSWindow.childWindows copy];
for (NSWindow *child in children)
if (m_nsWindow != child) {
@@ -1095,7 +1144,7 @@ void QCocoaWindow::propagateSizeHints()
QSize sizeIncrement = windowSizeIncrement();
if (sizeIncrement.isEmpty())
sizeIncrement = QSize(1, 1);
- [m_nsWindow setResizeIncrements:sizeIncrement.toCGSize()];
+ [m_nsWindow setResizeIncrements:NSSizeFromCGSize(sizeIncrement.toCGSize())];
QRect rect = geometry();
QSize baseSize = windowBaseSize();
@@ -1158,7 +1207,7 @@ void QCocoaWindow::setParent(const QPlatformWindow *parentWindow)
// recreate the window for compatibility
bool unhideAfterRecreate = parentWindow && !m_viewIsToBeEmbedded && ![m_view isHidden];
- recreateWindow(parentWindow);
+ recreateWindowIfNeeded();
if (unhideAfterRecreate)
[m_view setHidden:NO];
setCocoaGeometry(geometry());
@@ -1182,6 +1231,8 @@ void QCocoaWindow::setEmbeddedInForeignView(bool embedded)
m_nsWindow = 0;
}
+// ----------------------- NSWindow notifications -----------------------
+
void QCocoaWindow::windowWillMove()
{
// Close any open popups on window move
@@ -1190,7 +1241,7 @@ void QCocoaWindow::windowWillMove()
void QCocoaWindow::windowDidMove()
{
- if (m_isNSWindowChild)
+ if (isChildNSWindow())
return;
[qnsview_cast(m_view) updateGeometry];
@@ -1201,13 +1252,30 @@ void QCocoaWindow::windowDidResize()
if (!m_nsWindow)
return;
- if (m_isNSWindowChild)
+ if (isChildNSWindow())
return;
clipChildWindows();
[qnsview_cast(m_view) updateGeometry];
}
+void QCocoaWindow::viewDidChangeFrame()
+{
+ [qnsview_cast(m_view) updateGeometry];
+}
+
+/*!
+ Callback for NSViewGlobalFrameDidChangeNotification.
+
+ Posted whenever an NSView object that has attached surfaces (that is,
+ NSOpenGLContext objects) moves to a different screen, or other cases
+ where the NSOpenGLContext object needs to be updated.
+*/
+void QCocoaWindow::viewDidChangeGlobalFrame()
+{
+ updateExposedGeometry();
+}
+
void QCocoaWindow::windowDidEndLiveResize()
{
if (m_synchedWindowState == Qt::WindowMaximized && ![m_nsWindow isZoomed]) {
@@ -1216,6 +1284,104 @@ void QCocoaWindow::windowDidEndLiveResize()
}
}
+void QCocoaWindow::windowDidBecomeKey()
+{
+ if (window()->type() == Qt::ForeignWindow)
+ return;
+
+ if (m_windowUnderMouse) {
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [qnsview_cast(m_view) convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ QWindowSystemInterface::handleEnterEvent(m_enterLeaveTargetWindow, windowPoint, screenPoint);
+ }
+
+ if (!windowIsPopupType() && !qnsview_cast(m_view).isMenuView)
+ QWindowSystemInterface::handleWindowActivated(window());
+}
+
+void QCocoaWindow::windowDidResignKey()
+{
+ if (window()->type() == Qt::ForeignWindow)
+ return;
+
+ // Key window will be non-nil if another window became key, so do not
+ // set the active window to zero here -- the new key window's
+ // NSWindowDidBecomeKeyNotification hander will change the active window.
+ NSWindow *keyWindow = [NSApp keyWindow];
+ if (!keyWindow || keyWindow == m_view.window) {
+ // No new key window, go ahead and set the active window to zero
+ if (!windowIsPopupType() && !qnsview_cast(m_view).isMenuView)
+ QWindowSystemInterface::handleWindowActivated(0);
+ }
+}
+
+void QCocoaWindow::windowDidMiniaturize()
+{
+ [qnsview_cast(m_view) notifyWindowStateChanged:Qt::WindowMinimized];
+}
+
+void QCocoaWindow::windowDidDeminiaturize()
+{
+ [qnsview_cast(m_view) notifyWindowStateChanged:Qt::WindowNoState];
+}
+
+void QCocoaWindow::windowDidEnterFullScreen()
+{
+ [qnsview_cast(m_view) notifyWindowStateChanged:Qt::WindowFullScreen];
+}
+
+void QCocoaWindow::windowDidExitFullScreen()
+{
+ [qnsview_cast(m_view) notifyWindowStateChanged:Qt::WindowNoState];
+}
+
+void QCocoaWindow::windowDidOrderOffScreen()
+{
+ obscureWindow();
+}
+
+void QCocoaWindow::windowDidOrderOnScreen()
+{
+ exposeWindow();
+}
+
+void QCocoaWindow::windowDidChangeOcclusionState()
+{
+ // Several unit tests expect paint and/or expose events for windows that are
+ // sometimes (unpredictably) occluded and some unit tests depend on QWindow::isExposed.
+ // Don't send Expose/Obscure events when running under QTestLib.
+ static const bool onTestLib = qt_mac_resolveOption(false, "QT_QTESTLIB_RUNNING");
+ if (!onTestLib) {
+ if ((NSUInteger)[m_view.window occlusionState] & NSWindowOcclusionStateVisible) {
+ exposeWindow();
+ } else {
+ // Send Obscure events on window occlusion to stop animations.
+ obscureWindow();
+ }
+ }
+}
+
+void QCocoaWindow::windowDidChangeScreen()
+{
+ if (!window())
+ return;
+
+ if (QCocoaScreen *cocoaScreen = QCocoaIntegration::instance()->screenForNSScreen(m_view.window.screen))
+ QWindowSystemInterface::handleWindowScreenChanged(window(), cocoaScreen->screen());
+
+ updateExposedGeometry();
+}
+
+void QCocoaWindow::windowWillClose()
+{
+ // Close any open popups on window closing.
+ if (window() && !windowIsPopupType(window()->type()))
+ qt_closePopups();
+}
+
+// ----------------------- NSWindowDelegate callbacks -----------------------
+
bool QCocoaWindow::windowShouldClose()
{
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::windowShouldClose" << window();
@@ -1229,12 +1395,7 @@ bool QCocoaWindow::windowShouldClose()
return accepted;
}
-void QCocoaWindow::windowWillClose()
-{
- // Close any open popups on window closing.
- if (window() && !windowIsPopupType(window()->type()))
- qt_closePopups();
-}
+// --------------------------------------------------------------------------
void QCocoaWindow::setSynchedWindowStateFromWindow()
{
@@ -1264,62 +1425,141 @@ QCocoaGLContext *QCocoaWindow::currentContext() const
}
#endif
-void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
+/*!
+ Checks if the window is a non-top level QWindow with a NSWindow.
+
+ \sa _q_platform_MacUseNSWindow, QT_MAC_USE_NSWINDOW
+*/
+bool QCocoaWindow::isChildNSWindow() const
+{
+ return m_view.window.parentWindow != nil;
+}
+
+/*!
+ Checks if the window is the content view of its immediate NSWindow.
+
+ Being the content view of a NSWindow means the QWindow is
+ the highest accessible NSView object in the window's view
+ hierarchy.
+
+ This can only happen in two cases, either if the QWindow is
+ itself a top level window, or if it's a child NSWindow.
+
+ \sa isChildNSWindow
+*/
+bool QCocoaWindow::isContentView() const
+{
+ return m_view.window.contentView == m_view;
+}
+
+/*!
+ Iterates child NSWindows that have a corresponding QCocoaWindow.
+*/
+void QCocoaWindow::foreachChildNSWindow(void (^block)(QCocoaWindow *))
+{
+ NSArray *windows = m_view.window.childWindows;
+ [windows enumerateObjectsUsingBlock:^(NSWindow *window, NSUInteger index, BOOL *stop) {
+ Q_UNUSED(index);
+ Q_UNUSED(stop);
+ if (QNSView *view = qnsview_cast(window.contentView))
+ block(view.platformWindow);
+ }];
+}
+
+/*!
+ Recreates (or removes) the NSWindow for this QWindow, if needed.
+
+ A QWindow may need a corresponding NSWindow, depending on whether
+ or not it's a top level or not (or explicitly set to be a child
+ NSWindow), whether it is a NSPanel or not, etc.
+*/
+void QCocoaWindow::recreateWindowIfNeeded()
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::recreateWindow" << window()
+ QPlatformWindow *parentWindow = QPlatformWindow::parent();
+ qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::recreateWindowIfNeeded" << window()
<< "parent" << (parentWindow ? parentWindow->window() : 0);
- bool wasNSWindowChild = m_isNSWindowChild;
- BOOL requestNSWindowChild = qt_mac_resolveOption(NO, window(), "_q_platform_MacUseNSWindow",
- "QT_MAC_USE_NSWINDOW");
- m_isNSWindowChild = parentWindow && requestNSWindowChild;
- bool needsNSWindow = m_isNSWindowChild || !parentWindow;
+ RecreationReasons recreateReason = RecreationNotNeeded;
+
+ QCocoaWindow *oldParentCocoaWindow = nullptr;
+ if (QNSView *qnsView = qnsview_cast(m_view.superview))
+ oldParentCocoaWindow = qnsView.platformWindow;
+
+ if (parentWindow != oldParentCocoaWindow)
+ recreateReason |= ParentChanged;
+
+ if (!m_view.window)
+ recreateReason |= MissingWindow;
+
+ // If the modality has changed the style mask will need updating
+ if (m_windowModality != window()->modality())
+ recreateReason |= WindowModalityChanged;
+
+ const bool shouldBeChildNSWindow = parentWindow && qt_mac_resolveOption(NO,
+ window(), "_q_platform_MacUseNSWindow", "QT_MAC_USE_NSWINDOW");
+
+ if (isChildNSWindow() != shouldBeChildNSWindow)
+ recreateReason |= ChildNSWindowChanged;
+
+ const bool shouldBeContentView = !parentWindow || shouldBeChildNSWindow;
+ if (isContentView() != shouldBeContentView)
+ recreateReason |= ContentViewChanged;
+
+ Qt::WindowType type = window()->type();
+ const bool isPanel = isContentView() && [m_view.window isKindOfClass:[QNSPanel class]];
+ const bool shouldBePanel = shouldBeContentView && !shouldBeChildNSWindow &&
+ ((type & Qt::Popup) == Qt::Popup || (type & Qt::Dialog) == Qt::Dialog);
+
+ if (isPanel != shouldBePanel)
+ recreateReason |= PanelChanged;
- QCocoaWindow *oldParentCocoaWindow = m_parentCocoaWindow;
- m_parentCocoaWindow = const_cast<QCocoaWindow *>(static_cast<const QCocoaWindow *>(parentWindow));
- if (m_parentCocoaWindow && m_isNSWindowChild) {
- QWindow *parentQWindow = m_parentCocoaWindow->window();
+ if (recreateReason == RecreationNotNeeded) {
+ qCDebug(lcQpaCocoaWindow) << "No need to recreate NSWindow";
+ return;
+ }
+
+ qCDebug(lcQpaCocoaWindow) << "Recreating NSWindow due to" << recreateReason;
+
+ QCocoaWindow *parentCocoaWindow = static_cast<QCocoaWindow *>(parentWindow);
+
+ if (shouldBeChildNSWindow) {
+ QWindow *parentQWindow = parentWindow->window();
+ // Ensure that all parents in the hierarchy are also child NSWindows
if (!parentQWindow->property("_q_platform_MacUseNSWindow").toBool()) {
parentQWindow->setProperty("_q_platform_MacUseNSWindow", QVariant(true));
- m_parentCocoaWindow->recreateWindow(m_parentCocoaWindow->m_parentCocoaWindow);
+ parentCocoaWindow->recreateWindowIfNeeded();
}
}
- bool usesNSPanel = [m_nsWindow isKindOfClass:[QNSPanel class]];
-
- // No child QNSWindow should notify its QNSView
- if (m_nsWindow && (window()->type() != Qt::ForeignWindow) && m_parentCocoaWindow && !oldParentCocoaWindow)
- [[NSNotificationCenter defaultCenter] removeObserver:m_view
- name:nil object:m_nsWindow];
-
// Remove current window (if any)
- if ((m_nsWindow && !needsNSWindow) || (usesNSPanel != shouldUseNSPanel())) {
+ if ((isContentView() && !shouldBeContentView) || (recreateReason & PanelChanged)) {
[m_nsWindow closeAndRelease];
- if (wasNSWindowChild && oldParentCocoaWindow)
- oldParentCocoaWindow->removeChildWindow(this);
+ if (isChildNSWindow())
+ [m_view.window.parentWindow removeChildWindow:m_view.window];
m_nsWindow = 0;
}
- if (needsNSWindow) {
+ if (shouldBeContentView) {
bool noPreviousWindow = m_nsWindow == 0;
if (noPreviousWindow)
- m_nsWindow = createNSWindow();
-
- // Only non-child QNSWindows should notify their QNSViews
- // (but don't register more than once).
- if ((window()->type() != Qt::ForeignWindow) && (noPreviousWindow || (wasNSWindowChild && !m_isNSWindowChild)))
- [[NSNotificationCenter defaultCenter] addObserver:m_view
- selector:@selector(windowNotification:)
- name:nil // Get all notifications
- object:m_nsWindow];
-
- if (oldParentCocoaWindow) {
- if (!m_isNSWindowChild || oldParentCocoaWindow != m_parentCocoaWindow)
- oldParentCocoaWindow->removeChildWindow(this);
+ m_nsWindow = createNSWindow(shouldBeChildNSWindow, shouldBePanel);
+
+ if (m_view.window.parentWindow) {
+ if (!shouldBeChildNSWindow || (recreateReason & ParentChanged))
+ [m_view.window.parentWindow removeChildWindow:m_view.window];
m_forwardWindow = oldParentCocoaWindow;
}
- setNSWindow(m_nsWindow);
+ // Move view to new NSWindow if needed
+ if (m_nsWindow.contentView != m_view) {
+ [m_view setPostsFrameChangedNotifications:NO];
+ [m_view retain];
+ if (m_view.superview) // m_view comes from another NSWindow
+ [m_view removeFromSuperview];
+ [m_nsWindow setContentView:m_view];
+ [m_view release];
+ [m_view setPostsFrameChangedNotifications:YES];
+ }
}
if (m_viewIsToBeEmbedded) {
@@ -1330,7 +1570,13 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
setWindowFlags(window()->flags());
setWindowTitle(window()->title());
setWindowState(window()->windowState());
- } else if (m_isNSWindowChild) {
+ } else if (shouldBeChildNSWindow) {
+ if (!m_hiddenByClipping) {
+ [parentCocoaWindow->m_nsWindow addChildWindow:m_nsWindow ordered:NSWindowAbove];
+ parentCocoaWindow->reinsertChildWindow(this);
+ }
+
+ // Set properties after the window has been made a child NSWindow
m_nsWindow.styleMask = NSBorderlessWindowMask;
m_nsWindow.hasShadow = NO;
m_nsWindow.level = NSNormalWindowLevel;
@@ -1340,22 +1586,12 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
m_nsWindow.animationBehavior = NSWindowAnimationBehaviorNone;
m_nsWindow.collectionBehavior = collectionBehavior;
setCocoaGeometry(windowGeometry());
-
- QList<QCocoaWindow *> &siblings = m_parentCocoaWindow->m_childWindows;
- if (siblings.contains(this)) {
- if (!m_hiddenByClipping)
- m_parentCocoaWindow->reinsertChildWindow(this);
- } else {
- if (!m_hiddenByClipping)
- [m_parentCocoaWindow->m_nsWindow addChildWindow:m_nsWindow ordered:NSWindowAbove];
- siblings.append(this);
- }
} else {
// Child windows have no NSWindow, link the NSViews instead.
if ([m_view superview])
[m_view removeFromSuperview];
- [m_parentCocoaWindow->m_view addSubview:m_view];
+ [parentCocoaWindow->m_view addSubview:m_view];
QRect rect = windowGeometry();
// Prevent setting a (0,0) window size; causes opengl context
// "Invalid Drawable" warnings.
@@ -1381,11 +1617,17 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
void QCocoaWindow::reinsertChildWindow(QCocoaWindow *child)
{
- int childIndex = m_childWindows.indexOf(child);
+ const QObjectList &childWindows = window()->children();
+ int childIndex = childWindows.indexOf(child->window());
Q_ASSERT(childIndex != -1);
- for (int i = childIndex; i < m_childWindows.size(); i++) {
- NSWindow *nsChild = m_childWindows[i]->m_nsWindow;
+ for (int i = childIndex; i < childWindows.size(); ++i) {
+ QWindow *window = static_cast<QWindow *>(childWindows.at(i));
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
+ if (!cocoaWindow)
+ continue;
+
+ NSWindow *nsChild = cocoaWindow->m_nsWindow;
if (i != childIndex)
[m_nsWindow removeChildWindow:nsChild];
[m_nsWindow addChildWindow:nsChild ordered:NSWindowAbove];
@@ -1399,26 +1641,39 @@ void QCocoaWindow::requestActivateWindow()
[window makeKeyWindow];
}
-bool QCocoaWindow::shouldUseNSPanel()
-{
- Qt::WindowType type = window()->type();
-
- return !m_isNSWindowChild &&
- ((type & Qt::Popup) == Qt::Popup || (type & Qt::Dialog) == Qt::Dialog);
-}
-
-QCocoaNSWindow * QCocoaWindow::createNSWindow()
+QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBeChildNSWindow, bool shouldBePanel)
{
QMacAutoReleasePool pool;
QRect rect = initialGeometry(window(), windowGeometry(), defaultWindowWidth, defaultWindowHeight);
- NSRect frame = qt_mac_flipRect(rect);
+
+ QScreen *targetScreen = nullptr;
+ for (QScreen *screen : QGuiApplication::screens()) {
+ if (screen->geometry().contains(rect.topLeft())) {
+ targetScreen = screen;
+ break;
+ }
+ }
+
+ if (!targetScreen) {
+ qCWarning(lcQpaCocoaWindow) << "Window position outside any known screen, using primary screen";
+ targetScreen = QGuiApplication::primaryScreen();
+ }
+
+ rect.translate(-targetScreen->geometry().topLeft());
+ QCocoaScreen *cocoaScreen = static_cast<QCocoaScreen *>(targetScreen->handle());
+ NSRect frame = NSRectFromCGRect(cocoaScreen->mapToNative(rect).toCGRect());
+
+ // Note: The macOS window manager has a bug, where if a screen is rotated, it will not allow
+ // a window to be created within the area of the screen that has a Y coordinate (I quadrant)
+ // higher than the height of the screen in its non-rotated state, unless the window is
+ // created with the NSWindowStyleMaskBorderless style mask.
Qt::WindowType type = window()->type();
Qt::WindowFlags flags = window()->flags();
NSUInteger styleMask;
- if (m_isNSWindowChild) {
+ if (shouldBeChildNSWindow) {
styleMask = NSBorderlessWindowMask;
} else {
styleMask = windowStyleMask(flags);
@@ -1427,32 +1682,28 @@ QCocoaNSWindow * QCocoaWindow::createNSWindow()
// Use NSPanel for popup-type windows. (Popup, Tool, ToolTip, SplashScreen)
// and dialogs
- if (shouldUseNSPanel()) {
- QNSPanel *window;
- window = [[QNSPanel alloc] initWithContentRect:frame
- styleMask: styleMask
- qPlatformWindow:this];
+ if (shouldBePanel) {
+ QNSPanel *panel = [[QNSPanel alloc] initWithContentRect:frame screen:cocoaScreen->nsScreen()
+ styleMask: styleMask qPlatformWindow:this];
+
if ((type & Qt::Popup) == Qt::Popup)
- [window setHasShadow:YES];
+ [panel setHasShadow:YES];
// Qt::Tool windows hide on app deactivation, unless Qt::WA_MacAlwaysShowToolWindow is set.
QVariant showWithoutActivating = QPlatformWindow::window()->property("_q_macAlwaysShowToolWindow");
bool shouldHideOnDeactivate = ((type & Qt::Tool) == Qt::Tool) &&
!(showWithoutActivating.isValid() && showWithoutActivating.toBool());
- [window setHidesOnDeactivate: shouldHideOnDeactivate];
+ [panel setHidesOnDeactivate: shouldHideOnDeactivate];
// Make popup windows show on the same desktop as the parent full-screen window.
- [window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
+ [panel setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
if ((type & Qt::Popup) == Qt::Popup)
- [window setAnimationBehavior:NSWindowAnimationBehaviorUtilityWindow];
+ [panel setAnimationBehavior:NSWindowAnimationBehaviorUtilityWindow];
- createdWindow = window;
+ createdWindow = panel;
} else {
- QNSWindow *window;
- window = [[QNSWindow alloc] initWithContentRect:frame
- styleMask: styleMask
- qPlatformWindow:this];
- createdWindow = window;
+ createdWindow = [[QNSWindow alloc] initWithContentRect:frame screen:cocoaScreen->nsScreen()
+ styleMask: styleMask qPlatformWindow:this];
}
if ([createdWindow respondsToSelector:@selector(setRestorable:)])
@@ -1479,36 +1730,6 @@ QCocoaNSWindow * QCocoaWindow::createNSWindow()
return createdWindow;
}
-void QCocoaWindow::setNSWindow(QCocoaNSWindow *window)
-{
- if (window.contentView != m_view) {
- [m_view setPostsFrameChangedNotifications:NO];
- [m_view retain];
- if (m_view.superview) // m_view comes from another NSWindow
- [m_view removeFromSuperview];
- [window setContentView:m_view];
- [m_view release];
- [m_view setPostsFrameChangedNotifications:YES];
- }
-}
-
-void QCocoaWindow::removeChildWindow(QCocoaWindow *child)
-{
- m_childWindows.removeOne(child);
- [m_nsWindow removeChildWindow:child->m_nsWindow];
-}
-
-bool QCocoaWindow::isNativeWindowTypeInconsistent()
-{
- if (!m_nsWindow)
- return false;
-
- const bool isPanel = [m_nsWindow isKindOfClass:[QNSPanel class]];
- const bool usePanel = shouldUseNSPanel();
-
- return isPanel != usePanel;
-}
-
void QCocoaWindow::removeMonitor()
{
if (!monitor)
@@ -1520,7 +1741,7 @@ void QCocoaWindow::removeMonitor()
// Returns the current global screen geometry for the nswindow associated with this window.
QRect QCocoaWindow::nativeWindowGeometry() const
{
- if (!m_nsWindow || m_isNSWindowChild)
+ if (!m_nsWindow || isChildNSWindow())
return geometry();
NSRect rect = [m_nsWindow frame];
@@ -1530,15 +1751,6 @@ QRect QCocoaWindow::nativeWindowGeometry() const
return qRect;
}
-// Returns a pointer to the parent QCocoaWindow for this window, or 0 if there is none.
-QCocoaWindow *QCocoaWindow::parentCocoaWindow() const
-{
- if (window() && window()->transientParent()) {
- return static_cast<QCocoaWindow*>(window()->transientParent()->handle());
- }
- return 0;
-}
-
// Syncs the NSWindow minimize/maximize/fullscreen state with the current QWindow state
void QCocoaWindow::syncWindowState(Qt::WindowState newState)
{
@@ -1819,12 +2031,8 @@ void QCocoaWindow::exposeWindow()
// time, and we won't get a NSWindowDidChangeScreenNotification
// on show. The case where the window is initially displayed
// on a non-primary screen needs special handling here.
- NSUInteger screenIndex = [[NSScreen screens] indexOfObject:m_nsWindow.screen];
- if (screenIndex != NSNotFound) {
- QCocoaScreen *cocoaScreen = QCocoaIntegration::instance()->screenAtIndex(screenIndex);
- if (cocoaScreen)
- window()->setScreen(cocoaScreen->screen());
- }
+ if (QCocoaScreen *cocoaScreen = QCocoaIntegration::instance()->screenForNSScreen(m_nsWindow.screen))
+ window()->setScreen(cocoaScreen->screen());
if (!m_isExposed) {
m_isExposed = true;
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index f226547b90..84be7eb797 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -74,7 +74,6 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
QStringList *currentCustomDragTypes;
bool m_sendUpAsRightButton;
Qt::KeyboardModifiers currentWheelModifiers;
- bool m_subscribesForGlobalFrameNotifications;
#ifndef QT_NO_OPENGL
QCocoaGLContext *m_glContext;
bool m_shouldSetGLContextinDrawRect;
@@ -102,7 +101,6 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
- (void)drawBackingStoreUsingCoreGraphics:(NSRect)dirtyRect;
- (void)updateGeometry;
- (void)notifyWindowStateChanged:(Qt::WindowState)newState;
-- (void)windowNotification : (NSNotification *) windowNotification;
- (void)notifyWindowWillZoom:(BOOL)willZoom;
- (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification;
- (void)viewDidHide;
@@ -152,6 +150,11 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
@end
+@interface QT_MANGLE_NAMESPACE(QNSView) (QtExtras)
+@property (nonatomic, readonly) QCocoaWindow *platformWindow;
+@property (nonatomic, readonly) BOOL isMenuView;
+@end
+
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSView);
#endif //QNSVIEW_H
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index a63bc4d570..689fd06d66 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -149,7 +149,6 @@ static bool _q_dontOverrideCtrlLMB = false;
m_acceptedMouseDowns = Qt::NoButton;
m_frameStrutButtons = Qt::NoButton;
m_sendKeyEvent = false;
- m_subscribesForGlobalFrameNotifications = false;
#ifndef QT_NO_OPENGL
m_glContext = 0;
m_shouldSetGLContextinDrawRect = false;
@@ -181,7 +180,6 @@ static bool _q_dontOverrideCtrlLMB = false;
CGImageRelease(m_maskImage);
[m_trackingArea release];
m_maskImage = 0;
- m_subscribesForGlobalFrameNotifications = false;
[m_inputSource release];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[m_mouseMoveHelper release];
@@ -217,11 +215,6 @@ static bool _q_dontOverrideCtrlLMB = false;
#endif
[self registerDragTypes];
- [self setPostsFrameChangedNotifications : YES];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(updateGeometry)
- name:NSViewFrameDidChangeNotification
- object:self];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textInputContextKeyboardSelectionDidChangeNotification:)
@@ -240,27 +233,9 @@ static bool _q_dontOverrideCtrlLMB = false;
//was unable to set view
m_shouldSetGLContextinDrawRect = true;
}
-
- if (!m_subscribesForGlobalFrameNotifications) {
- // NSOpenGLContext expects us to repaint (or update) the view when
- // it changes position on screen. Since this happens unnoticed for
- // the view when the parent view moves, we need to register a special
- // notification that lets us handle this case:
- m_subscribesForGlobalFrameNotifications = true;
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(globalFrameChanged:)
- name:NSViewGlobalFrameDidChangeNotification
- object:self];
- }
}
#endif
-- (void) globalFrameChanged:(NSNotification*)notification
-{
- Q_UNUSED(notification);
- m_platformWindow->updateExposedGeometry();
-}
-
- (void)viewDidMoveToSuperview
{
if (!(m_platformWindow->m_viewIsToBeEmbedded))
@@ -281,22 +256,6 @@ static bool _q_dontOverrideCtrlLMB = false;
m_backingStore = Q_NULLPTR;
}
-- (void)viewWillMoveToWindow:(NSWindow *)newWindow
-{
- // ### Merge "normal" window code path with this one for 5.1.
- if (!(m_platformWindow->window()->type() & Qt::SubWindow))
- return;
-
- if (newWindow) {
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(windowNotification:)
- name:nil // Get all notifications
- object:newWindow];
- }
- if ([self window])
- [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:[self window]];
-}
-
- (QWindow *)topLevelWindow
{
QWindow *focusWindow = m_platformWindow->window();
@@ -316,7 +275,7 @@ static bool _q_dontOverrideCtrlLMB = false;
{
QRect geometry;
- if (m_platformWindow->m_isNSWindowChild) {
+ if (self.window.parentWindow) {
return;
#if 0
//geometry = QRectF::fromCGRect([self frame]).toRect();
@@ -336,10 +295,10 @@ static bool _q_dontOverrideCtrlLMB = false;
geometry = QRect(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height);
} else if (m_platformWindow->m_viewIsToBeEmbedded) {
// embedded child window, use the frame rect ### merge with case below
- geometry = QRectF::fromCGRect([self bounds]).toRect();
+ geometry = QRectF::fromCGRect(NSRectToCGRect([self bounds])).toRect();
} else {
// child window, use the frame rect
- geometry = QRectF::fromCGRect([self frame]).toRect();
+ geometry = QRectF::fromCGRect(NSRectToCGRect([self frame])).toRect();
}
if (m_platformWindow->m_nsWindow && geometry == m_platformWindow->geometry())
@@ -395,64 +354,6 @@ static bool _q_dontOverrideCtrlLMB = false;
m_platformWindow->setSynchedWindowStateFromWindow();
}
-- (void)windowNotification : (NSNotification *) windowNotification
-{
- //qDebug() << "windowNotification" << QString::fromNSString([windowNotification name]);
-
- NSString *notificationName = [windowNotification name];
- if (notificationName == NSWindowDidBecomeKeyNotification) {
- if (!m_platformWindow->windowIsPopupType() && !m_isMenuView)
- QWindowSystemInterface::handleWindowActivated(m_platformWindow->window());
- } else if (notificationName == NSWindowDidResignKeyNotification) {
- // key window will be non-nil if another window became key... do not
- // set the active window to zero here, the new key window's
- // NSWindowDidBecomeKeyNotification hander will change the active window
- NSWindow *keyWindow = [NSApp keyWindow];
- if (!keyWindow || keyWindow == windowNotification.object) {
- // no new key window, go ahead and set the active window to zero
- if (!m_platformWindow->windowIsPopupType() && !m_isMenuView)
- QWindowSystemInterface::handleWindowActivated(0);
- }
- } else if (notificationName == NSWindowDidMiniaturizeNotification
- || notificationName == NSWindowDidDeminiaturizeNotification) {
- Qt::WindowState newState = notificationName == NSWindowDidMiniaturizeNotification ?
- Qt::WindowMinimized : Qt::WindowNoState;
- [self notifyWindowStateChanged:newState];
- } else if ([notificationName isEqualToString: @"NSWindowDidOrderOffScreenNotification"]) {
- m_platformWindow->obscureWindow();
- } else if ([notificationName isEqualToString: @"NSWindowDidOrderOnScreenAndFinishAnimatingNotification"]) {
- m_platformWindow->exposeWindow();
- } else if ([notificationName isEqualToString:NSWindowDidChangeOcclusionStateNotification]) {
- // Several unit tests expect paint and/or expose events for windows that are
- // sometimes (unpredictably) occluded and some unit tests depend on QWindow::isExposed -
- // don't send Expose/Obscure events when running under QTestLib.
- static const bool onTestLib = qt_mac_resolveOption(false, "QT_QTESTLIB_RUNNING");
- if (!onTestLib) {
- if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible) {
- m_platformWindow->exposeWindow();
- } else {
- // Send Obscure events on window occlusion to stop animations.
- m_platformWindow->obscureWindow();
- }
- }
- } else if (notificationName == NSWindowDidChangeScreenNotification) {
- if (m_platformWindow->window()) {
- NSUInteger screenIndex = [[NSScreen screens] indexOfObject:self.window.screen];
- if (screenIndex != NSNotFound) {
- QCocoaScreen *cocoaScreen = QCocoaIntegration::instance()->screenAtIndex(screenIndex);
- if (cocoaScreen)
- QWindowSystemInterface::handleWindowScreenChanged(m_platformWindow->window(), cocoaScreen->screen());
- m_platformWindow->updateExposedGeometry();
- }
- }
- } else if (notificationName == NSWindowDidEnterFullScreenNotification
- || notificationName == NSWindowDidExitFullScreenNotification) {
- Qt::WindowState newState = notificationName == NSWindowDidEnterFullScreenNotification ?
- Qt::WindowFullScreen : Qt::WindowNoState;
- [self notifyWindowStateChanged:newState];
- }
-}
-
- (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification
{
Q_UNUSED(textInputContextKeyboardSelectionDidChangeNotification)
@@ -553,7 +454,7 @@ static bool _q_dontOverrideCtrlLMB = false;
- (void) drawRect:(NSRect)dirtyRect
{
- qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:]" << m_platformWindow->window() << QRectF::fromCGRect(dirtyRect);
+ qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:]" << m_platformWindow->window() << QRectF::fromCGRect(NSRectToCGRect(dirtyRect));
#ifndef QT_NO_OPENGL
if (m_glContext && m_shouldSetGLContextinDrawRect) {
@@ -1336,7 +1237,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
- (bool)handleGestureAsBeginEnd:(NSEvent *)event
{
- if (QSysInfo::QSysInfo::MacintoshVersion < QSysInfo::MV_10_11)
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXElCapitan)
return false;
if ([event phase] == NSEventPhaseBegan) {
@@ -2201,3 +2102,17 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
}
@end
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (QtExtras)
+
+- (QCocoaWindow*)platformWindow
+{
+ return m_platformWindow.data();;
+}
+
+- (BOOL)isMenuView
+{
+ return m_isMenuView;
+}
+
+@end
diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.h b/src/plugins/platforms/cocoa/qnswindowdelegate.h
index f29aa97b68..a465b249c5 100644
--- a/src/plugins/platforms/cocoa/qnswindowdelegate.h
+++ b/src/plugins/platforms/cocoa/qnswindowdelegate.h
@@ -49,15 +49,10 @@
QCocoaWindow *m_cocoaWindow;
}
-- (id)initWithQCocoaWindow: (QCocoaWindow *) cocoaWindow;
+- (id)initWithQCocoaWindow:(QCocoaWindow *)cocoaWindow;
-- (void)windowDidBecomeKey:(NSNotification *)notification;
-- (void)windowDidResize:(NSNotification *)notification;
-- (void)windowDidMove:(NSNotification *)notification;
-- (void)windowWillMove:(NSNotification *)notification;
- (BOOL)windowShouldClose:(NSNotification *)notification;
- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame;
-- (void)windowWillClose:(NSNotification *)notification;
- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu;
- (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard;
diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm
index 7f988ac963..3781a4cc65 100644
--- a/src/plugins/platforms/cocoa/qnswindowdelegate.mm
+++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm
@@ -45,57 +45,12 @@
@implementation QNSWindowDelegate
-- (id) initWithQCocoaWindow: (QCocoaWindow *) cocoaWindow
+- (id)initWithQCocoaWindow:(QCocoaWindow *)cocoaWindow
{
- self = [super init];
-
- if (self) {
+ if (self = [super init])
m_cocoaWindow = cocoaWindow;
- }
- return self;
-}
-
-- (void)windowDidBecomeKey:(NSNotification *)notification
-{
- Q_UNUSED(notification);
- if (m_cocoaWindow->m_windowUnderMouse) {
- QPointF windowPoint;
- QPointF screenPoint;
- [qnsview_cast(m_cocoaWindow->view()) convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
- QWindowSystemInterface::handleEnterEvent(m_cocoaWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint);
- }
-}
-
-- (void)windowDidResize:(NSNotification *)notification
-{
- Q_UNUSED(notification);
- if (m_cocoaWindow) {
- m_cocoaWindow->windowDidResize();
- }
-}
-
-- (void)windowDidEndLiveResize:(NSNotification *)notification
-{
- Q_UNUSED(notification);
- if (m_cocoaWindow) {
- m_cocoaWindow->windowDidEndLiveResize();
- }
-}
-
-- (void)windowWillMove:(NSNotification *)notification
-{
- Q_UNUSED(notification);
- if (m_cocoaWindow) {
- m_cocoaWindow->windowWillMove();
- }
-}
-- (void)windowDidMove:(NSNotification *)notification
-{
- Q_UNUSED(notification);
- if (m_cocoaWindow) {
- m_cocoaWindow->windowDidMove();
- }
+ return self;
}
- (BOOL)windowShouldClose:(NSNotification *)notification
@@ -116,13 +71,6 @@
return YES;
}
-- (void)windowWillClose:(NSNotification *)notification
-{
- Q_UNUSED(notification);
- if (m_cocoaWindow)
- m_cocoaWindow->windowWillClose();
-}
-
- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu
{
Q_UNUSED(window);
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp
index b5065ba380..38425f8fa1 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp
@@ -55,8 +55,9 @@ class QWindowsDirect2DBitmapPrivate
{
public:
QWindowsDirect2DBitmapPrivate(ID2D1DeviceContext *dc = 0, ID2D1Bitmap1 *bm = 0)
- : bitmap(bm)
- , deviceContext(new QWindowsDirect2DDeviceContext(dc))
+ : deviceContext(new QWindowsDirect2DDeviceContext(dc))
+ , bitmap(bm)
+
{
deviceContext->get()->SetTarget(bm);
}
@@ -83,13 +84,13 @@ public:
UINT32(width), UINT32(height)
};
- HRESULT hr = deviceContext->get()->CreateBitmap(size, data, pitch,
+ HRESULT hr = deviceContext->get()->CreateBitmap(size, data, UINT32(pitch),
bitmapProperties(),
bitmap.ReleaseAndGetAddressOf());
if (SUCCEEDED(hr))
deviceContext->get()->SetTarget(bitmap.Get());
else
- qWarning("%s: Could not create bitmap: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create bitmap: %#lx", __FUNCTION__, hr);
return SUCCEEDED(hr);
}
@@ -107,28 +108,28 @@ public:
D2D1_BITMAP_PROPERTIES1 properties = bitmapProperties();
properties.bitmapOptions = D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ;
- hr = deviceContext->get()->CreateBitmap(size, NULL, NULL,
+ hr = deviceContext->get()->CreateBitmap(size, NULL, 0,
properties, &mappingCopy);
if (FAILED(hr)) {
- qWarning("%s: Could not create bitmap: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create bitmap: %#lx", __FUNCTION__, hr);
return QImage();
}
hr = mappingCopy->CopyFromBitmap(NULL, bitmap.Get(), NULL);
if (FAILED(hr)) {
- qWarning("%s: Could not copy from bitmap: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not copy from bitmap: %#lx", __FUNCTION__, hr);
return QImage();
}
D2D1_MAPPED_RECT mappedRect;
hr = mappingCopy->Map(D2D1_MAP_OPTIONS_READ, &mappedRect);
if (FAILED(hr)) {
- qWarning("%s: Could not map: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not map: %#lx", __FUNCTION__, hr);
return QImage();
}
return QImage(static_cast<const uchar *>(mappedRect.bits),
- size.width, size.height, mappedRect.pitch,
+ int(size.width), int(size.height), int(mappedRect.pitch),
QImage::Format_ARGB32_Premultiplied).copy(rect);
}
@@ -197,7 +198,7 @@ QSize QWindowsDirect2DBitmap::size() const
Q_D(const QWindowsDirect2DBitmap);
D2D1_SIZE_U size = d->bitmap->GetPixelSize();
- return QSize(size.width, size.height);
+ return QSize(int(size.width), int(size.height));
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp
index fb5bb43d17..a5817016e6 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp
@@ -84,7 +84,7 @@ public:
}
if (FAILED(hr)) {
- qWarning("%s: Could not create Direct3D Device: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create Direct3D Device: %#lx", __FUNCTION__, hr);
return false;
}
@@ -93,7 +93,7 @@ public:
hr = d3dDevice.As(&dxgiDevice);
if (FAILED(hr)) {
- qWarning("%s: DXGI Device interface query failed on D3D Device: %#x", __FUNCTION__, hr);
+ qWarning("%s: DXGI Device interface query failed on D3D Device: %#lx", __FUNCTION__, hr);
return false;
}
@@ -102,13 +102,13 @@ public:
hr = dxgiDevice->GetAdapter(&dxgiAdapter);
if (FAILED(hr)) {
- qWarning("%s: Failed to probe DXGI Device for parent DXGI Adapter: %#x", __FUNCTION__, hr);
+ qWarning("%s: Failed to probe DXGI Device for parent DXGI Adapter: %#lx", __FUNCTION__, hr);
return false;
}
hr = dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory));
if (FAILED(hr)) {
- qWarning("%s: Failed to probe DXGI Adapter for parent DXGI Factory: %#x", __FUNCTION__, hr);
+ qWarning("%s: Failed to probe DXGI Adapter for parent DXGI Factory: %#lx", __FUNCTION__, hr);
return false;
}
@@ -121,26 +121,26 @@ public:
hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, options, d2dFactory.GetAddressOf());
if (FAILED(hr)) {
- qWarning("%s: Could not create Direct2D Factory: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create Direct2D Factory: %#lx", __FUNCTION__, hr);
return false;
}
hr = d2dFactory->CreateDevice(dxgiDevice.Get(), &d2dDevice);
if (FAILED(hr)) {
- qWarning("%s: Could not create D2D Device: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create D2D Device: %#lx", __FUNCTION__, hr);
return false;
}
hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
static_cast<IUnknown **>(&directWriteFactory));
if (FAILED(hr)) {
- qWarning("%s: Could not create DirectWrite factory: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create DirectWrite factory: %#lx", __FUNCTION__, hr);
return false;
}
hr = directWriteFactory->GetGdiInterop(&directWriteGdiInterop);
if (FAILED(hr)) {
- qWarning("%s: Could not create DirectWrite GDI Interop: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create DirectWrite GDI Interop: %#lx", __FUNCTION__, hr);
return false;
}
@@ -161,7 +161,7 @@ QWindowsDirect2DContext::QWindowsDirect2DContext()
{
}
-QWindowsDirect2DContext::~QWindowsDirect2DContext() {}
+QWindowsDirect2DContext::~QWindowsDirect2DContext() = default;
bool QWindowsDirect2DContext::init()
{
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h
index a3478d2d4e..0d42c65964 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h
@@ -59,7 +59,7 @@ class QWindowsDirect2DContext
public:
QWindowsDirect2DContext();
- virtual ~QWindowsDirect2DContext();
+ ~QWindowsDirect2DContext();
bool init();
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp
index 30238217dd..8a34f6974f 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.cpp
@@ -51,14 +51,13 @@ class QWindowsDirect2DDeviceContextPrivate {
public:
QWindowsDirect2DDeviceContextPrivate(ID2D1DeviceContext *dc)
: deviceContext(dc)
- , refCount(0)
{
if (!dc) {
HRESULT hr = QWindowsDirect2DContext::instance()->d2dDevice()->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
&deviceContext);
if (Q_UNLIKELY(FAILED(hr)))
- qFatal("%s: Couldn't create Direct2D Device Context: %#x", __FUNCTION__, hr);
+ qFatal("%s: Couldn't create Direct2D Device Context: %#lx", __FUNCTION__, hr);
}
Q_ASSERT(deviceContext);
@@ -98,7 +97,7 @@ public:
}
ComPtr<ID2D1DeviceContext> deviceContext;
- int refCount;
+ int refCount = 0;
};
QWindowsDirect2DDeviceContext::QWindowsDirect2DDeviceContext(ID2D1DeviceContext *dc)
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
index da4a4e6ce6..ea51135583 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
@@ -76,12 +76,7 @@ public:
class Direct2DVersion
{
private:
- Direct2DVersion()
- : partOne(0)
- , partTwo(0)
- , partThree(0)
- , partFour(0)
- {}
+ Direct2DVersion() = default;
Direct2DVersion(int one, int two, int three, int four)
: partOne(one)
@@ -108,13 +103,14 @@ public:
if (_tcscat_s(filename, bufSize, __TEXT("\\d2d1.dll")) == 0) {
DWORD versionInfoSize = GetFileVersionInfoSize(filename, NULL);
if (versionInfoSize) {
- QVarLengthArray<BYTE> info(versionInfoSize);
- if (GetFileVersionInfo(filename, NULL, versionInfoSize, info.data())) {
+ QVarLengthArray<BYTE> info(static_cast<int>(versionInfoSize));
+ if (GetFileVersionInfo(filename, 0, versionInfoSize, info.data())) {
UINT size;
DWORD *fi;
- if (VerQueryValue(info.constData(), __TEXT("\\"), (LPVOID *) &fi, &size) && size) {
- VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *) fi;
+ if (VerQueryValue(info.constData(), __TEXT("\\"),
+ reinterpret_cast<void **>(&fi), &size) && size) {
+ const VS_FIXEDFILEINFO *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi);
return Direct2DVersion(HIWORD(verInfo->dwFileVersionMS),
LOWORD(verInfo->dwFileVersionMS),
HIWORD(verInfo->dwFileVersionLS),
@@ -171,7 +167,10 @@ public:
return a - b;
}
- int partOne, partTwo, partThree, partFour;
+ int partOne = 0;
+ int partTwo = 0;
+ int partThree = 0;
+ int partFour = 0;
};
QWindowsDirect2DIntegration *QWindowsDirect2DIntegration::create(const QStringList &paramList)
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
index 29b01391e2..3c86168a74 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.cpp
@@ -93,42 +93,33 @@ int QWindowsDirect2DPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric)
switch (metric) {
case QPaintDevice::PdmWidth:
- return d->bitmap->bitmap()->GetPixelSize().width;
- break;
+ return int(d->bitmap->bitmap()->GetPixelSize().width);
case QPaintDevice::PdmHeight:
- return d->bitmap->bitmap()->GetPixelSize().height;
- break;
+ return int(d->bitmap->bitmap()->GetPixelSize().height);
case QPaintDevice::PdmNumColors:
return INT_MAX;
- break;
case QPaintDevice::PdmDepth:
return 32;
- break;
case QPaintDevice::PdmDpiX:
case QPaintDevice::PdmPhysicalDpiX:
{
FLOAT x, y;
QWindowsDirect2DContext::instance()->d2dFactory()->GetDesktopDpi(&x, &y);
- return x;
+ return qRound(x);
}
- break;
case QPaintDevice::PdmDpiY:
case QPaintDevice::PdmPhysicalDpiY:
{
FLOAT x, y;
QWindowsDirect2DContext::instance()->d2dFactory()->GetDesktopDpi(&x, &y);
- return y;
+ return qRound(y);
}
- break;
case QPaintDevice::PdmDevicePixelRatio:
return 1;
- break;
case QPaintDevice::PdmDevicePixelRatioScaled:
- return 1 * devicePixelRatioFScale();
- break;
+ return qRound(devicePixelRatioFScale());
case QPaintDevice::PdmWidthMM:
case QPaintDevice::PdmHeightMM:
- return -1;
break;
}
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
index c4ff937a0b..164429ba30 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -87,7 +87,7 @@ enum {
};
//Clipping flags
-enum {
+enum : unsigned {
SimpleSystemClip = 0x1
};
@@ -125,28 +125,30 @@ static inline D2D1_MATRIX_3X2_F transformFromLine(const QLineF &line, qreal penW
static void adjustLine(QPointF *p1, QPointF *p2);
static bool isLinePositivelySloped(const QPointF &p1, const QPointF &p2);
-class Direct2DPathGeometryWriter
+static QVector<D2D1_GRADIENT_STOP> qGradientStopsToD2DStops(const QGradientStops &qstops)
{
-public:
- Direct2DPathGeometryWriter()
- : m_inFigure(false)
- , m_roundCoordinates(false)
- , m_adjustPositivelySlopedLines(false)
- {
-
+ QVector<D2D1_GRADIENT_STOP> stops(qstops.count());
+ for (int i = 0, count = stops.size(); i < count; ++i) {
+ stops[i].position = FLOAT(qstops.at(i).first);
+ stops[i].color = to_d2d_color_f(qstops.at(i).second);
}
+ return stops;
+}
+class Direct2DPathGeometryWriter
+{
+public:
bool begin()
{
HRESULT hr = factory()->CreatePathGeometry(&m_geometry);
if (FAILED(hr)) {
- qWarning("%s: Could not create path geometry: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create path geometry: %#lx", __FUNCTION__, hr);
return false;
}
hr = m_geometry->Open(&m_sink);
if (FAILED(hr)) {
- qWarning("%s: Could not create geometry sink: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create geometry sink: %#lx", __FUNCTION__, hr);
return false;
}
@@ -239,9 +241,9 @@ private:
ComPtr<ID2D1PathGeometry1> m_geometry;
ComPtr<ID2D1GeometrySink> m_sink;
- bool m_inFigure;
- bool m_roundCoordinates;
- bool m_adjustPositivelySlopedLines;
+ bool m_inFigure = false;
+ bool m_roundCoordinates = false;
+ bool m_adjustPositivelySlopedLines = false;
QPointF m_previousPoint;
};
@@ -262,7 +264,6 @@ class QWindowsDirect2DPaintEnginePrivate : public QPaintEngineExPrivate
public:
QWindowsDirect2DPaintEnginePrivate(QWindowsDirect2DBitmap *bm, QWindowsDirect2DPaintEngine::Flags flags)
: bitmap(bm)
- , clipFlags(0)
, flags(flags)
{
pen.reset();
@@ -274,7 +275,7 @@ public:
QWindowsDirect2DBitmap *bitmap;
QImage fallbackImage;
- unsigned int clipFlags;
+ unsigned int clipFlags = 0;
QStack<ClipType> pushedClips;
QWindowsDirect2DPaintEngine::Flags flags;
@@ -348,9 +349,9 @@ public:
void updateOpacity(qreal opacity)
{
if (brush.brush)
- brush.brush->SetOpacity(opacity);
+ brush.brush->SetOpacity(FLOAT(opacity));
if (pen.brush)
- pen.brush->SetOpacity(opacity);
+ pen.brush->SetOpacity(FLOAT(opacity));
}
void pushClip(const QVectorPath &path)
@@ -459,7 +460,7 @@ public:
brush.qbrush = newBrush;
if (brush.brush) {
- brush.brush->SetOpacity(q->state()->opacity);
+ brush.brush->SetOpacity(FLOAT(q->state()->opacity));
applyBrushOrigin(currentBrushOrigin);
}
}
@@ -477,8 +478,8 @@ public:
brush.brush->GetTransform(&transform);
brush.brush->SetTransform(*(D2D1::Matrix3x2F::ReinterpretBaseType(&transform))
- * D2D1::Matrix3x2F::Translation(-currentBrushOrigin.x(),
- -currentBrushOrigin.y()));
+ * D2D1::Matrix3x2F::Translation(FLOAT(-currentBrushOrigin.x()),
+ FLOAT(-currentBrushOrigin.y())));
}
}
@@ -489,7 +490,7 @@ public:
brush.brush->GetTransform(&transform);
brush.brush->SetTransform(*(D2D1::Matrix3x2F::ReinterpretBaseType(&transform))
- * D2D1::Matrix3x2F::Translation(origin.x(), origin.y()));
+ * D2D1::Matrix3x2F::Translation(FLOAT(origin.x()), FLOAT(origin.y())));
}
currentBrushOrigin = origin;
@@ -511,7 +512,7 @@ public:
if (!pen.brush)
return;
- pen.brush->SetOpacity(q->state()->opacity);
+ pen.brush->SetOpacity(FLOAT(q->state()->opacity));
D2D1_STROKE_STYLE_PROPERTIES1 props = {};
@@ -541,8 +542,8 @@ public:
break;
}
- props.miterLimit = newPen.miterLimit() * qreal(2.0); // D2D and Qt miter specs differ
- props.dashOffset = newPen.dashOffset();
+ props.miterLimit = FLOAT(newPen.miterLimit() * qreal(2.0)); // D2D and Qt miter specs differ
+ props.dashOffset = FLOAT(newPen.dashOffset());
if (newPen.widthF() == 0)
props.transformType = D2D1_STROKE_TRANSFORM_TYPE_HAIRLINE;
@@ -577,24 +578,24 @@ public:
qreal penWidth = pen.qpen.widthF();
qreal brushWidth = 0;
for (int i = 0; i < dashes.size(); i++) {
- converted[i] = dashes[i];
+ converted[i] = FLOAT(dashes[i]);
brushWidth += penWidth * dashes[i];
}
- hr = factory()->CreateStrokeStyle(props, converted.constData(), converted.size(), &pen.strokeStyle);
+ hr = factory()->CreateStrokeStyle(props, converted.constData(), UINT32(converted.size()), &pen.strokeStyle);
// Create a combined brush/dash pattern for optimized line drawing
QWindowsDirect2DBitmap bitmap;
- bitmap.resize(ceil(brushWidth), ceil(penWidth));
+ bitmap.resize(int(ceil(brushWidth)), int(ceil(penWidth)));
bitmap.deviceContext()->begin();
bitmap.deviceContext()->get()->SetAntialiasMode(antialiasMode());
bitmap.deviceContext()->get()->SetTransform(D2D1::IdentityMatrix());
bitmap.deviceContext()->get()->Clear();
const qreal offsetX = (qreal(bitmap.size().width()) - brushWidth) / 2;
const qreal offsetY = qreal(bitmap.size().height()) / 2;
- bitmap.deviceContext()->get()->DrawLine(D2D1::Point2F(offsetX, offsetY),
- D2D1::Point2F(brushWidth, offsetY),
- pen.brush.Get(), penWidth, pen.strokeStyle.Get());
+ bitmap.deviceContext()->get()->DrawLine(D2D1::Point2F(FLOAT(offsetX), FLOAT(offsetY)),
+ D2D1::Point2F(FLOAT(brushWidth), FLOAT(offsetY)),
+ pen.brush.Get(), FLOAT(penWidth), pen.strokeStyle.Get());
bitmap.deviceContext()->end();
D2D1_BITMAP_BRUSH_PROPERTIES1 bitmapBrushProperties = D2D1::BitmapBrushProperties1(
D2D1_EXTEND_MODE_WRAP, D2D1_EXTEND_MODE_CLAMP, D2D1_INTERPOLATION_MODE_LINEAR);
@@ -605,7 +606,7 @@ public:
}
if (FAILED(hr))
- qWarning("%s: Could not create stroke style: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create stroke style: %#lx", __FUNCTION__, hr);
}
ComPtr<ID2D1Brush> to_d2d_brush(const QBrush &newBrush, bool *needsEmulation)
@@ -627,13 +628,13 @@ public:
hr = dc()->CreateSolidColorBrush(to_d2d_color_f(newBrush.color()), &solid);
if (FAILED(hr)) {
- qWarning("%s: Could not create solid color brush: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create solid color brush: %#lx", __FUNCTION__, hr);
break;
}
hr = solid.As(&result);
if (FAILED(hr))
- qWarning("%s: Could not convert solid color brush: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not convert solid color brush: %#lx", __FUNCTION__, hr);
}
break;
@@ -673,13 +674,13 @@ public:
bitmapBrushProperties,
&bitmapBrush);
if (FAILED(hr)) {
- qWarning("%s: Could not create Direct2D bitmap brush for Qt pattern brush: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create Direct2D bitmap brush for Qt pattern brush: %#lx", __FUNCTION__, hr);
break;
}
hr = bitmapBrush.As(&result);
if (FAILED(hr))
- qWarning("%s: Could not convert Direct2D bitmap brush for Qt pattern brush: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not convert Direct2D bitmap brush for Qt pattern brush: %#lx", __FUNCTION__, hr);
}
break;
@@ -693,33 +694,29 @@ public:
D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES linearGradientBrushProperties;
ComPtr<ID2D1GradientStopCollection> gradientStopCollection;
- const QGradientStops &qstops = qlinear->stops();
- QVector<D2D1_GRADIENT_STOP> stops(qstops.count());
-
linearGradientBrushProperties.startPoint = to_d2d_point_2f(qlinear->start());
linearGradientBrushProperties.endPoint = to_d2d_point_2f(qlinear->finalStop());
- for (int i = 0; i < stops.size(); i++) {
- stops[i].position = qstops[i].first;
- stops[i].color = to_d2d_color_f(qstops[i].second);
- }
+ const QVector<D2D1_GRADIENT_STOP> stops = qGradientStopsToD2DStops(qlinear->stops());
- hr = dc()->CreateGradientStopCollection(stops.constData(), stops.size(), &gradientStopCollection);
+ hr = dc()->CreateGradientStopCollection(stops.constData(),
+ UINT32(stops.size()),
+ &gradientStopCollection);
if (FAILED(hr)) {
- qWarning("%s: Could not create gradient stop collection for linear gradient: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create gradient stop collection for linear gradient: %#lx", __FUNCTION__, hr);
break;
}
hr = dc()->CreateLinearGradientBrush(linearGradientBrushProperties, gradientStopCollection.Get(),
&linear);
if (FAILED(hr)) {
- qWarning("%s: Could not create Direct2D linear gradient brush: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create Direct2D linear gradient brush: %#lx", __FUNCTION__, hr);
break;
}
hr = linear.As(&result);
if (FAILED(hr)) {
- qWarning("%s: Could not convert Direct2D linear gradient brush: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not convert Direct2D linear gradient brush: %#lx", __FUNCTION__, hr);
break;
}
}
@@ -735,35 +732,29 @@ public:
D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES radialGradientBrushProperties;
ComPtr<ID2D1GradientStopCollection> gradientStopCollection;
- const QGradientStops &qstops = qradial->stops();
- QVector<D2D1_GRADIENT_STOP> stops(qstops.count());
-
radialGradientBrushProperties.center = to_d2d_point_2f(qradial->center());
radialGradientBrushProperties.gradientOriginOffset = to_d2d_point_2f(qradial->focalPoint() - qradial->center());
- radialGradientBrushProperties.radiusX = qradial->radius();
- radialGradientBrushProperties.radiusY = qradial->radius();
+ radialGradientBrushProperties.radiusX = FLOAT(qradial->radius());
+ radialGradientBrushProperties.radiusY = FLOAT(qradial->radius());
- for (int i = 0; i < stops.size(); i++) {
- stops[i].position = qstops[i].first;
- stops[i].color = to_d2d_color_f(qstops[i].second);
- }
+ const QVector<D2D1_GRADIENT_STOP> stops = qGradientStopsToD2DStops(qradial->stops());
hr = dc()->CreateGradientStopCollection(stops.constData(), stops.size(), &gradientStopCollection);
if (FAILED(hr)) {
- qWarning("%s: Could not create gradient stop collection for radial gradient: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create gradient stop collection for radial gradient: %#lx", __FUNCTION__, hr);
break;
}
hr = dc()->CreateRadialGradientBrush(radialGradientBrushProperties, gradientStopCollection.Get(),
&radial);
if (FAILED(hr)) {
- qWarning("%s: Could not create Direct2D radial gradient brush: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create Direct2D radial gradient brush: %#lx", __FUNCTION__, hr);
break;
}
radial.As(&result);
if (FAILED(hr)) {
- qWarning("%s: Could not convert Direct2D radial gradient brush: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not convert Direct2D radial gradient brush: %#lx", __FUNCTION__, hr);
break;
}
}
@@ -789,13 +780,13 @@ public:
&bitmapBrush);
if (FAILED(hr)) {
- qWarning("%s: Could not create texture brush: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create texture brush: %#lx", __FUNCTION__, hr);
break;
}
hr = bitmapBrush.As(&result);
if (FAILED(hr))
- qWarning("%s: Could not convert texture brush: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not convert texture brush: %#lx", __FUNCTION__, hr);
}
break;
}
@@ -958,7 +949,8 @@ public:
qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__);
return;
}
- dc()->DrawGeometry(geometry.Get(), pen.brush.Get(), pen.qpen.widthF(), pen.strokeStyle.Get());
+ dc()->DrawGeometry(geometry.Get(), pen.brush.Get(),
+ FLOAT(pen.qpen.widthF()), pen.strokeStyle.Get());
return;
}
@@ -998,7 +990,7 @@ public:
dashOffset = pen.dashLength - fmod(lineLength - dashOffset, pen.dashLength);
}
dc()->DrawLine(to_d2d_point_2f(p1), to_d2d_point_2f(p2),
- brush, pen.qpen.widthF(), NULL);
+ brush, FLOAT(pen.qpen.widthF()), NULL);
if (skipJoin)
continue;
@@ -1013,7 +1005,8 @@ public:
writer.lineTo(p1);
writer.lineTo(line.pointAt(patchSegment));
writer.close();
- dc()->DrawGeometry(writer.geometry().Get(), pen.brush.Get(), pen.qpen.widthF(), pen.strokeStyle.Get());
+ dc()->DrawGeometry(writer.geometry().Get(), pen.brush.Get(),
+ FLOAT(pen.qpen.widthF()), pen.strokeStyle.Get());
}
// Record the start position of the next joint
jointStart = line.pointAt(1 - patchSegment);
@@ -1025,7 +1018,8 @@ public:
writer.lineTo(p2);
writer.lineTo(QLineF(p2, QPointF(points[2], points[3])).pointAt(patchSegment));
writer.close();
- dc()->DrawGeometry(writer.geometry().Get(), pen.brush.Get(), pen.qpen.widthF(), pen.strokeStyle.Get());
+ dc()->DrawGeometry(writer.geometry().Get(), pen.brush.Get(),
+ FLOAT(pen.qpen.widthF()), pen.strokeStyle.Get());
}
}
}
@@ -1045,20 +1039,20 @@ public:
const QString nameSubstitute = QSettings(QLatin1String(keyC), QSettings::NativeFormat).value(familyName, familyName).toString();
if (nameSubstitute != familyName) {
const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1);
- memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t));
+ memcpy(lf.lfFaceName, nameSubstitute.utf16(), size_t(nameSubstituteLength) * sizeof(wchar_t));
lf.lfFaceName[nameSubstituteLength] = 0;
}
ComPtr<IDWriteFont> dwriteFont;
HRESULT hr = QWindowsDirect2DContext::instance()->dwriteGdiInterop()->CreateFontFromLOGFONT(&lf, &dwriteFont);
if (FAILED(hr)) {
- qDebug("%s: CreateFontFromLOGFONT failed: %#x", __FUNCTION__, hr);
+ qDebug("%s: CreateFontFromLOGFONT failed: %#lx", __FUNCTION__, hr);
return fontFace;
}
hr = dwriteFont->CreateFontFace(&fontFace);
if (FAILED(hr)) {
- qDebug("%s: CreateFontFace failed: %#x", __FUNCTION__, hr);
+ qDebug("%s: CreateFontFace failed: %#lx", __FUNCTION__, hr);
return fontFace;
}
@@ -1332,7 +1326,8 @@ void QWindowsDirect2DPaintEngine::drawRects(const QRect *rects, int rectCount)
d->dc()->FillRectangle(d2d_rect, d->brush.brush.Get());
if (d->pen.brush)
- d->dc()->DrawRectangle(d2d_rect, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
+ d->dc()->DrawRectangle(d2d_rect, d->pen.brush.Get(),
+ FLOAT(d->pen.qpen.widthF()), d->pen.strokeStyle.Get());
}
}
}
@@ -1359,7 +1354,8 @@ void QWindowsDirect2DPaintEngine::drawRects(const QRectF *rects, int rectCount)
d->dc()->FillRectangle(d2d_rect, d->brush.brush.Get());
if (d->pen.brush)
- d->dc()->DrawRectangle(d2d_rect, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
+ d->dc()->DrawRectangle(d2d_rect, d->pen.brush.Get(),
+ FLOAT(d->pen.qpen.widthF()), d->pen.strokeStyle.Get());
}
}
}
@@ -1407,7 +1403,9 @@ void QWindowsDirect2DPaintEngine::drawEllipse(const QRectF &r)
d->dc()->FillEllipse(ellipse, d->brush.brush.Get());
if (d->pen.brush)
- d->dc()->DrawEllipse(ellipse, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
+ d->dc()->DrawEllipse(ellipse, d->pen.brush.Get(),
+ FLOAT(d->pen.qpen.widthF()),
+ d->pen.strokeStyle.Get());
}
}
@@ -1435,7 +1433,9 @@ void QWindowsDirect2DPaintEngine::drawEllipse(const QRect &r)
d->dc()->FillEllipse(ellipse, d->brush.brush.Get());
if (d->pen.brush)
- d->dc()->DrawEllipse(ellipse, d->pen.brush.Get(), d->pen.qpen.widthF(), d->pen.strokeStyle.Get());
+ d->dc()->DrawEllipse(ellipse, d->pen.brush.Get(),
+ FLOAT(d->pen.qpen.widthF()),
+ d->pen.strokeStyle.Get());
}
}
@@ -1490,12 +1490,12 @@ void QWindowsDirect2DPaintEngine::drawPixmap(const QRectF &r,
// Good, src bitmap != dst bitmap
if (sr.isValid())
d->dc()->DrawBitmap(bitmap->bitmap(),
- to_d2d_rect_f(r), state()->opacity,
+ to_d2d_rect_f(r), FLOAT(state()->opacity),
d->interpolationMode(),
to_d2d_rect_f(sr));
else
d->dc()->DrawBitmap(bitmap->bitmap(),
- to_d2d_rect_f(r), state()->opacity,
+ to_d2d_rect_f(r), FLOAT(state()->opacity),
d->interpolationMode());
} else {
// Ok, so the source pixmap and destination pixmap is the same.
@@ -1504,7 +1504,7 @@ void QWindowsDirect2DPaintEngine::drawPixmap(const QRectF &r,
QWindowsDirect2DBitmap intermediate;
if (sr.isValid()) {
- bool r = intermediate.resize(sr.width(), sr.height());
+ bool r = intermediate.resize(int(sr.width()), int(sr.height()));
if (!r) {
qWarning("%s: Could not resize intermediate bitmap to source rect size", __FUNCTION__);
return;
@@ -1515,7 +1515,7 @@ void QWindowsDirect2DPaintEngine::drawPixmap(const QRectF &r,
bitmap->bitmap(),
&d2d_sr);
if (FAILED(hr)) {
- qWarning("%s: Could not copy source rect area from source bitmap to intermediate bitmap: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not copy source rect area from source bitmap to intermediate bitmap: %#lx", __FUNCTION__, hr);
return;
}
} else {
@@ -1530,13 +1530,13 @@ void QWindowsDirect2DPaintEngine::drawPixmap(const QRectF &r,
bitmap->bitmap(),
NULL);
if (FAILED(hr)) {
- qWarning("%s: Could not copy source bitmap to intermediate bitmap: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not copy source bitmap to intermediate bitmap: %#lx", __FUNCTION__, hr);
return;
}
}
d->dc()->DrawBitmap(intermediate.bitmap(),
- to_d2d_rect_f(r), state()->opacity,
+ to_d2d_rect_f(r), FLOAT(state()->opacity),
d->interpolationMode());
}
}
@@ -1573,9 +1573,9 @@ void QWindowsDirect2DPaintEngine::drawStaticTextItem(QStaticTextItem *staticText
// This looks a little funky because the positions are precalculated
glyphAdvances[i] = 0;
- glyphOffsets[i].advanceOffset = staticTextItem->glyphPositions[i].x.toReal();
+ glyphOffsets[i].advanceOffset = FLOAT(staticTextItem->glyphPositions[i].x.toReal());
// Qt and Direct2D seem to disagree on the direction of the ascender offset...
- glyphOffsets[i].ascenderOffset = staticTextItem->glyphPositions[i].y.toReal() * -1;
+ glyphOffsets[i].ascenderOffset = FLOAT(staticTextItem->glyphPositions[i].y.toReal() * -1);
}
d->drawGlyphRun(D2D1::Point2F(0, 0),
@@ -1618,11 +1618,11 @@ void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem
for (int i = 0; i < ti.glyphs.numGlyphs; i++) {
glyphIndices[i] = UINT16(ti.glyphs.glyphs[i]); // Imperfect conversion here
- glyphAdvances[i] = ti.glyphs.effectiveAdvance(i).toReal();
- glyphOffsets[i].advanceOffset = ti.glyphs.offsets[i].x.toReal();
+ glyphAdvances[i] = FLOAT(ti.glyphs.effectiveAdvance(i).toReal());
+ glyphOffsets[i].advanceOffset = FLOAT(ti.glyphs.offsets[i].x.toReal());
// XXX Should we negate the y value like for static text items?
- glyphOffsets[i].ascenderOffset = ti.glyphs.offsets[i].y.toReal();
+ glyphOffsets[i].ascenderOffset = FLOAT(ti.glyphs.offsets[i].y.toReal());
}
const bool rtl = (ti.flags & QTextItem::RightToLeft);
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
index e7e2fa4ff7..65e056d312 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
@@ -57,15 +57,12 @@ public:
: owns_bitmap(true)
, bitmap(new QWindowsDirect2DBitmap)
, device(new QWindowsDirect2DPaintDevice(bitmap, QInternal::Pixmap))
- , devicePixelRatio(1.0)
{}
QWindowsDirect2DPlatformPixmapPrivate(QWindowsDirect2DBitmap *bitmap,
QWindowsDirect2DPaintEngine::Flags flags)
- : owns_bitmap(false)
- , bitmap(bitmap)
+ : bitmap(bitmap)
, device(new QWindowsDirect2DPaintDevice(bitmap, QInternal::Pixmap, flags))
- , devicePixelRatio(1.0)
{}
~QWindowsDirect2DPlatformPixmapPrivate()
@@ -74,10 +71,10 @@ public:
delete bitmap;
}
- bool owns_bitmap;
+ bool owns_bitmap = false;
QWindowsDirect2DBitmap *bitmap;
QScopedPointer<QWindowsDirect2DPaintDevice> device;
- qreal devicePixelRatio;
+ qreal devicePixelRatio = 1.0;
};
static int qt_d2dpixmap_serno = 0;
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
index c750b02078..21294cfb15 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
@@ -54,7 +54,6 @@ QT_BEGIN_NAMESPACE
QWindowsDirect2DWindow::QWindowsDirect2DWindow(QWindow *window, const QWindowsWindowData &data)
: QWindowsWindow(window, data)
- , m_needsFullFlush(true)
, m_directRendering(!(data.flags & Qt::FramelessWindowHint && window->format().hasAlpha()))
{
if (window->type() == Qt::Desktop)
@@ -67,7 +66,7 @@ QWindowsDirect2DWindow::QWindowsDirect2DWindow(QWindow *window, const QWindowsWi
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
m_deviceContext.GetAddressOf());
if (FAILED(hr))
- qWarning("%s: Couldn't create Direct2D Device context: %#x", __FUNCTION__, hr);
+ qWarning("%s: Couldn't create Direct2D Device context: %#lx", __FUNCTION__, hr);
}
QWindowsDirect2DWindow::~QWindowsDirect2DWindow()
@@ -100,12 +99,12 @@ void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion
HRESULT hr = m_swapChain->GetDesc1(&desc);
QRect geom = geometry();
- if ((FAILED(hr) || (desc.Width != geom.width()) || (desc.Height != geom.height()))) {
+ if (FAILED(hr) || (desc.Width != UINT(geom.width()) || (desc.Height != UINT(geom.height())))) {
resizeSwapChain(geom.size());
m_swapChain->GetDesc1(&desc);
}
- size.setWidth(desc.Width);
- size.setHeight(desc.Height);
+ size.setWidth(int(desc.Width));
+ size.setHeight(int(desc.Height));
} else {
size = geometry().size();
}
@@ -175,7 +174,7 @@ void QWindowsDirect2DWindow::present(const QRegion &region)
UPDATELAYEREDWINDOWINFO info = { sizeof(UPDATELAYEREDWINDOWINFO), NULL,
&ptDst, &size, hdc, &ptSrc, 0, &blend, ULW_ALPHA, &dirty };
if (!UpdateLayeredWindowIndirect(handle(), &info))
- qErrnoWarning(GetLastError(), "Failed to update the layered window");
+ qErrnoWarning(int(GetLastError()), "Failed to update the layered window");
hr = dxgiSurface->ReleaseDC(NULL);
if (FAILED(hr))
@@ -201,7 +200,7 @@ void QWindowsDirect2DWindow::setupSwapChain()
m_swapChain.ReleaseAndGetAddressOf()); // [out] IDXGISwapChain1 **ppSwapChain
if (FAILED(hr))
- qWarning("%s: Could not create swap chain: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create swap chain: %#lx", __FUNCTION__, hr);
m_needsFullFlush = true;
}
@@ -217,11 +216,11 @@ void QWindowsDirect2DWindow::resizeSwapChain(const QSize &size)
return;
HRESULT hr = m_swapChain->ResizeBuffers(0,
- size.width(), size.height(),
+ UINT(size.width()), UINT(size.height()),
DXGI_FORMAT_UNKNOWN,
0);
if (FAILED(hr))
- qWarning("%s: Could not resize swap chain: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not resize swap chain: %#lx", __FUNCTION__, hr);
}
QSharedPointer<QWindowsDirect2DBitmap> QWindowsDirect2DWindow::copyBackBuffer() const
@@ -248,13 +247,13 @@ QSharedPointer<QWindowsDirect2DBitmap> QWindowsDirect2DWindow::copyBackBuffer()
HRESULT hr = m_deviceContext.Get()->CreateBitmap(size, NULL, 0, properties, &copy);
if (FAILED(hr)) {
- qWarning("%s: Could not create staging bitmap: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create staging bitmap: %#lx", __FUNCTION__, hr);
return null_result;
}
hr = copy.Get()->CopyFromBitmap(NULL, m_bitmap->bitmap(), NULL);
if (FAILED(hr)) {
- qWarning("%s: Could not copy from bitmap! %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not copy from bitmap! %#lx", __FUNCTION__, hr);
return null_result;
}
@@ -277,12 +276,12 @@ void QWindowsDirect2DWindow::setupBitmap()
if (m_directRendering) {
hr = m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBufferSurface));
if (FAILED(hr)) {
- qWarning("%s: Could not query backbuffer for DXGI Surface: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not query backbuffer for DXGI Surface: %#lx", __FUNCTION__, hr);
return;
}
} else {
const QRect rect = geometry();
- CD3D11_TEXTURE2D_DESC backBufferDesc(DXGI_FORMAT_B8G8R8A8_UNORM, rect.width(), rect.height(), 1, 1);
+ CD3D11_TEXTURE2D_DESC backBufferDesc(DXGI_FORMAT_B8G8R8A8_UNORM, UINT(rect.width()), UINT(rect.height()), 1, 1);
backBufferDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
backBufferDesc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
ComPtr<ID3D11Texture2D> backBufferTexture;
@@ -302,7 +301,7 @@ void QWindowsDirect2DWindow::setupBitmap()
ComPtr<ID2D1Bitmap1> backBufferBitmap;
hr = m_deviceContext->CreateBitmapFromDxgiSurface(backBufferSurface.Get(), NULL, backBufferBitmap.GetAddressOf());
if (FAILED(hr)) {
- qWarning("%s: Could not create Direct2D Bitmap from DXGI Surface: %#x", __FUNCTION__, hr);
+ qWarning("%s: Could not create Direct2D Bitmap from DXGI Surface: %#lx", __FUNCTION__, hr);
return;
}
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
index 2da0e5f507..156d4660d1 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
@@ -74,8 +74,8 @@ private:
Microsoft::WRL::ComPtr<ID2D1DeviceContext> m_deviceContext;
QScopedPointer<QWindowsDirect2DBitmap> m_bitmap;
QScopedPointer<QPixmap> m_pixmap;
- bool m_needsFullFlush;
- bool m_directRendering;
+ bool m_needsFullFlush = true;
+ bool m_directRendering = false;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/api/api.pri b/src/plugins/platforms/eglfs/api/api.pri
index 0ea65bd1ff..a6d81016b6 100644
--- a/src/plugins/platforms/eglfs/api/api.pri
+++ b/src/plugins/platforms/eglfs/api/api.pri
@@ -1,21 +1,26 @@
SOURCES += $$PWD/qeglfswindow.cpp \
$$PWD/qeglfsscreen.cpp \
- $$PWD/qeglfscursor.cpp \
$$PWD/qeglfshooks.cpp \
$$PWD/qeglfsdeviceintegration.cpp \
$$PWD/qeglfsintegration.cpp \
- $$PWD/qeglfscontext.cpp \
$$PWD/qeglfsoffscreenwindow.cpp
HEADERS += $$PWD/qeglfswindow_p.h \
$$PWD/qeglfsscreen_p.h \
- $$PWD/qeglfscursor_p.h \
$$PWD/qeglfshooks_p.h \
$$PWD/qeglfsdeviceintegration_p.h \
$$PWD/qeglfsintegration_p.h \
- $$PWD/qeglfscontext_p.h \
$$PWD/qeglfsoffscreenwindow_p.h \
$$PWD/qeglfsglobal_p.h
+qtConfig(opengl) {
+ SOURCES += \
+ $$PWD/qeglfscursor.cpp \
+ $$PWD/qeglfscontext.cpp
+ HEADERS += \
+ $$PWD/qeglfscursor_p.h \
+ $$PWD/qeglfscontext_p.h
+}
+
INCLUDEPATH += $$PWD
diff --git a/src/plugins/platforms/eglfs/api/qeglfscontext_p.h b/src/plugins/platforms/eglfs/api/qeglfscontext_p.h
index ab5bf99c3c..96f7f01381 100644
--- a/src/plugins/platforms/eglfs/api/qeglfscontext_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfscontext_p.h
@@ -62,11 +62,11 @@ class Q_EGLFS_EXPORT QEglFSContext : public QEGLPlatformContext
public:
QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
EGLConfig *config, const QVariant &nativeHandle);
- EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- EGLSurface createTemporaryOffscreenSurface() Q_DECL_OVERRIDE;
- void destroyTemporaryOffscreenSurface(EGLSurface surface) Q_DECL_OVERRIDE;
- void runGLChecks() Q_DECL_OVERRIDE;
- void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
+ EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) override;
+ EGLSurface createTemporaryOffscreenSurface() override;
+ void destroyTemporaryOffscreenSurface(EGLSurface surface) override;
+ void runGLChecks() override;
+ void swapBuffers(QPlatformSurface *surface) override;
private:
EGLNativeWindowType m_tempWindow;
diff --git a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp
index 2b54251a06..19a0e03212 100644
--- a/src/plugins/platforms/eglfs/api/qeglfscursor.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfscursor.cpp
@@ -146,8 +146,8 @@ void QEglFSCursor::createShaderPrograms()
GraphicsContextData &gfx(m_gfx[QOpenGLContext::currentContext()]);
gfx.program = new QOpenGLShaderProgram;
- gfx.program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
- gfx.program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
+ gfx.program->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
+ gfx.program->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
gfx.program->bindAttributeLocation("vertexCoordEntry", 0);
gfx.program->bindAttributeLocation("textureCoordEntry", 1);
gfx.program->link();
diff --git a/src/plugins/platforms/eglfs/api/qeglfscursor_p.h b/src/plugins/platforms/eglfs/api/qeglfscursor_p.h
index bf6dbc8a21..942fb09aac 100644
--- a/src/plugins/platforms/eglfs/api/qeglfscursor_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfscursor_p.h
@@ -87,11 +87,11 @@ public:
~QEglFSCursor();
#ifndef QT_NO_CURSOR
- void changeCursor(QCursor *cursor, QWindow *widget) Q_DECL_OVERRIDE;
+ void changeCursor(QCursor *cursor, QWindow *widget) override;
#endif
- void pointerEvent(const QMouseEvent &event) Q_DECL_OVERRIDE;
- QPoint pos() const Q_DECL_OVERRIDE;
- void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
+ void pointerEvent(const QMouseEvent &event) override;
+ QPoint pos() const override;
+ void setPos(const QPoint &pos) override;
QRect cursorRect() const;
void paintOnScreen();
@@ -100,7 +100,7 @@ public:
void updateMouseStatus();
private:
- bool event(QEvent *e) Q_DECL_OVERRIDE;
+ bool event(QEvent *e) override;
#ifndef QT_NO_CURSOR
bool setCurrentCursor(QCursor *cursor);
#endif
diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
index 3e1e93f1e4..80708fd17a 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
@@ -39,7 +39,9 @@
#include "qeglfsdeviceintegration_p.h"
#include "qeglfsintegration_p.h"
-#include "qeglfscursor_p.h"
+#ifndef QT_NO_OPENGL
+# include "qeglfscursor_p.h"
+#endif
#include "qeglfswindow_p.h"
#include "qeglfsscreen_p.h"
#include "qeglfshooks_p.h"
@@ -312,7 +314,12 @@ bool QEglFSDeviceIntegration::hasCapability(QPlatformIntegration::Capability cap
QPlatformCursor *QEglFSDeviceIntegration::createCursor(QPlatformScreen *screen) const
{
+#ifndef QT_NO_OPENGL
return new QEglFSCursor(static_cast<QEglFSScreen *>(screen));
+#else
+ Q_UNUSED(screen);
+ return nullptr;
+#endif
}
void QEglFSDeviceIntegration::waitForVSync(QPlatformSurface *surface) const
@@ -355,7 +362,7 @@ EGLConfig QEglFSDeviceIntegration::chooseConfig(EGLDisplay display, const QSurfa
public:
Chooser(EGLDisplay display)
: QEglConfigChooser(display) { }
- bool filterConfig(EGLConfig config) const Q_DECL_OVERRIDE {
+ bool filterConfig(EGLConfig config) const override {
return qt_egl_device_integration()->filterConfig(display(), config)
&& QEglConfigChooser::filterConfig(config);
}
diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
index 8cf6660c44..190f5a80d0 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
@@ -42,9 +42,11 @@
#include <qpa/qplatformwindow.h>
#include <QtGui/QSurfaceFormat>
-#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
-#include <QtGui/QOffscreenSurface>
+#ifndef QT_NO_OPENGL
+# include <QtGui/QOpenGLContext>
+# include <QtGui/QOffscreenSurface>
+#endif
#include <QtGui/QWindow>
#include <QtCore/QLoggingCategory>
#include <qpa/qwindowsysteminterface.h>
@@ -53,20 +55,26 @@
#include "qeglfsintegration_p.h"
#include "qeglfswindow_p.h"
#include "qeglfshooks_p.h"
-#include "qeglfscontext_p.h"
+#ifndef QT_NO_OPENGL
+# include "qeglfscontext_p.h"
+# include "qeglfscursor_p.h"
+#endif
#include "qeglfsoffscreenwindow_p.h"
-#include "qeglfscursor_p.h"
#include <QtEglSupport/private/qeglconvenience_p.h>
-#include <QtEglSupport/private/qeglplatformcontext_p.h>
-#include <QtEglSupport/private/qeglpbuffer_p.h>
+#ifndef QT_NO_OPENGL
+# include <QtEglSupport/private/qeglplatformcontext_p.h>
+# include <QtEglSupport/private/qeglpbuffer_p.h>
+#endif
#include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h>
#include <QtServiceSupport/private/qgenericunixservices_p.h>
#include <QtThemeSupport/private/qgenericunixthemes_p.h>
#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
#include <QtFbSupport/private/qfbvthandler_p.h>
-#include <QtPlatformCompositorSupport/private/qopenglcompositorbackingstore_p.h>
+#ifndef QT_NO_OPENGL
+# include <QtPlatformCompositorSupport/private/qopenglcompositorbackingstore_p.h>
+#endif
#include <QtPlatformHeaders/QEGLNativeContext>
@@ -179,11 +187,15 @@ QPlatformTheme *QEglFSIntegration::createPlatformTheme(const QString &name) cons
QPlatformBackingStore *QEglFSIntegration::createPlatformBackingStore(QWindow *window) const
{
+#ifndef QT_NO_OPENGL
QOpenGLCompositorBackingStore *bs = new QOpenGLCompositorBackingStore(window);
if (!window->handle())
window->create();
static_cast<QEglFSWindow *>(window->handle())->setBackingStore(bs);
return bs;
+#else
+ return nullptr;
+#endif
}
QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const
@@ -196,6 +208,7 @@ QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const
return w;
}
+#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *QEglFSIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
EGLDisplay dpy = context->screen() ? static_cast<QEglFSScreen *>(context->screen()->handle())->display() : display();
@@ -230,6 +243,7 @@ QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOf
}
// Never return null. Multiple QWindows are not supported by this plugin.
}
+#endif // QT_NO_OPENGL
bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
@@ -239,10 +253,16 @@ bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
switch (cap) {
case ThreadedPixmaps: return true;
+#ifndef QT_NO_OPENGL
case OpenGL: return true;
case ThreadedOpenGL: return true;
- case WindowManagement: return false;
case RasterGLSurface: return true;
+#else
+ case OpenGL: return false;
+ case ThreadedOpenGL: return false;
+ case RasterGLSurface: return false;
+#endif
+ case WindowManagement: return false;
default: return QPlatformIntegration::hasCapability(cap);
}
}
@@ -259,7 +279,8 @@ enum ResourceType {
EglConfig,
NativeDisplay,
XlibDisplay,
- WaylandDisplay
+ WaylandDisplay,
+ EglSurface
};
static int resourceType(const QByteArray &key)
@@ -271,7 +292,8 @@ static int resourceType(const QByteArray &key)
QByteArrayLiteral("eglconfig"),
QByteArrayLiteral("nativedisplay"),
QByteArrayLiteral("display"),
- QByteArrayLiteral("server_wl_display")
+ QByteArrayLiteral("server_wl_display"),
+ QByteArrayLiteral("eglsurface")
};
const QByteArray *end = names + sizeof(names) / sizeof(names[0]);
const QByteArray *result = std::find(names, end, key);
@@ -333,6 +355,10 @@ void *QEglFSIntegration::nativeResourceForWindow(const QByteArray &resource, QWi
if (window && window->handle())
result = reinterpret_cast<void*>(static_cast<QEglFSWindow *>(window->handle())->eglWindow());
break;
+ case EglSurface:
+ if (window && window->handle())
+ result = reinterpret_cast<void*>(static_cast<QEglFSWindow *>(window->handle())->surface());
+ break;
default:
break;
}
@@ -340,6 +366,7 @@ void *QEglFSIntegration::nativeResourceForWindow(const QByteArray &resource, QWi
return result;
}
+#ifndef QT_NO_OPENGL
void *QEglFSIntegration::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
{
void *result = 0;
@@ -374,13 +401,17 @@ static void *eglContextForContext(QOpenGLContext *context)
return handle->eglContext();
}
+#endif
QPlatformNativeInterface::NativeResourceForContextFunction QEglFSIntegration::nativeResourceFunctionForContext(const QByteArray &resource)
{
+#ifndef QT_NO_OPENGL
QByteArray lowerCaseResource = resource.toLower();
if (lowerCaseResource == "get_egl_context")
return NativeResourceForContextFunction(eglContextForContext);
-
+#else
+ Q_UNUSED(resource);
+#endif
return 0;
}
diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h
index 1a3a44d441..080c8ed332 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h
@@ -69,34 +69,37 @@ class Q_EGLFS_EXPORT QEglFSIntegration : public QPlatformIntegration, public QPl
public:
QEglFSIntegration();
- void initialize() Q_DECL_OVERRIDE;
- void destroy() Q_DECL_OVERRIDE;
+ void initialize() override;
+ void destroy() override;
EGLDisplay display() const { return m_display; }
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
- QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
- QPlatformServices *services() const Q_DECL_OVERRIDE;
- QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE { return m_inputContext; }
- QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
+ QPlatformFontDatabase *fontDatabase() const override;
+ QPlatformServices *services() const override;
+ QPlatformInputContext *inputContext() const override { return m_inputContext; }
+ QPlatformTheme *createPlatformTheme(const QString &name) const override;
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
- QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
- QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const override;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
+#ifndef QT_NO_OPENGL
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
+ QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override;
+#endif
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
-
- QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
+ QPlatformNativeInterface *nativeInterface() const override;
// QPlatformNativeInterface
- void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
- void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) Q_DECL_OVERRIDE;
- void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) Q_DECL_OVERRIDE;
- void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) Q_DECL_OVERRIDE;
- NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE;
-
- QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE;
+ void *nativeResourceForIntegration(const QByteArray &resource) override;
+ void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) override;
+ void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) override;
+#ifndef QT_NO_OPENGL
+ void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) override;
+#endif
+ NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) override;
+
+ QFunctionPointer platformFunction(const QByteArray &function) const override;
QFbVtHandler *vtHandler() { return m_vtHandler.data(); }
diff --git a/src/plugins/platforms/eglfs/api/qeglfsoffscreenwindow_p.h b/src/plugins/platforms/eglfs/api/qeglfsoffscreenwindow_p.h
index ec483c64e2..9fdb81efdd 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsoffscreenwindow_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfsoffscreenwindow_p.h
@@ -62,8 +62,8 @@ public:
QEglFSOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface);
~QEglFSOffscreenWindow();
- QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
- bool isValid() const Q_DECL_OVERRIDE { return m_surface != EGL_NO_SURFACE; }
+ QSurfaceFormat format() const override { return m_format; }
+ bool isValid() const override { return m_surface != EGL_NO_SURFACE; }
private:
QSurfaceFormat m_format;
diff --git a/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp
index 5613179041..d5c22b3d37 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp
@@ -41,7 +41,9 @@
#include <QtGui/qwindow.h>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformcursor.h>
-#include <QtPlatformCompositorSupport/private/qopenglcompositor_p.h>
+#ifndef QT_NO_OPENGL
+# include <QtPlatformCompositorSupport/private/qopenglcompositor_p.h>
+#endif
#include "qeglfsscreen_p.h"
#include "qeglfswindow_p.h"
@@ -60,7 +62,9 @@ QEglFSScreen::QEglFSScreen(EGLDisplay dpy)
QEglFSScreen::~QEglFSScreen()
{
delete m_cursor;
+#ifndef QT_NO_OPENGL
QOpenGLCompositor::destroy();
+#endif
}
QRect QEglFSScreen::geometry() const
@@ -145,6 +149,7 @@ void QEglFSScreen::setPrimarySurface(EGLSurface surface)
void QEglFSScreen::handleCursorMove(const QPoint &pos)
{
+#ifndef QT_NO_OPENGL
const QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
const QList<QOpenGLCompositorWindow *> windows = compositor->windows();
@@ -178,10 +183,12 @@ void QEglFSScreen::handleCursorMove(const QPoint &pos)
if (enter && leave)
QWindowSystemInterface::handleEnterLeaveEvent(enter, leave, enter->mapFromGlobal(pos), pos);
+#endif
}
QPixmap QEglFSScreen::grabWindow(WId wid, int x, int y, int width, int height) const
{
+#ifndef QT_NO_OPENGL
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
const QList<QOpenGLCompositorWindow *> windows = compositor->windows();
Q_ASSERT(!windows.isEmpty());
@@ -224,7 +231,7 @@ QPixmap QEglFSScreen::grabWindow(WId wid, int x, int y, int width, int height) c
return QPixmap::fromImage(img).copy(rect);
}
}
-
+#endif // QT_NO_OPENGL
return QPixmap();
}
diff --git a/src/plugins/platforms/eglfs/api/qeglfsscreen_p.h b/src/plugins/platforms/eglfs/api/qeglfsscreen_p.h
index 131e619e06..bea7b4c8ef 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsscreen_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfsscreen_p.h
@@ -67,22 +67,22 @@ public:
QEglFSScreen(EGLDisplay display);
~QEglFSScreen();
- QRect geometry() const Q_DECL_OVERRIDE;
+ QRect geometry() const override;
virtual QRect rawGeometry() const;
- int depth() const Q_DECL_OVERRIDE;
- QImage::Format format() const Q_DECL_OVERRIDE;
+ int depth() const override;
+ QImage::Format format() const override;
- QSizeF physicalSize() const Q_DECL_OVERRIDE;
- QDpi logicalDpi() const Q_DECL_OVERRIDE;
- qreal pixelDensity() const Q_DECL_OVERRIDE;
- Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE;
- Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE;
+ QSizeF physicalSize() const override;
+ QDpi logicalDpi() const override;
+ qreal pixelDensity() const override;
+ Qt::ScreenOrientation nativeOrientation() const override;
+ Qt::ScreenOrientation orientation() const override;
- QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
+ QPlatformCursor *cursor() const override;
- qreal refreshRate() const Q_DECL_OVERRIDE;
+ qreal refreshRate() const override;
- QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
+ QPixmap grabWindow(WId wid, int x, int y, int width, int height) const override;
EGLSurface primarySurface() const { return m_surface; }
diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp
index 639fc56d2b..12108fd1c4 100644
--- a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp
@@ -41,13 +41,17 @@
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformintegration.h>
#include <private/qguiapplication_p.h>
-#include <QtGui/private/qopenglcontext_p.h>
-#include <QtGui/QOpenGLContext>
+#ifndef QT_NO_OPENGL
+# include <QtGui/private/qopenglcontext_p.h>
+# include <QtGui/QOpenGLContext>
+# include <QtPlatformCompositorSupport/private/qopenglcompositorbackingstore_p.h>
+#endif
#include <QtEglSupport/private/qeglconvenience_p.h>
-#include <QtPlatformCompositorSupport/private/qopenglcompositorbackingstore_p.h>
#include "qeglfswindow_p.h"
-#include "qeglfscursor_p.h"
+#ifndef QT_NO_OPENGL
+# include "qeglfscursor_p.h"
+#endif
#include "qeglfshooks_p.h"
#include "qeglfsdeviceintegration_p.h"
@@ -55,7 +59,9 @@ QT_BEGIN_NAMESPACE
QEglFSWindow::QEglFSWindow(QWindow *w)
: QPlatformWindow(w),
+#ifndef QT_NO_OPENGL
m_backingStore(0),
+#endif
m_raster(false),
m_winId(0),
m_surface(EGL_NO_SURFACE),
@@ -107,6 +113,7 @@ void QEglFSWindow::create()
// raster windows will not have their own native window, surface and context. Instead,
// they will be composited onto the root window's surface.
QEglFSScreen *screen = this->screen();
+#ifndef QT_NO_OPENGL
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
if (screen->primarySurface() != EGL_NO_SURFACE) {
if (Q_UNLIKELY(!isRaster() || !compositor->targetWindow())) {
@@ -120,6 +127,7 @@ void QEglFSWindow::create()
m_format = compositor->targetWindow()->format();
return;
}
+#endif // QT_NO_OPENGL
m_flags |= HasNativeWindow;
setGeometry(QRect()); // will become fullscreen
@@ -135,6 +143,7 @@ void QEglFSWindow::create()
screen->setPrimarySurface(m_surface);
+#ifndef QT_NO_OPENGL
if (isRaster()) {
QOpenGLContext *context = new QOpenGLContext(QGuiApplication::instance());
context->setShareContext(qt_gl_global_share_context());
@@ -153,16 +162,18 @@ void QEglFSWindow::create()
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
}
}
+#endif // QT_NO_OPENGL
}
void QEglFSWindow::destroy()
{
QEglFSScreen *screen = this->screen();
if (m_flags.testFlag(HasNativeWindow)) {
+#ifndef QT_NO_OPENGL
QEglFSCursor *cursor = qobject_cast<QEglFSCursor *>(screen->cursor());
if (cursor)
cursor->resetResources();
-
+#endif
if (screen->primarySurface() == m_surface)
screen->setPrimarySurface(EGL_NO_SURFACE);
@@ -170,7 +181,9 @@ void QEglFSWindow::destroy()
}
m_flags = 0;
+#ifndef QT_NO_OPENGL
QOpenGLCompositor::instance()->removeWindow(this);
+#endif
}
void QEglFSWindow::invalidateSurface()
@@ -197,6 +210,7 @@ void QEglFSWindow::resetSurface()
void QEglFSWindow::setVisible(bool visible)
{
+#ifndef QT_NO_OPENGL
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
QList<QOpenGLCompositorWindow *> windows = compositor->windows();
QWindow *wnd = window();
@@ -211,7 +225,9 @@ void QEglFSWindow::setVisible(bool visible)
windows.last()->sourceWindow()->requestActivate();
}
}
-
+#else
+ QWindow *wnd = window();
+#endif
QWindowSystemInterface::handleExposeEvent(wnd, QRect(QPoint(0, 0), wnd->geometry().size()));
if (visible)
@@ -247,9 +263,10 @@ QRect QEglFSWindow::geometry() const
void QEglFSWindow::requestActivateWindow()
{
+#ifndef QT_NO_OPENGL
if (window()->type() != Qt::Desktop)
QOpenGLCompositor::instance()->moveToTop(this);
-
+#endif
QWindow *wnd = window();
QWindowSystemInterface::handleWindowActivated(wnd);
QWindowSystemInterface::handleExposeEvent(wnd, QRect(QPoint(0, 0), wnd->geometry().size()));
@@ -259,13 +276,16 @@ void QEglFSWindow::raise()
{
QWindow *wnd = window();
if (wnd->type() != Qt::Desktop) {
+#ifndef QT_NO_OPENGL
QOpenGLCompositor::instance()->moveToTop(this);
+#endif
QWindowSystemInterface::handleExposeEvent(wnd, QRect(QPoint(0, 0), wnd->geometry().size()));
}
}
void QEglFSWindow::lower()
{
+#ifndef QT_NO_OPENGL
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
QList<QOpenGLCompositorWindow *> windows = compositor->windows();
if (window()->type() != Qt::Desktop && windows.count() > 1) {
@@ -276,6 +296,7 @@ void QEglFSWindow::lower()
QRect(QPoint(0, 0), windows.last()->sourceWindow()->geometry().size()));
}
}
+#endif
}
EGLSurface QEglFSWindow::surface() const
@@ -303,6 +324,7 @@ bool QEglFSWindow::isRaster() const
return m_raster || window()->surfaceType() == QSurface::RasterGLSurface;
}
+#ifndef QT_NO_OPENGL
QWindow *QEglFSWindow::sourceWindow() const
{
return window();
@@ -321,6 +343,7 @@ void QEglFSWindow::endCompositing()
if (m_backingStore)
m_backingStore->notifyComposited();
}
+#endif
WId QEglFSWindow::winId() const
{
diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow_p.h b/src/plugins/platforms/eglfs/api/qeglfswindow_p.h
index 0889f27ae3..6bda262523 100644
--- a/src/plugins/platforms/eglfs/api/qeglfswindow_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfswindow_p.h
@@ -56,14 +56,19 @@
#include "qeglfsscreen_p.h"
#include <qpa/qplatformwindow.h>
-#include <QtPlatformCompositorSupport/private/qopenglcompositor_p.h>
+#ifndef QT_NO_OPENGL
+# include <QtPlatformCompositorSupport/private/qopenglcompositor_p.h>
+#endif
QT_BEGIN_NAMESPACE
class QOpenGLCompositorBackingStore;
class QPlatformTextureList;
-
+#ifndef QT_NO_OPENGL
class Q_EGLFS_EXPORT QEglFSWindow : public QPlatformWindow, public QOpenGLCompositorWindow
+#else
+class Q_EGLFS_EXPORT QEglFSWindow : public QPlatformWindow
+#endif
{
public:
QEglFSWindow(QWindow *w);
@@ -72,21 +77,21 @@ public:
void create();
void destroy();
- void setGeometry(const QRect &) Q_DECL_OVERRIDE;
- QRect geometry() const Q_DECL_OVERRIDE;
- void setVisible(bool visible) Q_DECL_OVERRIDE;
- void requestActivateWindow() Q_DECL_OVERRIDE;
- void raise() Q_DECL_OVERRIDE;
- void lower() Q_DECL_OVERRIDE;
+ void setGeometry(const QRect &) override;
+ QRect geometry() const override;
+ void setVisible(bool visible) override;
+ void requestActivateWindow() override;
+ void raise() override;
+ void lower() override;
- void propagateSizeHints() Q_DECL_OVERRIDE { }
- void setMask(const QRegion &) Q_DECL_OVERRIDE { }
- bool setKeyboardGrabEnabled(bool) Q_DECL_OVERRIDE { return false; }
- bool setMouseGrabEnabled(bool) Q_DECL_OVERRIDE { return false; }
- void setOpacity(qreal) Q_DECL_OVERRIDE;
- WId winId() const Q_DECL_OVERRIDE;
+ void propagateSizeHints() override { }
+ void setMask(const QRegion &) override { }
+ bool setKeyboardGrabEnabled(bool) override { return false; }
+ bool setMouseGrabEnabled(bool) override { return false; }
+ void setOpacity(qreal) override;
+ WId winId() const override;
- QSurfaceFormat format() const Q_DECL_OVERRIDE;
+ QSurfaceFormat format() const override;
EGLNativeWindowType eglWindow() const;
EGLSurface surface() const;
@@ -94,19 +99,24 @@ public:
bool hasNativeWindow() const { return m_flags.testFlag(HasNativeWindow); }
- virtual void invalidateSurface() Q_DECL_OVERRIDE;
+ void invalidateSurface() override;
virtual void resetSurface();
+#ifndef QT_NO_OPENGL
QOpenGLCompositorBackingStore *backingStore() { return m_backingStore; }
void setBackingStore(QOpenGLCompositorBackingStore *backingStore) { m_backingStore = backingStore; }
+#endif
bool isRaster() const;
-
- QWindow *sourceWindow() const Q_DECL_OVERRIDE;
- const QPlatformTextureList *textures() const Q_DECL_OVERRIDE;
- void endCompositing() Q_DECL_OVERRIDE;
+#ifndef QT_NO_OPENGL
+ QWindow *sourceWindow() const override;
+ const QPlatformTextureList *textures() const override;
+ void endCompositing() override;
+#endif
protected:
+#ifndef QT_NO_OPENGL
QOpenGLCompositorBackingStore *m_backingStore;
+#endif
bool m_raster;
WId m_winId;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro
index d86a67b4f4..52cc5739aa 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro
@@ -9,5 +9,7 @@ qtConfig(eglfs_mali): SUBDIRS += eglfs_mali
qtConfig(eglfs_viv): SUBDIRS += eglfs_viv
qtConfig(eglfs_viv_wl): SUBDIRS += eglfs_viv_wl
+SUBDIRS += eglfs_emu
+
eglfs_kms_egldevice.depends = eglfs_kms_support
eglfs_kms.depends = eglfs_kms_support
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.h
index 5af628dedd..83bcc487af 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.h
@@ -47,13 +47,13 @@ QT_BEGIN_NAMESPACE
class QEglFSBrcmIntegration : public QEglFSDeviceIntegration
{
public:
- void platformInit() Q_DECL_OVERRIDE;
- void platformDestroy() Q_DECL_OVERRIDE;
- EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE;
- QSize screenSize() const Q_DECL_OVERRIDE;
- EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) Q_DECL_OVERRIDE;
- void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE;
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+ void platformInit() override;
+ void platformDestroy() override;
+ EGLNativeDisplayType platformDisplay() const override;
+ QSize screenSize() const override;
+ EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) override;
+ void destroyNativeWindow(EGLNativeWindowType window) override;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmmain.cpp
index 80d7631931..fd6665e560 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmmain.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmmain.cpp
@@ -48,7 +48,7 @@ class QEglFSBrcmIntegrationPlugin : public QEglFSDeviceIntegrationPlugin
Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_brcm.json")
public:
- QEglFSDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSBrcmIntegration; }
+ QEglFSDeviceIntegration *create() override { return new QEglFSBrcmIntegration; }
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/eglfs_emu.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/eglfs_emu.json
new file mode 100644
index 0000000000..3aa38abd7a
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/eglfs_emu.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "eglfs_emu" ]
+}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/eglfs_emu.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/eglfs_emu.pro
new file mode 100644
index 0000000000..609f04e8a9
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/eglfs_emu.pro
@@ -0,0 +1,27 @@
+TARGET = qeglfs-emu-integration
+
+QT += core-private gui-private eglfsdeviceintegration-private
+
+INCLUDEPATH += $$PWD/../../api
+CONFIG += egl
+
+# Avoid X11 header collision
+DEFINES += QT_EGL_NO_X11
+
+OTHER_FILES += $$PWD/eglfs_emu.json
+
+PLUGIN_TYPE = egldeviceintegrations
+PLUGIN_CLASS_NAME = QEglFSEmulatorIntegrationPlugin
+load(qt_plugin)
+
+DISTFILES += \
+ eglfs_emu.json
+
+SOURCES += \
+ qeglfsemumain.cpp \
+ qeglfsemulatorintegration.cpp \
+ qeglfsemulatorscreen.cpp
+
+HEADERS += \
+ qeglfsemulatorintegration.h \
+ qeglfsemulatorscreen.h
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp
new file mode 100644
index 0000000000..8a059ba973
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglfsemulatorintegration.h"
+#include "qeglfsemulatorscreen.h"
+#include "private/qeglfsintegration_p.h"
+
+#include <private/qguiapplication_p.h>
+#include <QtEglSupport/private/qeglconvenience_p.h>
+#include <QtEglSupport/private/qeglplatformcontext_p.h>
+
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonParseError>
+
+QT_BEGIN_NAMESPACE
+
+QEglFSEmulatorIntegration::QEglFSEmulatorIntegration()
+{
+ // The Qt Emulator provides the ability to render to multiple displays
+ // In addition to the usual EGL and OpenGLESv2 API's, there are also a
+ // few additional API's that enable the client (this plugin) to query
+ // the available screens and their properties, as well as the ability
+ // to select which screen is the active render target (as this is
+ // usually handled in a platform specific way and not by EGL itself).
+
+ getDisplays = reinterpret_cast<PFNQGSGETDISPLAYSPROC>(eglGetProcAddress("qgsGetDisplays"));
+ setDisplay = reinterpret_cast<PFNQGSSETDISPLAYPROC>(eglGetProcAddress("qgsSetDisplay"));
+}
+
+void QEglFSEmulatorIntegration::platformInit()
+{
+}
+
+void QEglFSEmulatorIntegration::platformDestroy()
+{
+}
+
+bool QEglFSEmulatorIntegration::usesDefaultScreen()
+{
+ // This makes it possible to remotely query and then register our own set of screens
+ return false;
+}
+
+void QEglFSEmulatorIntegration::screenInit()
+{
+ QEglFSIntegration *integration = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration());
+
+ // Use qgsGetDisplays() call to retrieve the available screens from the Emulator
+ if (getDisplays) {
+ QByteArray displaysInfo = getDisplays();
+ QJsonParseError error;
+ QJsonDocument displaysDocument = QJsonDocument::fromJson(displaysInfo, &error);
+ if (error.error == QJsonParseError::NoError) {
+ // Document should be an array of screen objects
+ if (displaysDocument.isArray()){
+ QJsonArray screenArray = displaysDocument.array();
+ for (auto screenValue : screenArray) {
+ if (screenValue.isObject())
+ integration->addScreen(new QEglFSEmulatorScreen(screenValue.toObject()));
+ }
+ }
+ } else {
+ qWarning() << "eglfs_emu: Failed to parse display info JSON with error: " << error.errorString();
+ }
+ } else {
+ qFatal("EGL library doesn't support Emulator extensions");
+ }
+}
+
+bool QEglFSEmulatorIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ switch (cap) {
+ case QPlatformIntegration::ThreadedPixmaps:
+ case QPlatformIntegration::OpenGL:
+ case QPlatformIntegration::ThreadedOpenGL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+EGLNativeWindowType QEglFSEmulatorIntegration::createNativeWindow(QPlatformWindow *platformWindow,
+ const QSize &size,
+ const QSurfaceFormat &format)
+{
+ Q_UNUSED(size);
+ Q_UNUSED(format);
+ static QAtomicInt uniqueWindowId(1);
+ QEglFSEmulatorScreen *screen = static_cast<QEglFSEmulatorScreen *>(platformWindow->screen());
+ if (screen && setDisplay) {
+ // Let the emulator know which screen the window surface is attached to
+ setDisplay(screen->id());
+ }
+ return EGLNativeWindowType(qintptr(uniqueWindowId.fetchAndAddRelaxed(1)));
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h
new file mode 100644
index 0000000000..513a5063fb
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLFSEMULATORINTEGRATION_H
+#define QEGLFSEMULATORINTEGRATION_H
+
+#include "private/qeglfsdeviceintegration_p.h"
+
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QFunctionPointer>
+
+typedef const char *(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC) ();
+typedef void (EGLAPIENTRYP PFNQGSSETDISPLAYPROC) (uint screen);
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcEglfsEmuDebug)
+
+class QEglFSEmulatorIntegration : public QEglFSDeviceIntegration
+{
+public:
+ QEglFSEmulatorIntegration();
+
+ void platformInit() override;
+ void platformDestroy() override;
+ bool usesDefaultScreen() override;
+ void screenInit() override;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
+
+ PFNQGSGETDISPLAYSPROC getDisplays;
+ PFNQGSSETDISPLAYPROC setDisplay;
+
+ EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, const QSize &size, const QSurfaceFormat &format) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLFSEMULATORINTEGRATION_H
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp
new file mode 100644
index 0000000000..4546088327
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeglfsemulatorscreen.h"
+
+QT_BEGIN_NAMESPACE
+
+QEglFSEmulatorScreen::QEglFSEmulatorScreen(const QJsonObject &screenDescription)
+ : QEglFSScreen(eglGetDisplay(EGL_DEFAULT_DISPLAY))
+ , m_id(0)
+{
+ initFromJsonObject(screenDescription);
+}
+
+QRect QEglFSEmulatorScreen::geometry() const
+{
+ return m_geometry;
+}
+
+QRect QEglFSEmulatorScreen::rawGeometry() const
+{
+ return QRect(QPoint(0, 0), m_geometry.size());
+}
+
+int QEglFSEmulatorScreen::depth() const
+{
+ return m_depth;
+}
+
+QImage::Format QEglFSEmulatorScreen::format() const
+{
+ return m_format;
+}
+
+QSizeF QEglFSEmulatorScreen::physicalSize() const
+{
+ return m_physicalSize;
+}
+
+QDpi QEglFSEmulatorScreen::logicalDpi() const
+{
+ const QSizeF ps = m_physicalSize;
+ const QSize s = m_geometry.size();
+
+ if (!ps.isEmpty() && !s.isEmpty())
+ return QDpi(25.4 * s.width() / ps.width(),
+ 25.4 * s.height() / ps.height());
+ else
+ return QDpi(100, 100);
+}
+
+qreal QEglFSEmulatorScreen::pixelDensity() const
+{
+ return m_pixelDensity;
+}
+
+qreal QEglFSEmulatorScreen::refreshRate() const
+{
+ return m_refreshRate;
+}
+
+Qt::ScreenOrientation QEglFSEmulatorScreen::nativeOrientation() const
+{
+ return m_nativeOrientation;
+}
+
+Qt::ScreenOrientation QEglFSEmulatorScreen::orientation() const
+{
+ return m_orientation;
+}
+
+uint QEglFSEmulatorScreen::id() const
+{
+ return m_id;
+}
+
+void QEglFSEmulatorScreen::initFromJsonObject(const QJsonObject &description)
+{
+ QJsonValue value;
+
+ value = description.value(QLatin1String("id"));
+ if (!value.isUndefined() && value.isDouble())
+ m_id = value.toInt();
+
+ value = description.value(QLatin1String("description"));
+ if (!value.isUndefined() && value.isString())
+ m_description = value.toString();
+
+ value = description.value(QLatin1String("geometry"));
+ if (!value.isUndefined() && value.isObject()) {
+ QJsonObject geometryObject = value.toObject();
+ value = geometryObject.value(QLatin1String("x"));
+ if (!value.isUndefined() && value.isDouble())
+ m_geometry.setX(value.toInt());
+ value = geometryObject.value(QLatin1String("y"));
+ if (!value.isUndefined() && value.isDouble())
+ m_geometry.setY(value.toInt());
+ value = geometryObject.value(QLatin1String("width"));
+ if (!value.isUndefined() && value.isDouble())
+ m_geometry.setWidth(value.toInt());
+ value = geometryObject.value(QLatin1String("height"));
+ if (!value.isUndefined() && value.isDouble())
+ m_geometry.setHeight(value.toInt());
+ }
+
+ value = description.value(QLatin1String("depth"));
+ if (!value.isUndefined() && value.isDouble())
+ m_depth = value.toInt();
+
+ value = description.value(QLatin1String("format"));
+ if (!value.isUndefined() && value.isDouble())
+ m_format = static_cast<QImage::Format>(value.toInt());
+
+ value = description.value(QLatin1String("physicalSize"));
+ if (!value.isUndefined() && value.isObject()) {
+ QJsonObject physicalSizeObject = value.toObject();
+ value = physicalSizeObject.value(QLatin1String("width"));
+ if (!value.isUndefined() && value.isDouble())
+ m_physicalSize.setWidth(value.toInt());
+ value = physicalSizeObject.value(QLatin1String("height"));
+ if (!value.isUndefined() && value.isDouble())
+ m_physicalSize.setHeight(value.toInt());
+ }
+
+ value = description.value(QLatin1String("pixelDensity"));
+ if (!value.isUndefined() && value.isDouble())
+ m_pixelDensity = value.toDouble();
+
+ value = description.value(QLatin1String("refreshRate"));
+ if (!value.isUndefined() && value.isDouble())
+ m_refreshRate = value.toDouble();
+
+ value = description.value(QLatin1String("nativeOrientation"));
+ if (!value.isUndefined() && value.isDouble())
+ m_nativeOrientation = static_cast<Qt::ScreenOrientation>(value.toInt());
+
+ value = description.value(QLatin1String("orientation"));
+ if (!value.isUndefined() && value.isDouble())
+ m_orientation = static_cast<Qt::ScreenOrientation>(value.toInt());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h
new file mode 100644
index 0000000000..3e5113c9c2
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEGLFSEMULATORSCREEN_H
+#define QEGLFSEMULATORSCREEN_H
+
+#include <QtCore/QJsonObject>
+
+#include "qeglfsemulatorintegration.h"
+#include "private/qeglfsscreen_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEglFSEmulatorScreen : public QEglFSScreen
+{
+public:
+ QEglFSEmulatorScreen(const QJsonObject &screenDescription);
+
+ QRect geometry() const override;
+ QRect rawGeometry() const override;
+ int depth() const override;
+ QImage::Format format() const override;
+ QSizeF physicalSize() const override;
+ QDpi logicalDpi() const override;
+ qreal pixelDensity() const override;
+ qreal refreshRate() const override;
+ Qt::ScreenOrientation nativeOrientation() const override;
+ Qt::ScreenOrientation orientation() const override;
+
+ uint id() const;
+
+private:
+ void initFromJsonObject(const QJsonObject &description);
+
+ QString m_description;
+ QRect m_geometry;
+ int m_depth;
+ QImage::Format m_format;
+ QSizeF m_physicalSize;
+ float m_pixelDensity;
+ float m_refreshRate;
+ Qt::ScreenOrientation m_nativeOrientation;
+ Qt::ScreenOrientation m_orientation;
+ uint m_id;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLFSEMULATORSCREEN_H
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemumain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemumain.cpp
new file mode 100644
index 0000000000..a9923851ef
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemumain.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qeglfsdeviceintegration_p.h"
+#include "qeglfsemulatorintegration.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEglFSEmulatorIntegrationPlugin : public QEglFSDeviceIntegrationPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_emu.json")
+
+public:
+ QEglFSDeviceIntegration *create() override { return new QEglFSEmulatorIntegration; }
+};
+
+QT_END_NAMESPACE
+
+#include "qeglfsemumain.moc"
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
index 255db824b7..e522c0ee1b 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
@@ -4,7 +4,7 @@ PLUGIN_TYPE = egldeviceintegrations
PLUGIN_CLASS_NAME = QEglFSKmsGbmIntegrationPlugin
load(qt_plugin)
-QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private
+QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private kms_support-private
INCLUDEPATH += $$PWD/../../api $$PWD/../eglfs_kms_support
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h
index de13a058cf..c96dd585d3 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.h
@@ -76,12 +76,12 @@ public:
~QEglFSKmsGbmCursor();
// input methods
- void pointerEvent(const QMouseEvent & event) Q_DECL_OVERRIDE;
+ void pointerEvent(const QMouseEvent & event) override;
#ifndef QT_NO_CURSOR
- void changeCursor(QCursor * windowCursor, QWindow * window) Q_DECL_OVERRIDE;
+ void changeCursor(QCursor * windowCursor, QWindow * window) override;
#endif
- QPoint pos() const Q_DECL_OVERRIDE;
- void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
+ QPoint pos() const override;
+ void setPos(const QPoint &pos) override;
void updateMouseStatus();
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
index 3a220ec942..2040d6bc0e 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
@@ -46,7 +46,6 @@
#include <QtCore/QLoggingCategory>
#include <QtCore/private/qcore_unix_p.h>
-#include <QtGui/private/qguiapplication_p.h>
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
@@ -65,8 +64,8 @@ void QEglFSKmsGbmDevice::pageFlipHandler(int fd, unsigned int sequence, unsigned
screen->flipFinished();
}
-QEglFSKmsGbmDevice::QEglFSKmsGbmDevice(QEglFSKmsIntegration *integration, const QString &path)
- : QEglFSKmsDevice(integration, path)
+QEglFSKmsGbmDevice::QEglFSKmsGbmDevice(QKmsScreenConfig *screenConfig, const QString &path)
+ : QEglFSKmsDevice(screenConfig, path)
, m_gbm_device(Q_NULLPTR)
, m_globalCursor(Q_NULLPTR)
{
@@ -77,7 +76,6 @@ bool QEglFSKmsGbmDevice::open()
Q_ASSERT(fd() == -1);
Q_ASSERT(m_gbm_device == Q_NULLPTR);
- qCDebug(qLcEglfsKmsDebug) << "Opening device" << devicePath();
int fd = qt_safe_open(devicePath().toLocal8Bit().constData(), O_RDWR | O_CLOEXEC);
if (fd == -1) {
qErrnoWarning("Could not open DRM device %s", qPrintable(devicePath()));
@@ -101,6 +99,8 @@ bool QEglFSKmsGbmDevice::open()
void QEglFSKmsGbmDevice::close()
{
+ // Note: screens are gone at this stage.
+
if (m_gbm_device) {
gbm_device_destroy(m_gbm_device);
m_gbm_device = Q_NULLPTR;
@@ -110,15 +110,11 @@ void QEglFSKmsGbmDevice::close()
qt_safe_close(fd());
setFd(-1);
}
-
- if (m_globalCursor)
- m_globalCursor->deleteLater();
- m_globalCursor = Q_NULLPTR;
}
-EGLNativeDisplayType QEglFSKmsGbmDevice::nativeDisplay() const
+void *QEglFSKmsGbmDevice::nativeDisplay() const
{
- return reinterpret_cast<EGLNativeDisplayType>(m_gbm_device);
+ return m_gbm_device;
}
gbm_device * QEglFSKmsGbmDevice::gbmDevice() const
@@ -131,6 +127,17 @@ QPlatformCursor *QEglFSKmsGbmDevice::globalCursor() const
return m_globalCursor;
}
+// Cannot do this from close(), it may be too late.
+// Call this from the last screen dtor instead.
+void QEglFSKmsGbmDevice::destroyGlobalCursor()
+{
+ if (m_globalCursor) {
+ qCDebug(qLcEglfsKmsDebug, "Destroying global GBM mouse cursor");
+ delete m_globalCursor;
+ m_globalCursor = Q_NULLPTR;
+ }
+}
+
void QEglFSKmsGbmDevice::handleDrmEvent()
{
drmEventContext drmEvent = {
@@ -142,14 +149,13 @@ void QEglFSKmsGbmDevice::handleDrmEvent()
drmHandleEvent(fd(), &drmEvent);
}
-QEglFSKmsScreen *QEglFSKmsGbmDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output)
+QPlatformScreen *QEglFSKmsGbmDevice::createScreen(const QKmsOutput &output)
{
- static bool firstScreen = true;
- QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(integration, device, output);
+ QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(this, output);
- if (firstScreen && integration->hwCursor()) {
+ if (!m_globalCursor && screenConfig()->hwCursor()) {
+ qCDebug(qLcEglfsKmsDebug, "Creating new global GBM mouse cursor");
m_globalCursor = new QEglFSKmsGbmCursor(screen);
- firstScreen = false;
}
return screen;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h
index 7c0af84422..08ca28d48e 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h
@@ -43,7 +43,7 @@
#define QEGLFSKMSGBMDEVICE_H
#include "qeglfskmsgbmcursor.h"
-#include "qeglfskmsdevice.h"
+#include <qeglfskmsdevice.h>
#include <gbm.h>
@@ -54,21 +54,20 @@ class QEglFSKmsScreen;
class QEglFSKmsGbmDevice: public QEglFSKmsDevice
{
public:
- QEglFSKmsGbmDevice(QEglFSKmsIntegration *integration, const QString &path);
+ QEglFSKmsGbmDevice(QKmsScreenConfig *screenConfig, const QString &path);
- bool open() Q_DECL_OVERRIDE;
- void close() Q_DECL_OVERRIDE;
+ bool open() override;
+ void close() override;
- EGLNativeDisplayType nativeDisplay() const Q_DECL_OVERRIDE;
+ void *nativeDisplay() const override;
gbm_device *gbmDevice() const;
QPlatformCursor *globalCursor() const;
+ void destroyGlobalCursor();
void handleDrmEvent();
- virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output) Q_DECL_OVERRIDE;
+ QPlatformScreen *createScreen(const QKmsOutput &output) override;
private:
Q_DISABLE_COPY(QEglFSKmsGbmDevice)
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
index 38419a55c8..16767114ab 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
@@ -63,8 +63,9 @@ QT_BEGIN_NAMESPACE
QMutex QEglFSKmsGbmScreen::m_waitForFlipMutex;
QEglFSKmsGbmIntegration::QEglFSKmsGbmIntegration()
- : QEglFSKmsIntegration()
-{}
+{
+ qCDebug(qLcEglfsKmsDebug, "New DRM/KMS via GBM integration created");
+}
EGLNativeWindowType QEglFSKmsGbmIntegration::createNativeWindow(QPlatformWindow *platformWindow,
const QSize &size,
@@ -104,10 +105,12 @@ void QEglFSKmsGbmIntegration::destroyNativeWindow(EGLNativeWindowType window)
QPlatformCursor *QEglFSKmsGbmIntegration::createCursor(QPlatformScreen *screen) const
{
- if (hwCursor())
- return Q_NULLPTR;
- else
+ if (screenConfig()->hwCursor()) {
+ return nullptr;
+ } else {
+ qCDebug(qLcEglfsKmsDebug, "Using plain OpenGL mouse cursor");
return new QEglFSCursor(screen);
+ }
}
void QEglFSKmsGbmIntegration::presentBuffer(QPlatformSurface *surface)
@@ -118,13 +121,12 @@ void QEglFSKmsGbmIntegration::presentBuffer(QPlatformSurface *surface)
screen->flip();
}
-QEglFSKmsDevice *QEglFSKmsGbmIntegration::createDevice(const QString &devicePath)
+QKmsDevice *QEglFSKmsGbmIntegration::createDevice()
{
- QString path = devicePath;
- if (!devicePath.isEmpty()) {
- qCDebug(qLcEglfsKmsDebug) << "Using DRM device" << path << "specified in config file";
+ QString path = screenConfig()->devicePath();
+ if (!path.isEmpty()) {
+ qCDebug(qLcEglfsKmsDebug) << "GBM: Using DRM device" << path << "specified in config file";
} else {
-
QDeviceDiscovery *d = QDeviceDiscovery::create(QDeviceDiscovery::Device_VideoMask);
const QStringList devices = d->scanConnectedDevices();
qCDebug(qLcEglfsKmsDebug) << "Found the following video devices:" << devices;
@@ -137,7 +139,7 @@ QEglFSKmsDevice *QEglFSKmsGbmIntegration::createDevice(const QString &devicePath
qCDebug(qLcEglfsKmsDebug) << "Using" << path;
}
- return new QEglFSKmsGbmDevice(this, path);
+ return new QEglFSKmsGbmDevice(screenConfig(), path);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h
index 727571d3e3..38f132d72e 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h
@@ -57,15 +57,15 @@ public:
EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow,
const QSize &size,
- const QSurfaceFormat &format) Q_DECL_OVERRIDE;
- EGLNativeWindowType createNativeOffscreenWindow(const QSurfaceFormat &format) Q_DECL_OVERRIDE;
- void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE;
+ const QSurfaceFormat &format) override;
+ EGLNativeWindowType createNativeOffscreenWindow(const QSurfaceFormat &format) override;
+ void destroyNativeWindow(EGLNativeWindowType window) override;
- QPlatformCursor *createCursor(QPlatformScreen *screen) const Q_DECL_OVERRIDE;
- void presentBuffer(QPlatformSurface *surface) Q_DECL_OVERRIDE;
+ QPlatformCursor *createCursor(QPlatformScreen *screen) const override;
+ void presentBuffer(QPlatformSurface *surface) override;
protected:
- QEglFSKmsDevice *createDevice(const QString &devicePath) Q_DECL_OVERRIDE;
+ QKmsDevice *createDevice() override;
private:
};
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmmain.cpp
index f34e4859c6..945c8b4255 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmmain.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmmain.cpp
@@ -49,7 +49,7 @@ class QEglFSKmsGbmIntegrationPlugin : public QEglFSDeviceIntegrationPlugin
Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_kms.json")
public:
- QEglFSDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSKmsGbmIntegration; }
+ QEglFSDeviceIntegration *create() override { return new QEglFSKmsGbmIntegration; }
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
index d4df0dc66e..3723142f0b 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
@@ -92,10 +92,8 @@ QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject(
return fb.take();
}
-QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output)
- : QEglFSKmsScreen(integration, device, output)
+QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output)
+ : QEglFSKmsScreen(device, output)
, m_gbm_surface(Q_NULLPTR)
, m_gbm_bo_current(Q_NULLPTR)
, m_gbm_bo_next(Q_NULLPTR)
@@ -105,12 +103,17 @@ QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration,
QEglFSKmsGbmScreen::~QEglFSKmsGbmScreen()
{
+ const int remainingScreenCount = qGuiApp->screens().count();
+ qCDebug(qLcEglfsKmsDebug, "Screen dtor. Remaining screens: %d", remainingScreenCount);
+ if (!remainingScreenCount && !device()->screenConfig()->separateScreens())
+ static_cast<QEglFSKmsGbmDevice *>(device())->destroyGlobalCursor();
}
QPlatformCursor *QEglFSKmsGbmScreen::cursor() const
{
- if (integration()->hwCursor()) {
- if (!integration()->separateScreens())
+ QKmsScreenConfig *config = device()->screenConfig();
+ if (config->hwCursor()) {
+ if (!config->separateScreens())
return static_cast<QEglFSKmsGbmDevice *>(device())->globalCursor();
if (m_cursor.isNull()) {
@@ -181,7 +184,7 @@ void QEglFSKmsGbmScreen::flip()
FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next);
- QEglFSKmsOutput &op(output());
+ QKmsOutput &op(output());
const int fd = device()->fd();
const uint32_t w = op.modes[op.mode].hdisplay;
const uint32_t h = op.modes[op.mode].vdisplay;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h
index d7ad348291..341cc95bbe 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h
@@ -54,20 +54,18 @@ class QEglFSKmsGbmCursor;
class QEglFSKmsGbmScreen : public QEglFSKmsScreen
{
public:
- QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output);
+ QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output);
~QEglFSKmsGbmScreen();
- QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
+ QPlatformCursor *cursor() const override;
gbm_surface *surface() const { return m_gbm_surface; }
gbm_surface *createSurface();
void destroySurface();
- void waitForFlip() Q_DECL_OVERRIDE;
- void flip() Q_DECL_OVERRIDE;
- void flipFinished() Q_DECL_OVERRIDE;
+ void waitForFlip() override;
+ void flip() override;
+ void flipFinished() override;
private:
gbm_surface *m_gbm_surface;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
index a625021aba..a2dc9c4a50 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
@@ -1,6 +1,6 @@
TARGET = qeglfs-kms-egldevice-integration
-QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private
+QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private kms_support-private
INCLUDEPATH += $$PWD/../../api $$PWD/../eglfs_kms_support
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
index 60989e2bd0..f0bf59466e 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
@@ -40,14 +40,16 @@
#include "qeglfskmsegldevice.h"
#include "qeglfskmsegldevicescreen.h"
#include "qeglfskmsegldeviceintegration.h"
+#include "private/qeglfsintegration_p.h"
#include "private/qeglfscursor_p.h"
#include <QtCore/private/qcore_unix_p.h>
QT_BEGIN_NAMESPACE
-QEglFSKmsEglDevice::QEglFSKmsEglDevice(QEglFSKmsIntegration *integration, const QString &path)
- : QEglFSKmsDevice(integration, path),
+QEglFSKmsEglDevice::QEglFSKmsEglDevice(QEglFSKmsEglDeviceIntegration *devInt, QKmsScreenConfig *screenConfig, const QString &path)
+ : QEglFSKmsDevice(screenConfig, path),
+ m_devInt(devInt),
m_globalCursor(nullptr)
{
}
@@ -56,11 +58,9 @@ bool QEglFSKmsEglDevice::open()
{
Q_ASSERT(fd() == -1);
- qCDebug(qLcEglfsKmsDebug, "Opening DRM device %s", qPrintable(devicePath()));
-
int fd = drmOpen(devicePath().toLocal8Bit().constData(), Q_NULLPTR);
if (Q_UNLIKELY(fd < 0))
- qFatal("Could not open DRM device");
+ qFatal("Could not open DRM (NV) device");
setFd(fd);
@@ -69,25 +69,24 @@ bool QEglFSKmsEglDevice::open()
void QEglFSKmsEglDevice::close()
{
- qCDebug(qLcEglfsKmsDebug, "Closing DRM device");
+ // Note: screens are gone at this stage.
if (qt_safe_close(fd()) == -1)
- qErrnoWarning("Could not close DRM device");
+ qErrnoWarning("Could not close DRM (NV) device");
setFd(-1);
}
EGLNativeDisplayType QEglFSKmsEglDevice::nativeDisplay() const
{
- return reinterpret_cast<EGLNativeDisplayType>(static_cast<QEglFSKmsEglDeviceIntegration *>(m_integration)->eglDevice());
+ return reinterpret_cast<EGLNativeDisplayType>(m_devInt->eglDevice());
}
-QEglFSKmsScreen *QEglFSKmsEglDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device,
- QEglFSKmsOutput output)
+QPlatformScreen *QEglFSKmsEglDevice::createScreen(const QKmsOutput &output)
{
- QEglFSKmsScreen *screen = new QEglFSKmsEglDeviceScreen(integration, device, output);
+ QEglFSKmsScreen *screen = new QEglFSKmsEglDeviceScreen(this, output);
- if (!m_globalCursor && !integration->separateScreens()) {
+ if (!m_globalCursor && !screenConfig()->separateScreens()) {
qCDebug(qLcEglfsKmsDebug, "Creating new global mouse cursor");
m_globalCursor = new QEglFSCursor(screen);
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h
index 8c8f79f70c..8d469879ab 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.h
@@ -45,25 +45,25 @@
QT_BEGIN_NAMESPACE
class QPlatformCursor;
+class QEglFSKmsEglDeviceIntegration;
class QEglFSKmsEglDevice: public QEglFSKmsDevice
{
public:
- QEglFSKmsEglDevice(QEglFSKmsIntegration *integration, const QString &path);
+ QEglFSKmsEglDevice(QEglFSKmsEglDeviceIntegration *devInt, QKmsScreenConfig *screenConfig, const QString &path);
- virtual bool open() Q_DECL_OVERRIDE;
- virtual void close() Q_DECL_OVERRIDE;
+ bool open() override;
+ void close() override;
- virtual EGLNativeDisplayType nativeDisplay() const Q_DECL_OVERRIDE;
+ void *nativeDisplay() const override;
- virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output) Q_DECL_OVERRIDE;
+ QPlatformScreen *createScreen(const QKmsOutput &output) override;
QPlatformCursor *globalCursor() { return m_globalCursor; }
void destroyGlobalCursor();
private:
+ QEglFSKmsEglDeviceIntegration *m_devInt;
QPlatformCursor *m_globalCursor;
};
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
index cf1de71831..3e333fc25a 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
@@ -50,8 +50,7 @@
QT_BEGIN_NAMESPACE
QEglFSKmsEglDeviceIntegration::QEglFSKmsEglDeviceIntegration()
- : QEglFSKmsIntegration()
- , m_egl_device(EGL_NO_DEVICE_EXT)
+ : m_egl_device(EGL_NO_DEVICE_EXT)
, m_funcs(Q_NULLPTR)
{
qCDebug(qLcEglfsKmsDebug, "New DRM/KMS on EGLDevice integration created");
@@ -101,30 +100,30 @@ bool QEglFSKmsEglDeviceIntegration::supportsPBuffers() const
return true;
}
-class QEglJetsonTK1Window : public QEglFSWindow
+class QEglFSKmsEglDeviceWindow : public QEglFSWindow
{
public:
- QEglJetsonTK1Window(QWindow *w, const QEglFSKmsEglDeviceIntegration *integration)
+ QEglFSKmsEglDeviceWindow(QWindow *w, const QEglFSKmsEglDeviceIntegration *integration)
: QEglFSWindow(w)
, m_integration(integration)
, m_egl_stream(EGL_NO_STREAM_KHR)
{ }
- void invalidateSurface() Q_DECL_OVERRIDE;
- void resetSurface() Q_DECL_OVERRIDE;
+ void invalidateSurface() override;
+ void resetSurface() override;
const QEglFSKmsEglDeviceIntegration *m_integration;
EGLStreamKHR m_egl_stream;
EGLint m_latency;
};
-void QEglJetsonTK1Window::invalidateSurface()
+void QEglFSKmsEglDeviceWindow::invalidateSurface()
{
QEglFSWindow::invalidateSurface();
m_integration->m_funcs->destroy_stream(screen()->display(), m_egl_stream);
}
-void QEglJetsonTK1Window::resetSurface()
+void QEglFSKmsEglDeviceWindow::resetSurface()
{
qCDebug(qLcEglfsKmsDebug, "Creating stream");
@@ -173,7 +172,7 @@ void QEglJetsonTK1Window::resetSurface()
QEglFSKmsEglDeviceScreen *cur_screen = static_cast<QEglFSKmsEglDeviceScreen *>(screen());
Q_ASSERT(cur_screen);
- QEglFSKmsOutput &output(cur_screen->output());
+ QKmsOutput &output(cur_screen->output());
const uint32_t wantedId = !output.wants_plane ? output.crtc_id : output.plane_id;
qCDebug(qLcEglfsKmsDebug, "Searching for id: %d", wantedId);
@@ -235,7 +234,7 @@ void QEglJetsonTK1Window::resetSurface()
QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const
{
- QEglJetsonTK1Window *eglWindow = new QEglJetsonTK1Window(window, this);
+ QEglFSKmsEglDeviceWindow *eglWindow = new QEglFSKmsEglDeviceWindow(window, this);
m_funcs->initialize(eglWindow->screen()->display());
if (Q_UNLIKELY(!(m_funcs->has_egl_output_base && m_funcs->has_egl_output_drm && m_funcs->has_egl_stream &&
@@ -245,10 +244,8 @@ QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const
return eglWindow;
}
-QEglFSKmsDevice *QEglFSKmsEglDeviceIntegration::createDevice(const QString &devicePath)
+QKmsDevice *QEglFSKmsEglDeviceIntegration::createDevice()
{
- Q_UNUSED(devicePath)
-
if (Q_UNLIKELY(!query_egl_device()))
qFatal("Could not set up EGL device!");
@@ -256,7 +253,7 @@ QEglFSKmsDevice *QEglFSKmsEglDeviceIntegration::createDevice(const QString &devi
if (Q_UNLIKELY(!deviceName))
qFatal("Failed to query device name from EGLDevice");
- return new QEglFSKmsEglDevice(this, deviceName);
+ return new QEglFSKmsEglDevice(this, screenConfig(), deviceName);
}
bool QEglFSKmsEglDeviceIntegration::query_egl_device()
@@ -283,7 +280,7 @@ bool QEglFSKmsEglDeviceIntegration::query_egl_device()
QPlatformCursor *QEglFSKmsEglDeviceIntegration::createCursor(QPlatformScreen *screen) const
{
- return separateScreens() ? new QEglFSCursor(screen) : nullptr;
+ return screenConfig()->separateScreens() ? new QEglFSCursor(screen) : nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
index cddfdbd5c6..62404cfcd1 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
@@ -55,27 +55,26 @@ class QEglFSKmsEglDeviceIntegration : public QEglFSKmsIntegration
public:
QEglFSKmsEglDeviceIntegration();
- EGLint surfaceType() const Q_DECL_OVERRIDE;
- EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) Q_DECL_OVERRIDE;
- bool supportsSurfacelessContexts() const Q_DECL_OVERRIDE;
- bool supportsPBuffers() const Q_DECL_OVERRIDE;
- QEglFSWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE;
+ EGLint surfaceType() const override;
+ EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) override;
+ bool supportsSurfacelessContexts() const override;
+ bool supportsPBuffers() const override;
+ QEglFSWindow *createWindow(QWindow *window) const override;
EGLDeviceEXT eglDevice() const { return m_egl_device; }
protected:
- QEglFSKmsDevice *createDevice(const QString &devicePath) Q_DECL_OVERRIDE;
- QPlatformCursor *createCursor(QPlatformScreen *screen) const Q_DECL_OVERRIDE;
+ QKmsDevice *createDevice() override;
+ QPlatformCursor *createCursor(QPlatformScreen *screen) const override;
private:
bool setup_kms();
bool query_egl_device();
EGLDeviceEXT m_egl_device;
-
- friend class QEglJetsonTK1Window;
- // EGLStream infrastructure
QEGLStreamConvenience *m_funcs;
+
+ friend class QEglFSKmsEglDeviceWindow;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp
index 42fec073f1..5763ab45cc 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicemain.cpp
@@ -47,7 +47,7 @@ class QEglFSKmsEglDeviceIntegrationPlugin : public QEglFSDeviceIntegrationPlugin
Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_kms_egldevice.json")
public:
- QEglFSDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSKmsEglDeviceIntegration; }
+ QEglFSDeviceIntegration *create() override { return new QEglFSKmsEglDeviceIntegration; }
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
index 3935c99b9e..7e5477e4bf 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
@@ -40,11 +40,14 @@
#include "qeglfskmsegldevicescreen.h"
#include "qeglfskmsegldevice.h"
#include <QGuiApplication>
+#include <QLoggingCategory>
QT_BEGIN_NAMESPACE
-QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output)
- : QEglFSKmsScreen(integration, device, output)
+Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+
+QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QKmsDevice *device, const QKmsOutput &output)
+ : QEglFSKmsScreen(device, output)
{
}
@@ -52,7 +55,7 @@ QEglFSKmsEglDeviceScreen::~QEglFSKmsEglDeviceScreen()
{
const int remainingScreenCount = qGuiApp->screens().count();
qCDebug(qLcEglfsKmsDebug, "Screen dtor. Remaining screens: %d", remainingScreenCount);
- if (!remainingScreenCount && !m_integration->separateScreens())
+ if (!remainingScreenCount && !device()->screenConfig()->separateScreens())
static_cast<QEglFSKmsEglDevice *>(device())->destroyGlobalCursor();
}
@@ -62,12 +65,15 @@ QPlatformCursor *QEglFSKmsEglDeviceScreen::cursor() const
// in its ctor. With separateScreens just use that. Otherwise
// there's a virtual desktop and the device has a global cursor
// and the base class has no dedicated cursor at all.
- return m_integration->separateScreens() ? QEglFSScreen::cursor() : static_cast<QEglFSKmsEglDevice *>(device())->globalCursor();
+ // config->hwCursor() is ignored for now, just use the standard OpenGL cursor.
+ return device()->screenConfig()->separateScreens()
+ ? QEglFSScreen::cursor()
+ : static_cast<QEglFSKmsEglDevice *>(device())->globalCursor();
}
void QEglFSKmsEglDeviceScreen::waitForFlip()
{
- QEglFSKmsOutput &op(output());
+ QKmsOutput &op(output());
const int fd = device()->fd();
const uint32_t w = op.modes[op.mode].hdisplay;
const uint32_t h = op.modes[op.mode].vdisplay;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h
index c57f52c6b7..5efe35f8b3 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.h
@@ -47,14 +47,12 @@ QT_BEGIN_NAMESPACE
class QEglFSKmsEglDeviceScreen : public QEglFSKmsScreen
{
public:
- QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output);
+ QEglFSKmsEglDeviceScreen(QKmsDevice *device, const QKmsOutput &output);
~QEglFSKmsEglDeviceScreen();
- QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
+ QPlatformCursor *cursor() const override;
- void waitForFlip() Q_DECL_OVERRIDE;
+ void waitForFlip() override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
index 487edb569e..3c0a0ce30f 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
@@ -2,7 +2,7 @@ TARGET = QtEglFsKmsSupport
CONFIG += no_module_headers internal_module
load(qt_module)
-QT += core-private gui-private eglfsdeviceintegration-private
+QT += core-private gui-private eglfsdeviceintegration-private kms_support-private
INCLUDEPATH += $$PWD/../../api
@@ -15,8 +15,8 @@ QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
SOURCES += $$PWD/qeglfskmsintegration.cpp \
$$PWD/qeglfskmsdevice.cpp \
- $$PWD/qeglfskmsscreen.cpp \
+ $$PWD/qeglfskmsscreen.cpp
HEADERS += $$PWD/qeglfskmsintegration.h \
$$PWD/qeglfskmsdevice.h \
- $$PWD/qeglfskmsscreen.h \
+ $$PWD/qeglfskmsscreen.h
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp
index f372b9d156..e99a6957a8 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp
@@ -1,6 +1,5 @@
/****************************************************************************
**
-** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Pelagicore AG
** Contact: https://www.qt.io/licensing/
@@ -41,464 +40,24 @@
#include "qeglfskmsdevice.h"
#include "qeglfskmsscreen.h"
-
-#include "qeglfsintegration_p.h"
-
-#include <QtCore/QLoggingCategory>
-#include <QtCore/private/qcore_unix_p.h>
+#include "private/qeglfsintegration_p.h"
#include <QtGui/private/qguiapplication_p.h>
-#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
-
QT_BEGIN_NAMESPACE
-Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
-
-enum OutputConfiguration {
- OutputConfigOff,
- OutputConfigPreferred,
- OutputConfigCurrent,
- OutputConfigMode,
- OutputConfigModeline
-};
-
-int QEglFSKmsDevice::crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector)
-{
- for (int i = 0; i < connector->count_encoders; i++) {
- drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->encoders[i]);
- if (!encoder) {
- qWarning("Failed to get encoder");
- continue;
- }
-
- quint32 possibleCrtcs = encoder->possible_crtcs;
- drmModeFreeEncoder(encoder);
-
- for (int j = 0; j < resources->count_crtcs; j++) {
- bool isPossible = possibleCrtcs & (1 << j);
- bool isAvailable = !(m_crtc_allocator & 1 << resources->crtcs[j]);
-
- if (isPossible && isAvailable)
- return j;
- }
- }
-
- return -1;
-}
-
-static const char * const connector_type_names[] = { // must match DRM_MODE_CONNECTOR_*
- "None",
- "VGA",
- "DVI",
- "DVI",
- "DVI",
- "Composite",
- "TV",
- "LVDS",
- "CTV",
- "DIN",
- "DP",
- "HDMI",
- "HDMI",
- "TV",
- "eDP",
- "Virtual",
- "DSI"
-};
-
-static QByteArray nameForConnector(const drmModeConnectorPtr connector)
-{
- const QByteArray id = QByteArray::number(connector->connector_type_id);
- if (connector->connector_type < ARRAY_LENGTH(connector_type_names))
- return connector_type_names[connector->connector_type] + id;
- return "UNKNOWN" + id;
-}
-
-static bool parseModeline(const QByteArray &text, drmModeModeInfoPtr mode)
-{
- char hsync[16];
- char vsync[16];
- float fclock;
-
- mode->type = DRM_MODE_TYPE_USERDEF;
- mode->hskew = 0;
- mode->vscan = 0;
- mode->vrefresh = 0;
- mode->flags = 0;
-
- if (sscanf(text.constData(), "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s",
- &fclock,
- &mode->hdisplay,
- &mode->hsync_start,
- &mode->hsync_end,
- &mode->htotal,
- &mode->vdisplay,
- &mode->vsync_start,
- &mode->vsync_end,
- &mode->vtotal, hsync, vsync) != 11)
- return false;
-
- mode->clock = fclock * 1000;
-
- if (strcmp(hsync, "+hsync") == 0)
- mode->flags |= DRM_MODE_FLAG_PHSYNC;
- else if (strcmp(hsync, "-hsync") == 0)
- mode->flags |= DRM_MODE_FLAG_NHSYNC;
- else
- return false;
-
- if (strcmp(vsync, "+vsync") == 0)
- mode->flags |= DRM_MODE_FLAG_PVSYNC;
- else if (strcmp(vsync, "-vsync") == 0)
- mode->flags |= DRM_MODE_FLAG_NVSYNC;
- else
- return false;
-
- return true;
-}
-
-QEglFSKmsScreen *QEglFSKmsDevice::createScreenForConnector(drmModeResPtr resources,
- drmModeConnectorPtr connector,
- VirtualDesktopInfo *vinfo)
-{
- const QByteArray connectorName = nameForConnector(connector);
-
- const int crtc = crtcForConnector(resources, connector);
- if (crtc < 0) {
- qWarning() << "No usable crtc/encoder pair for connector" << connectorName;
- return Q_NULLPTR;
- }
-
- OutputConfiguration configuration;
- QSize configurationSize;
- drmModeModeInfo configurationModeline;
-
- auto userConfig = m_integration->outputSettings();
- auto userConnectorConfig = userConfig.value(QString::fromUtf8(connectorName));
- // default to the preferred mode unless overridden in the config
- const QByteArray mode = userConnectorConfig.value(QStringLiteral("mode"), QStringLiteral("preferred"))
- .toByteArray().toLower();
- if (mode == "off") {
- configuration = OutputConfigOff;
- } else if (mode == "preferred") {
- configuration = OutputConfigPreferred;
- } else if (mode == "current") {
- configuration = OutputConfigCurrent;
- } else if (sscanf(mode.constData(), "%dx%d", &configurationSize.rwidth(), &configurationSize.rheight()) == 2) {
- configuration = OutputConfigMode;
- } else if (parseModeline(mode, &configurationModeline)) {
- configuration = OutputConfigModeline;
- } else {
- qWarning("Invalid mode \"%s\" for output %s", mode.constData(), connectorName.constData());
- configuration = OutputConfigPreferred;
- }
- if (vinfo) {
- *vinfo = VirtualDesktopInfo();
- vinfo->virtualIndex = userConnectorConfig.value(QStringLiteral("virtualIndex"), INT_MAX).toInt();
- if (userConnectorConfig.contains(QStringLiteral("virtualPos"))) {
- const QByteArray vpos = userConnectorConfig.value(QStringLiteral("virtualPos")).toByteArray();
- const QByteArrayList vposComp = vpos.split(',');
- if (vposComp.count() == 2)
- vinfo->virtualPos = QPoint(vposComp[0].trimmed().toInt(), vposComp[1].trimmed().toInt());
- }
- }
-
- const uint32_t crtc_id = resources->crtcs[crtc];
-
- if (configuration == OutputConfigOff) {
- qCDebug(qLcEglfsKmsDebug) << "Turning off output" << connectorName;
- drmModeSetCrtc(m_dri_fd, crtc_id, 0, 0, 0, 0, 0, Q_NULLPTR);
- return Q_NULLPTR;
- }
-
- // Skip disconnected output
- if (configuration == OutputConfigPreferred && connector->connection == DRM_MODE_DISCONNECTED) {
- qCDebug(qLcEglfsKmsDebug) << "Skipping disconnected output" << connectorName;
- return Q_NULLPTR;
- }
-
- // Get the current mode on the current crtc
- drmModeModeInfo crtc_mode;
- memset(&crtc_mode, 0, sizeof crtc_mode);
- if (drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->connector_id)) {
- drmModeCrtcPtr crtc = drmModeGetCrtc(m_dri_fd, encoder->crtc_id);
- drmModeFreeEncoder(encoder);
-
- if (!crtc)
- return Q_NULLPTR;
-
- if (crtc->mode_valid)
- crtc_mode = crtc->mode;
-
- drmModeFreeCrtc(crtc);
- }
-
- QList<drmModeModeInfo> modes;
- modes.reserve(connector->count_modes);
- qCDebug(qLcEglfsKmsDebug) << connectorName << "mode count:" << connector->count_modes;
- for (int i = 0; i < connector->count_modes; i++) {
- const drmModeModeInfo &mode = connector->modes[i];
- qCDebug(qLcEglfsKmsDebug) << "mode" << i << mode.hdisplay << "x" << mode.vdisplay
- << '@' << mode.vrefresh << "hz";
- modes << connector->modes[i];
- }
-
- int preferred = -1;
- int current = -1;
- int configured = -1;
- int best = -1;
-
- for (int i = modes.size() - 1; i >= 0; i--) {
- const drmModeModeInfo &m = modes.at(i);
-
- if (configuration == OutputConfigMode &&
- m.hdisplay == configurationSize.width() &&
- m.vdisplay == configurationSize.height()) {
- configured = i;
- }
-
- if (!memcmp(&crtc_mode, &m, sizeof m))
- current = i;
-
- if (m.type & DRM_MODE_TYPE_PREFERRED)
- preferred = i;
-
- best = i;
- }
-
- if (configuration == OutputConfigModeline) {
- modes << configurationModeline;
- configured = modes.size() - 1;
- }
-
- if (current < 0 && crtc_mode.clock != 0) {
- modes << crtc_mode;
- current = mode.size() - 1;
- }
-
- if (configuration == OutputConfigCurrent)
- configured = current;
-
- int selected_mode = -1;
-
- if (configured >= 0)
- selected_mode = configured;
- else if (preferred >= 0)
- selected_mode = preferred;
- else if (current >= 0)
- selected_mode = current;
- else if (best >= 0)
- selected_mode = best;
-
- if (selected_mode < 0) {
- qWarning() << "No modes available for output" << connectorName;
- return Q_NULLPTR;
- } else {
- int width = modes[selected_mode].hdisplay;
- int height = modes[selected_mode].vdisplay;
- int refresh = modes[selected_mode].vrefresh;
- qCDebug(qLcEglfsKmsDebug) << "Selected mode" << selected_mode << ":" << width << "x" << height
- << '@' << refresh << "hz for output" << connectorName;
- }
-
- // physical size from connector < config values < env vars
- static const int width = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_WIDTH");
- static const int height = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_HEIGHT");
- QSizeF physSize(width, height);
- if (physSize.isEmpty()) {
- physSize = QSize(userConnectorConfig.value(QStringLiteral("physicalWidth")).toInt(),
- userConnectorConfig.value(QStringLiteral("physicalHeight")).toInt());
- if (physSize.isEmpty()) {
- physSize.setWidth(connector->mmWidth);
- physSize.setHeight(connector->mmHeight);
- }
- }
- qCDebug(qLcEglfsKmsDebug) << "Physical size is" << physSize << "mm" << "for output" << connectorName;
-
- QEglFSKmsOutput output = {
- QString::fromUtf8(connectorName),
- connector->connector_id,
- crtc_id,
- physSize,
- selected_mode,
- false,
- drmModeGetCrtc(m_dri_fd, crtc_id),
- modes,
- connector->subpixel,
- connectorProperty(connector, QByteArrayLiteral("DPMS")),
- false,
- 0,
- false
- };
-
- bool ok;
- int idx = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_PLANE_INDEX", &ok);
- if (ok) {
- drmModePlaneRes *planeResources = drmModeGetPlaneResources(m_dri_fd);
- if (planeResources) {
- if (idx >= 0 && idx < int(planeResources->count_planes)) {
- drmModePlane *plane = drmModeGetPlane(m_dri_fd, planeResources->planes[idx]);
- if (plane) {
- output.wants_plane = true;
- output.plane_id = plane->plane_id;
- qCDebug(qLcEglfsKmsDebug, "Forcing plane index %d, plane id %u (belongs to crtc id %u)",
- idx, plane->plane_id, plane->crtc_id);
- drmModeFreePlane(plane);
- }
- } else {
- qWarning("Invalid plane index %d, must be between 0 and %u", idx, planeResources->count_planes - 1);
- }
- }
- }
-
- m_crtc_allocator |= (1 << output.crtc_id);
- m_connector_allocator |= (1 << output.connector_id);
-
- return createScreen(m_integration, this, output);
-}
-
-drmModePropertyPtr QEglFSKmsDevice::connectorProperty(drmModeConnectorPtr connector, const QByteArray &name)
-{
- drmModePropertyPtr prop;
-
- for (int i = 0; i < connector->count_props; i++) {
- prop = drmModeGetProperty(m_dri_fd, connector->props[i]);
- if (!prop)
- continue;
- if (strcmp(prop->name, name.constData()) == 0)
- return prop;
- drmModeFreeProperty(prop);
- }
-
- return Q_NULLPTR;
-}
-
-QEglFSKmsDevice::QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path)
- : m_integration(integration)
- , m_path(path)
- , m_dri_fd(-1)
- , m_crtc_allocator(0)
- , m_connector_allocator(0)
-{
-}
-
-QEglFSKmsDevice::~QEglFSKmsDevice()
-{
-}
-
-struct OrderedScreen
-{
- OrderedScreen() : screen(nullptr) { }
- OrderedScreen(QEglFSKmsScreen *screen, const QEglFSKmsDevice::VirtualDesktopInfo &vinfo)
- : screen(screen), vinfo(vinfo) { }
- QEglFSKmsScreen *screen;
- QEglFSKmsDevice::VirtualDesktopInfo vinfo;
-};
-
-QDebug operator<<(QDebug dbg, const OrderedScreen &s)
-{
- QDebugStateSaver saver(dbg);
- dbg.nospace() << "OrderedScreen(" << s.screen << " : " << s.vinfo.virtualIndex
- << " / " << s.vinfo.virtualPos << ")";
- return dbg;
-}
-
-static bool orderedScreenLessThan(const OrderedScreen &a, const OrderedScreen &b)
-{
- return a.vinfo.virtualIndex < b.vinfo.virtualIndex;
-}
-
-void QEglFSKmsDevice::createScreens()
-{
- drmModeResPtr resources = drmModeGetResources(m_dri_fd);
- if (!resources) {
- qWarning("drmModeGetResources failed");
- return;
- }
-
- QVector<OrderedScreen> screens;
-
- int wantedConnectorIndex = -1;
- bool ok;
- int idx = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_CONNECTOR_INDEX", &ok);
- if (ok) {
- if (idx >= 0 && idx < resources->count_connectors)
- wantedConnectorIndex = idx;
- else
- qWarning("Invalid connector index %d, must be between 0 and %u", idx, resources->count_connectors - 1);
- }
-
- for (int i = 0; i < resources->count_connectors; i++) {
- if (wantedConnectorIndex >= 0 && i != wantedConnectorIndex)
- continue;
-
- drmModeConnectorPtr connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]);
- if (!connector)
- continue;
-
- VirtualDesktopInfo vinfo;
- QEglFSKmsScreen *screen = createScreenForConnector(resources, connector, &vinfo);
- if (screen)
- screens.append(OrderedScreen(screen, vinfo));
-
- drmModeFreeConnector(connector);
- }
-
- drmModeFreeResources(resources);
-
- // Use stable sort to preserve the original order for outputs with unspecified indices.
- std::stable_sort(screens.begin(), screens.end(), orderedScreenLessThan);
- qCDebug(qLcEglfsKmsDebug) << "Sorted screen list:" << screens;
-
- QPoint pos(0, 0);
- QList<QPlatformScreen *> siblings;
- QEglFSIntegration *qpaIntegration = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration());
-
- for (const OrderedScreen &orderedScreen : screens) {
- QEglFSKmsScreen *s = orderedScreen.screen;
- // set up a horizontal or vertical virtual desktop
- if (orderedScreen.vinfo.virtualPos.isNull()) {
- s->setVirtualPosition(pos);
- if (m_integration->virtualDesktopLayout() == QEglFSKmsIntegration::VirtualDesktopLayoutVertical)
- pos.ry() += s->geometry().height();
- else
- pos.rx() += s->geometry().width();
- } else {
- s->setVirtualPosition(orderedScreen.vinfo.virtualPos);
- }
- qCDebug(qLcEglfsKmsDebug) << "Adding screen" << s << "to QPA with geometry" << s->geometry();
- // The order in qguiapp's screens list will match the order set by
- // virtualIndex. This is not only handy but also required since for instance
- // evdevtouch relies on it when performing touch device - screen mapping.
- qpaIntegration->addScreen(s);
- siblings << s;
- }
-
- if (!m_integration->separateScreens()) {
- // enable the virtual desktop
- Q_FOREACH (QPlatformScreen *screen, siblings)
- static_cast<QEglFSKmsScreen *>(screen)->setVirtualSiblings(siblings);
- }
-}
-
-int QEglFSKmsDevice::fd() const
-{
- return m_dri_fd;
-}
-
-QString QEglFSKmsDevice::devicePath() const
-{
- return m_path;
-}
-
-QEglFSKmsScreen *QEglFSKmsDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output)
+QEglFSKmsDevice::QEglFSKmsDevice(QKmsScreenConfig *screenConfig, const QString &path)
+ : QKmsDevice(screenConfig, path)
{
- return new QEglFSKmsScreen(integration, device, output);
}
-void QEglFSKmsDevice::setFd(int fd)
+void QEglFSKmsDevice::registerScreen(QPlatformScreen *screen,
+ const QPoint &virtualPos,
+ const QList<QPlatformScreen *> &virtualSiblings)
{
- m_dri_fd = fd;
+ QEglFSKmsScreen *s = static_cast<QEglFSKmsScreen *>(screen);
+ s->setVirtualPosition(virtualPos);
+ s->setVirtualSiblings(virtualSiblings);
+ static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->addScreen(s);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h
index 3e7ac7e3f0..1bbea250bb 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.h
@@ -1,6 +1,5 @@
/****************************************************************************
**
-** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Pelagicore AG
** Contact: https://www.qt.io/licensing/
@@ -42,64 +41,21 @@
#ifndef QEGLFSKMSDEVICE_H
#define QEGLFSKMSDEVICE_H
-#include "qeglfskmsintegration.h"
-#include "qeglfskmsscreen.h"
-
-#include <xf86drm.h>
-#include <xf86drmMode.h>
+#include "private/qeglfsglobal_p.h"
+#include <QtKmsSupport/private/qkmsdevice_p.h>
QT_BEGIN_NAMESPACE
-class Q_EGLFS_EXPORT QEglFSKmsDevice
+class Q_EGLFS_EXPORT QEglFSKmsDevice : public QKmsDevice
{
public:
- struct VirtualDesktopInfo {
- VirtualDesktopInfo() : virtualIndex(0) { }
- int virtualIndex;
- QPoint virtualPos;
- };
-
- QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path);
- virtual ~QEglFSKmsDevice();
-
- virtual bool open() = 0;
- virtual void close() = 0;
-
- virtual void createScreens();
-
- virtual EGLNativeDisplayType nativeDisplay() const = 0;
- int fd() const;
- QString devicePath() const;
-
-protected:
- virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output);
- void setFd(int fd);
-
- QEglFSKmsIntegration *m_integration;
- QString m_path;
- int m_dri_fd;
-
- quint32 m_crtc_allocator;
- quint32 m_connector_allocator;
-
- int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector);
- QEglFSKmsScreen *createScreenForConnector(drmModeResPtr resources,
- drmModeConnectorPtr connector,
- VirtualDesktopInfo *vinfo);
- drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
-
- static void pageFlipHandler(int fd,
- unsigned int sequence,
- unsigned int tv_sec,
- unsigned int tv_usec,
- void *user_data);
+ QEglFSKmsDevice(QKmsScreenConfig *screenConfig, const QString &path);
-private:
- Q_DISABLE_COPY(QEglFSKmsDevice)
+ void registerScreen(QPlatformScreen *screen,
+ const QPoint &virtualPos,
+ const QList<QPlatformScreen *> &virtualSiblings) override;
};
QT_END_NAMESPACE
-#endif
+#endif // QEGLFSKMSDEVICE_H
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
index 5368a6d031..c77151181e 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
@@ -40,13 +40,10 @@
****************************************************************************/
#include "qeglfskmsintegration.h"
-#include "qeglfskmsdevice.h"
#include "qeglfskmsscreen.h"
-#include <QtCore/QJsonDocument>
-#include <QtCore/QJsonObject>
-#include <QtCore/QJsonArray>
-#include <QtCore/QFile>
+#include <QtKmsSupport/private/qkmsdevice_p.h>
+
#include <QtGui/qpa/qplatformwindow.h>
#include <QtGui/QScreen>
@@ -58,28 +55,27 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms")
QEglFSKmsIntegration::QEglFSKmsIntegration()
- : m_device(Q_NULLPTR)
- , m_hwCursor(false)
- , m_pbuffers(false)
- , m_separateScreens(false)
- , m_virtualDesktopLayout(VirtualDesktopLayoutHorizontal)
-{}
-
-void QEglFSKmsIntegration::platformInit()
+ : m_device(Q_NULLPTR),
+ m_screenConfig(new QKmsScreenConfig)
{
- loadConfig();
+}
- if (!m_devicePath.isEmpty()) {
- qCDebug(qLcEglfsKmsDebug) << "Using DRM device" << m_devicePath << "specified in config file";
- }
+QEglFSKmsIntegration::~QEglFSKmsIntegration()
+{
+ delete m_screenConfig;
+}
- m_device = createDevice(m_devicePath);
+void QEglFSKmsIntegration::platformInit()
+{
+ qCDebug(qLcEglfsKmsDebug, "platformInit: Opening DRM device");
+ m_device = createDevice();
if (Q_UNLIKELY(!m_device->open()))
- qFatal("Could not open device %s - aborting!", qPrintable(m_devicePath));
+ qFatal("Could not open DRM device");
}
void QEglFSKmsIntegration::platformDestroy()
{
+ qCDebug(qLcEglfsKmsDebug, "platformDestroy: Closing DRM device");
m_device->close();
delete m_device;
m_device = Q_NULLPTR;
@@ -88,7 +84,7 @@ void QEglFSKmsIntegration::platformDestroy()
EGLNativeDisplayType QEglFSKmsIntegration::platformDisplay() const
{
Q_ASSERT(m_device);
- return m_device->nativeDisplay();
+ return (EGLNativeDisplayType) m_device->nativeDisplay();
}
bool QEglFSKmsIntegration::usesDefaultScreen()
@@ -134,94 +130,17 @@ void QEglFSKmsIntegration::waitForVSync(QPlatformSurface *surface) const
bool QEglFSKmsIntegration::supportsPBuffers() const
{
- return m_pbuffers;
-}
-
-bool QEglFSKmsIntegration::hwCursor() const
-{
- return m_hwCursor;
-}
-
-bool QEglFSKmsIntegration::separateScreens() const
-{
- return m_separateScreens;
-}
-
-QEglFSKmsIntegration::VirtualDesktopLayout QEglFSKmsIntegration::virtualDesktopLayout() const
-{
- return m_virtualDesktopLayout;
+ return m_screenConfig->supportsPBuffers();
}
-QMap<QString, QVariantMap> QEglFSKmsIntegration::outputSettings() const
-{
- return m_outputSettings;
-}
-
-QEglFSKmsDevice *QEglFSKmsIntegration::device() const
+QKmsDevice *QEglFSKmsIntegration::device() const
{
return m_device;
}
-void QEglFSKmsIntegration::loadConfig()
+QKmsScreenConfig *QEglFSKmsIntegration::screenConfig() const
{
- static QByteArray json = qgetenv("QT_QPA_EGLFS_KMS_CONFIG");
- if (json.isEmpty())
- return;
-
- qCDebug(qLcEglfsKmsDebug) << "Loading KMS setup from" << json;
-
- QFile file(QString::fromUtf8(json));
- if (!file.open(QFile::ReadOnly)) {
- qCWarning(qLcEglfsKmsDebug) << "Could not open config file"
- << json << "for reading";
- return;
- }
-
- const QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
- if (!doc.isObject()) {
- qCWarning(qLcEglfsKmsDebug) << "Invalid config file" << json
- << "- no top-level JSON object";
- return;
- }
-
- const QJsonObject object = doc.object();
-
- m_hwCursor = object.value(QLatin1String("hwcursor")).toBool(m_hwCursor);
- m_pbuffers = object.value(QLatin1String("pbuffers")).toBool(m_pbuffers);
- m_devicePath = object.value(QLatin1String("device")).toString();
- m_separateScreens = object.value(QLatin1String("separateScreens")).toBool(m_separateScreens);
-
- const QString vdOriString = object.value(QLatin1String("virtualDesktopLayout")).toString();
- if (!vdOriString.isEmpty()) {
- if (vdOriString == QLatin1String("horizontal"))
- m_virtualDesktopLayout = VirtualDesktopLayoutHorizontal;
- else if (vdOriString == QLatin1String("vertical"))
- m_virtualDesktopLayout = VirtualDesktopLayoutVertical;
- else
- qCWarning(qLcEglfsKmsDebug) << "Unknown virtualDesktopOrientation value" << vdOriString;
- }
-
- const QJsonArray outputs = object.value(QLatin1String("outputs")).toArray();
- for (int i = 0; i < outputs.size(); i++) {
- const QVariantMap outputSettings = outputs.at(i).toObject().toVariantMap();
-
- if (outputSettings.contains(QStringLiteral("name"))) {
- const QString name = outputSettings.value(QStringLiteral("name")).toString();
-
- if (m_outputSettings.contains(name)) {
- qCDebug(qLcEglfsKmsDebug) << "Output" << name << "configured multiple times!";
- }
-
- m_outputSettings.insert(name, outputSettings);
- }
- }
-
- qCDebug(qLcEglfsKmsDebug) << "Configuration:\n"
- << "\thwcursor:" << m_hwCursor << "\n"
- << "\tpbuffers:" << m_pbuffers << "\n"
- << "\tseparateScreens:" << m_separateScreens << "\n"
- << "\tvirtualDesktopLayout:" << m_virtualDesktopLayout << "\n"
- << "\toutputs:" << m_outputSettings;
+ return m_screenConfig;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
index ba49945715..9955616919 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
@@ -49,49 +49,35 @@
QT_BEGIN_NAMESPACE
-class QEglFSKmsDevice;
+class QKmsDevice;
+class QKmsScreenConfig;
Q_EGLFS_EXPORT Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
class Q_EGLFS_EXPORT QEglFSKmsIntegration : public QEglFSDeviceIntegration
{
public:
- enum VirtualDesktopLayout {
- VirtualDesktopLayoutHorizontal,
- VirtualDesktopLayoutVertical
- };
-
QEglFSKmsIntegration();
+ ~QEglFSKmsIntegration();
- void platformInit() Q_DECL_OVERRIDE;
- void platformDestroy() Q_DECL_OVERRIDE;
- EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE;
- bool usesDefaultScreen() Q_DECL_OVERRIDE;
- void screenInit() Q_DECL_OVERRIDE;
- QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const Q_DECL_OVERRIDE;
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
- void waitForVSync(QPlatformSurface *surface) const Q_DECL_OVERRIDE;
- bool supportsPBuffers() const Q_DECL_OVERRIDE;
-
- virtual bool hwCursor() const;
- virtual bool separateScreens() const;
- virtual VirtualDesktopLayout virtualDesktopLayout() const;
- QMap<QString, QVariantMap> outputSettings() const;
+ void platformInit() override;
+ void platformDestroy() override;
+ EGLNativeDisplayType platformDisplay() const override;
+ bool usesDefaultScreen() override;
+ void screenInit() override;
+ QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const override;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
+ void waitForVSync(QPlatformSurface *surface) const override;
+ bool supportsPBuffers() const override;
- QEglFSKmsDevice *device() const;
+ QKmsDevice *device() const;
+ QKmsScreenConfig *screenConfig() const;
protected:
- virtual QEglFSKmsDevice *createDevice(const QString &devicePath) = 0;
-
- void loadConfig();
+ virtual QKmsDevice *createDevice() = 0;
- QEglFSKmsDevice *m_device;
- bool m_hwCursor;
- bool m_pbuffers;
- bool m_separateScreens;
- VirtualDesktopLayout m_virtualDesktopLayout;
- QString m_devicePath;
- QMap<QString, QVariantMap> m_outputSettings;
+ QKmsDevice *m_device;
+ QKmsScreenConfig *m_screenConfig;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
index 4021609407..a2af586947 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
@@ -40,7 +40,6 @@
****************************************************************************/
#include "qeglfskmsscreen.h"
-#include "qeglfskmsdevice.h"
#include "qeglfsintegration_p.h"
#include <QtCore/QLoggingCategory>
@@ -69,30 +68,19 @@ private:
QEglFSKmsScreen *m_screen;
};
-QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output)
- : QEglFSScreen(eglGetDisplay(device->nativeDisplay()))
- , m_integration(integration)
+QEglFSKmsScreen::QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output)
+ : QEglFSScreen(eglGetDisplay((EGLNativeDisplayType) device->nativeDisplay()))
, m_device(device)
, m_output(output)
, m_powerState(PowerStateOn)
, m_interruptHandler(new QEglFSKmsInterruptHandler(this))
{
- m_siblings << this; // gets overridden by QEglFSKmsDevice later if !separateScreens
+ m_siblings << this; // gets overridden later
}
QEglFSKmsScreen::~QEglFSKmsScreen()
{
- if (m_output.dpms_prop) {
- drmModeFreeProperty(m_output.dpms_prop);
- m_output.dpms_prop = Q_NULLPTR;
- }
- restoreMode();
- if (m_output.saved_crtc) {
- drmModeFreeCrtc(m_output.saved_crtc);
- m_output.saved_crtc = Q_NULLPTR;
- }
+ m_output.cleanup(m_device);
delete m_interruptHandler;
}
@@ -171,16 +159,7 @@ void QEglFSKmsScreen::flipFinished()
void QEglFSKmsScreen::restoreMode()
{
- if (m_output.mode_set && m_output.saved_crtc) {
- drmModeSetCrtc(m_device->fd(),
- m_output.saved_crtc->crtc_id,
- m_output.saved_crtc->buffer_id,
- 0, 0,
- &m_output.connector_id, 1,
- &m_output.saved_crtc->mode);
-
- m_output.mode_set = false;
- }
+ m_output.restoreMode(m_device);
}
qreal QEglFSKmsScreen::refreshRate() const
@@ -191,20 +170,7 @@ qreal QEglFSKmsScreen::refreshRate() const
QPlatformScreen::SubpixelAntialiasingType QEglFSKmsScreen::subpixelAntialiasingTypeHint() const
{
- switch (m_output.subpixel) {
- default:
- case DRM_MODE_SUBPIXEL_UNKNOWN:
- case DRM_MODE_SUBPIXEL_NONE:
- return Subpixel_None;
- case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
- return Subpixel_RGB;
- case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
- return Subpixel_BGR;
- case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
- return Subpixel_VRGB;
- case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
- return Subpixel_VBGR;
- }
+ return m_output.subpixelAntialiasingTypeHint();
}
QPlatformScreen::PowerState QEglFSKmsScreen::powerState() const
@@ -214,11 +180,7 @@ QPlatformScreen::PowerState QEglFSKmsScreen::powerState() const
void QEglFSKmsScreen::setPowerState(QPlatformScreen::PowerState state)
{
- if (!m_output.dpms_prop)
- return;
-
- drmModeConnectorSetProperty(m_device->fd(), m_output.connector_id,
- m_output.dpms_prop->prop_id, (int)state);
+ m_output.setPowerState(m_device, state);
m_powerState = state;
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
index fa331f0931..80bbb0c7f1 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
@@ -42,65 +42,42 @@
#ifndef QEGLFSKMSSCREEN_H
#define QEGLFSKMSSCREEN_H
-#include "qeglfskmsintegration.h"
#include "private/qeglfsscreen_p.h"
#include <QtCore/QList>
#include <QtCore/QMutex>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
+#include <QtKmsSupport/private/qkmsdevice_p.h>
QT_BEGIN_NAMESPACE
-class QEglFSKmsDevice;
class QEglFSKmsInterruptHandler;
-struct QEglFSKmsOutput
-{
- QString name;
- uint32_t connector_id;
- uint32_t crtc_id;
- QSizeF physical_size;
- int mode; // index of selected mode in list below
- bool mode_set;
- drmModeCrtcPtr saved_crtc;
- QList<drmModeModeInfo> modes;
- int subpixel;
- drmModePropertyPtr dpms_prop;
- bool wants_plane;
- uint32_t plane_id;
- bool plane_set;
-};
-
class Q_EGLFS_EXPORT QEglFSKmsScreen : public QEglFSScreen
{
public:
- QEglFSKmsScreen(QEglFSKmsIntegration *integration,
- QEglFSKmsDevice *device,
- QEglFSKmsOutput output);
+ QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output);
~QEglFSKmsScreen();
void setVirtualPosition(const QPoint &pos);
- QRect rawGeometry() const Q_DECL_OVERRIDE;
+ QRect rawGeometry() const override;
- int depth() const Q_DECL_OVERRIDE;
- QImage::Format format() const Q_DECL_OVERRIDE;
+ int depth() const override;
+ QImage::Format format() const override;
- QSizeF physicalSize() const Q_DECL_OVERRIDE;
- QDpi logicalDpi() const Q_DECL_OVERRIDE;
- Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE;
- Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE;
+ QSizeF physicalSize() const override;
+ QDpi logicalDpi() const override;
+ Qt::ScreenOrientation nativeOrientation() const override;
+ Qt::ScreenOrientation orientation() const override;
- QString name() const Q_DECL_OVERRIDE;
+ QString name() const override;
- qreal refreshRate() const Q_DECL_OVERRIDE;
+ qreal refreshRate() const override;
- QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; }
+ QList<QPlatformScreen *> virtualSiblings() const override { return m_siblings; }
void setVirtualSiblings(QList<QPlatformScreen *> sl) { m_siblings = sl; }
- QEglFSKmsIntegration *integration() const { return m_integration; }
- QEglFSKmsDevice *device() const { return m_device; }
+ QKmsDevice *device() const { return m_device; }
void destroySurface();
@@ -108,19 +85,18 @@ public:
virtual void flip();
virtual void flipFinished();
- QEglFSKmsOutput &output() { return m_output; }
+ QKmsOutput &output() { return m_output; }
void restoreMode();
- SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE;
+ SubpixelAntialiasingType subpixelAntialiasingTypeHint() const override;
- QPlatformScreen::PowerState powerState() const Q_DECL_OVERRIDE;
- void setPowerState(QPlatformScreen::PowerState state) Q_DECL_OVERRIDE;
+ QPlatformScreen::PowerState powerState() const override;
+ void setPowerState(QPlatformScreen::PowerState state) override;
protected:
- QEglFSKmsIntegration *m_integration;
- QEglFSKmsDevice *m_device;
+ QKmsDevice *m_device;
- QEglFSKmsOutput m_output;
+ QKmsOutput m_output;
QPoint m_pos;
QList<QPlatformScreen *> m_siblings;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.h
index 56883a3676..85eda4889f 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.h
@@ -47,9 +47,9 @@ QT_BEGIN_NAMESPACE
class QEglFSMaliIntegration : public QEglFSDeviceIntegration
{
public:
- void platformInit() Q_DECL_OVERRIDE;
- EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) Q_DECL_OVERRIDE;
- void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE;
+ void platformInit() override;
+ EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) override;
+ void destroyNativeWindow(EGLNativeWindowType window) override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmalimain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmalimain.cpp
index a3c804f54d..4f87dab967 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmalimain.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmalimain.cpp
@@ -48,7 +48,7 @@ class QEglFSMaliIntegrationPlugin : public QEglFSDeviceIntegrationPlugin
Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_mali.json")
public:
- QEglFSDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSMaliIntegration; }
+ QEglFSDeviceIntegration *create() override { return new QEglFSMaliIntegration; }
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h
index 2e98c2b4b1..4d1718afcf 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h
@@ -47,11 +47,11 @@ QT_BEGIN_NAMESPACE
class QEglFSVivIntegration : public QEglFSDeviceIntegration
{
public:
- void platformInit() Q_DECL_OVERRIDE;
- QSize screenSize() const Q_DECL_OVERRIDE;
- EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) Q_DECL_OVERRIDE;
- void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE;
- EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE;
+ void platformInit() override;
+ QSize screenSize() const override;
+ EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) override;
+ void destroyNativeWindow(EGLNativeWindowType window) override;
+ EGLNativeDisplayType platformDisplay() const override;
private:
QSize mScreenSize;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivmain.cpp
index ebe2091b1e..0736637b6b 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivmain.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivmain.cpp
@@ -48,7 +48,7 @@ class QEglFSVivIntegrationPlugin : public QEglFSDeviceIntegrationPlugin
Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_viv.json")
public:
- QEglFSDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSVivIntegration; }
+ QEglFSDeviceIntegration *create() override { return new QEglFSVivIntegration; }
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h
index 9abbe817a6..2c49eb6440 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlintegration.h
@@ -48,13 +48,13 @@ QT_BEGIN_NAMESPACE
class QEglFSVivWaylandIntegration : public QEglFSDeviceIntegration
{
public:
- void platformInit() Q_DECL_OVERRIDE;
- QSize screenSize() const Q_DECL_OVERRIDE;
- EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) Q_DECL_OVERRIDE;
- void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE;
- EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE;
+ void platformInit() override;
+ QSize screenSize() const override;
+ EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) override;
+ void destroyNativeWindow(EGLNativeWindowType window) override;
+ EGLNativeDisplayType platformDisplay() const override;
- void *wlDisplay() const Q_DECL_OVERRIDE;
+ void *wlDisplay() const override;
private:
QSize mScreenSize;
EGLNativeDisplayType mNativeDisplay;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlmain.cpp
index 3b26feda07..6cdc9346c0 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlmain.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/qeglfsvivwlmain.cpp
@@ -48,7 +48,7 @@ class QEglFSVivWaylandIntegrationPlugin : public QEglFSDeviceIntegrationPlugin
Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_viv_wl.json")
public:
- QEglFSDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSVivWaylandIntegration; }
+ QEglFSDeviceIntegration *create() override { return new QEglFSVivWaylandIntegration; }
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.h
index c0f0ee5f22..bf431caaac 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.h
@@ -69,15 +69,15 @@ class QEglFSX11Integration : public QEglFSDeviceIntegration
public:
QEglFSX11Integration() : m_connection(0), m_window(0), m_eventReader(0) {}
- void platformInit() Q_DECL_OVERRIDE;
- void platformDestroy() Q_DECL_OVERRIDE;
- EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE;
- QSize screenSize() const Q_DECL_OVERRIDE;
+ void platformInit() override;
+ void platformDestroy() override;
+ EGLNativeDisplayType platformDisplay() const override;
+ QSize screenSize() const override;
EGLNativeWindowType createNativeWindow(QPlatformWindow *window,
const QSize &size,
- const QSurfaceFormat &format) Q_DECL_OVERRIDE;
- void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE;
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+ const QSurfaceFormat &format) override;
+ void destroyNativeWindow(EGLNativeWindowType window) override;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
xcb_connection_t *connection() { return m_connection; }
const xcb_atom_t *atoms() const { return m_atoms; }
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11main.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11main.cpp
index c15e05b657..39ab54ae5a 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11main.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11main.cpp
@@ -48,7 +48,7 @@ class QEglFSX11IntegrationPlugin : public QEglFSDeviceIntegrationPlugin
Q_PLUGIN_METADATA(IID QEglFSDeviceIntegrationFactoryInterface_iid FILE "eglfs_x11.json")
public:
- QEglFSDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSX11Integration; }
+ QEglFSDeviceIntegration *create() override { return new QEglFSX11Integration; }
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/eglfs-plugin.pro b/src/plugins/platforms/eglfs/eglfs-plugin.pro
index cf4863975a..3844328ee0 100644
--- a/src/plugins/platforms/eglfs/eglfs-plugin.pro
+++ b/src/plugins/platforms/eglfs/eglfs-plugin.pro
@@ -2,6 +2,8 @@ TARGET = qeglfs
QT += eglfsdeviceintegration-private
+CONFIG += egl
+
SOURCES += $$PWD/qeglfsmain.cpp
OTHER_FILES += $$PWD/eglfs.json
diff --git a/src/plugins/platforms/eglfs/eglfsdeviceintegration.pro b/src/plugins/platforms/eglfs/eglfsdeviceintegration.pro
index 35af3615bd..5c084b33fc 100644
--- a/src/plugins/platforms/eglfs/eglfsdeviceintegration.pro
+++ b/src/plugins/platforms/eglfs/eglfsdeviceintegration.pro
@@ -12,11 +12,14 @@ QT += \
core-private gui-private \
devicediscovery_support-private eventdispatcher_support-private \
service_support-private theme_support-private fontdatabase_support-private \
- fb_support-private egl_support-private platformcompositor_support-private
+ fb_support-private egl_support-private
qtHaveModule(input_support-private): \
QT += input_support-private
+qtHaveModule(platformcompositor_support-private): \
+ QT += platformcompositor_support-private
+
LIBS += $$QMAKE_LIBS_DYNLOAD
# Avoid X11 header collision, use generic EGL native types
diff --git a/src/plugins/platforms/eglfs/qeglfsmain.cpp b/src/plugins/platforms/eglfs/qeglfsmain.cpp
index 2885d397c6..4f77b7cd17 100644
--- a/src/plugins/platforms/eglfs/qeglfsmain.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsmain.cpp
@@ -47,7 +47,7 @@ class QEglFSIntegrationPlugin : public QPlatformIntegrationPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "eglfs.json")
public:
- QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE;
+ QPlatformIntegration *create(const QString&, const QStringList&) override;
};
QPlatformIntegration* QEglFSIntegrationPlugin::create(const QString& system, const QStringList& paramList)
diff --git a/src/plugins/platforms/ios/kernel.pro b/src/plugins/platforms/ios/kernel.pro
index caafe89730..71257d09f7 100644
--- a/src/plugins/platforms/ios/kernel.pro
+++ b/src/plugins/platforms/ios/kernel.pro
@@ -1,5 +1,10 @@
TARGET = qios
+# QTBUG-42937: Work around linker errors caused by circular
+# dependencies between the iOS platform plugin and the user
+# application's main() when the plugin is a shared library.
+qtConfig(shared): CONFIG += static
+
QT += \
core-private gui-private \
clipboard_support-private fontdatabase_support-private graphics_support-private
diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/nsphotolibrarysupport.pro b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/nsphotolibrarysupport.pro
index f4588dda03..7379765599 100644
--- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/nsphotolibrarysupport.pro
+++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/nsphotolibrarysupport.pro
@@ -1,7 +1,11 @@
TARGET = qiosnsphotolibrarysupport
+# QTBUG-42937: Since the iOS plugin (kernel) is
+# static, this plugin needs to be static as well.
+qtConfig(shared): CONFIG += static
+
QT += core gui gui-private
-LIBS += -framework UIKit -framework AssetsLibrary
+LIBS += -framework Foundation -framework UIKit -framework AssetsLibrary
HEADERS = \
qiosfileengineassetslibrary.h \
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index e5b4d6da85..fbf167b514 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -61,6 +61,7 @@
#include <QtFontDatabaseSupport/private/qcoretextfontdatabase_p.h>
#include <QtClipboardSupport/private/qmacmime_p.h>
#include <QDir>
+#include <QOperatingSystemVersion>
#import <AudioToolbox/AudioServices.h>
@@ -119,7 +120,7 @@ QIOSIntegration::QIOSIntegration()
m_touchDevice = new QTouchDevice;
m_touchDevice->setType(QTouchDevice::TouchScreen);
QTouchDevice::Capabilities touchCapabilities = QTouchDevice::Position | QTouchDevice::NormalizedPosition;
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_9_0) {
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)) {
if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
touchCapabilities |= QTouchDevice::Pressure;
}
diff --git a/src/plugins/platforms/ios/qiosmessagedialog.mm b/src/plugins/platforms/ios/qiosmessagedialog.mm
index 50d5442f17..4f0c667861 100644
--- a/src/plugins/platforms/ios/qiosmessagedialog.mm
+++ b/src/plugins/platforms/ios/qiosmessagedialog.mm
@@ -39,6 +39,7 @@
#import <UIKit/UIKit.h>
+#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/qwindow.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformtheme.h>
@@ -109,7 +110,7 @@ bool QIOSMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality win
if (m_alertController // Ensure that the dialog is not showing already
|| !options() // Some message dialogs don't have options (QErrorMessage)
|| windowModality == Qt::NonModal // We can only do modal dialogs
- || QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_8_0) // API limitation
+ || QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) // API limitation
return false;
m_alertController = [[UIAlertController
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index c518f9111d..49268ee076 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -45,6 +45,7 @@
#include "qiosapplicationdelegate.h"
#include "qiosviewcontroller.h"
#include "quiview.h"
+#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/private/qwindow_p.h>
#include <private/qcoregraphics_p.h>
@@ -274,7 +275,7 @@ void QIOSScreen::updateProperties()
if (m_uiScreen == [UIScreen mainScreen]) {
Qt::ScreenOrientation statusBarOrientation = toQtScreenOrientation(UIDeviceOrientation([UIApplication sharedApplication].statusBarOrientation));
- if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_8_0) {
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) {
// On iOS < 8.0 the UIScreen geometry is always in portait, and the system applies
// the screen rotation to the root view-controller's view instead of directly to the
// screen, like iOS 8 and above does.
@@ -302,7 +303,7 @@ void QIOSScreen::updateProperties()
if (m_geometry != previousGeometry) {
QRectF physicalGeometry;
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) {
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) {
// We can't use the primaryOrientation of screen(), as we haven't reported the new geometry yet
Qt::ScreenOrientation primaryOrientation = m_geometry.width() >= m_geometry.height() ?
Qt::LandscapeOrientation : Qt::PortraitOrientation;
@@ -407,7 +408,7 @@ Qt::ScreenOrientation QIOSScreen::nativeOrientation() const
{
CGRect nativeBounds =
#if !defined(Q_OS_TVOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0)
- QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0 ? m_uiScreen.nativeBounds :
+ QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8) ? m_uiScreen.nativeBounds :
#endif
m_uiScreen.bounds;
diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm
index 238d7addf6..48262dad10 100644
--- a/src/plugins/platforms/ios/qiostextinputoverlay.mm
+++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm
@@ -219,7 +219,7 @@ static void executeBlockWithoutAnimation(Block block)
borderLayer.borderColor = [[UIColor lightGrayColor] CGColor];
[self addSublayer:borderLayer];
- if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0) {
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 7)) {
// [UIView snapshotViewAfterScreenUpdates:] is available since iOS 7.0.
// Just silently ignore showing the loupe for older versions.
self.hidden = YES;
@@ -267,7 +267,7 @@ static void executeBlockWithoutAnimation(Block block)
- (void)display
{
- if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0)
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 7))
return;
// Take a snapshow of the target view, magnify the area around the focal
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 2a1444e9e5..259070216e 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -48,6 +48,7 @@
#include "qiosmenu.h"
#endif
+#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qwindow_p.h>
#include <qpa/qwindowsysteminterface_p.h>
@@ -291,7 +292,7 @@
QTouchDevice *touchDevice = QIOSIntegration::instance()->touchDevice();
QTouchDevice::Capabilities touchCapabilities = touchDevice->capabilities();
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_9_0) {
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)) {
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
touchCapabilities |= QTouchDevice::Pressure;
else
diff --git a/src/plugins/platforms/linuxfb/linuxfb.pro b/src/plugins/platforms/linuxfb/linuxfb.pro
index e2fa31211d..d3a4476f80 100644
--- a/src/plugins/platforms/linuxfb/linuxfb.pro
+++ b/src/plugins/platforms/linuxfb/linuxfb.pro
@@ -10,8 +10,18 @@ QT += \
qtHaveModule(input_support-private): \
QT += input_support-private
-SOURCES = main.cpp qlinuxfbintegration.cpp qlinuxfbscreen.cpp
-HEADERS = qlinuxfbintegration.h qlinuxfbscreen.h
+SOURCES = main.cpp \
+ qlinuxfbintegration.cpp \
+ qlinuxfbscreen.cpp
+
+HEADERS = qlinuxfbintegration.h \
+ qlinuxfbscreen.h
+
+qtHaveModule(kms_support-private) {
+ QT += kms_support-private
+ SOURCES += qlinuxfbdrmscreen.cpp
+ HEADERS += qlinuxfbdrmscreen.h
+}
OTHER_FILES += linuxfb.json
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
new file mode 100644
index 0000000000..bdf2634642
--- /dev/null
+++ b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
@@ -0,0 +1,409 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Experimental DRM dumb buffer backend.
+//
+// TODO:
+// Multiscreen: QWindow-QScreen(-output) association. Needs some reorg (device cannot be owned by screen)
+// Find card via devicediscovery like in eglfs_kms.
+// Mode restore like QEglFSKmsInterruptHandler.
+// Formats other then 32 bpp?
+// grabWindow
+
+#include "qlinuxfbdrmscreen.h"
+#include <QLoggingCategory>
+#include <QGuiApplication>
+#include <QPainter>
+#include <QtFbSupport/private/qfbcursor_p.h>
+#include <QtFbSupport/private/qfbwindow_p.h>
+#include <QtKmsSupport/private/qkmsdevice_p.h>
+#include <QtCore/private/qcore_unix_p.h>
+#include <sys/mman.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(qLcFbDrm, "qt.qpa.fb")
+
+static const int BUFFER_COUNT = 2;
+
+class QLinuxFbDevice : public QKmsDevice
+{
+public:
+ struct Framebuffer {
+ Framebuffer() : handle(0), pitch(0), size(0), fb(0), p(MAP_FAILED) { }
+ uint32_t handle;
+ uint32_t pitch;
+ uint64_t size;
+ uint32_t fb;
+ void *p;
+ QImage wrapper;
+ };
+
+ struct Output {
+ Output() : backFb(0), flipped(false) { }
+ QKmsOutput kmsOutput;
+ Framebuffer fb[BUFFER_COUNT];
+ QRegion dirty[BUFFER_COUNT];
+ int backFb;
+ bool flipped;
+ QSize currentRes() const {
+ const drmModeModeInfo &modeInfo(kmsOutput.modes[kmsOutput.mode]);
+ return QSize(modeInfo.hdisplay, modeInfo.vdisplay);
+ }
+ };
+
+ QLinuxFbDevice(QKmsScreenConfig *screenConfig);
+
+ bool open() override;
+ void close() override;
+
+ void createFramebuffers();
+ void destroyFramebuffers();
+ void setMode();
+
+ void swapBuffers(Output *output);
+
+ int outputCount() const { return m_outputs.count(); }
+ Output *output(int idx) { return &m_outputs[idx]; }
+
+private:
+ void *nativeDisplay() const override;
+ QPlatformScreen *createScreen(const QKmsOutput &output) override;
+ void registerScreen(QPlatformScreen *screen,
+ const QPoint &virtualPos,
+ const QList<QPlatformScreen *> &virtualSiblings) override;
+
+ bool createFramebuffer(Output *output, int bufferIdx);
+ void destroyFramebuffer(Output *output, int bufferIdx);
+
+ static void pageFlipHandler(int fd, unsigned int sequence,
+ unsigned int tv_sec, unsigned int tv_usec, void *user_data);
+
+ QVector<Output> m_outputs;
+};
+
+QLinuxFbDevice::QLinuxFbDevice(QKmsScreenConfig *screenConfig)
+ : QKmsDevice(screenConfig, QStringLiteral("/dev/dri/card0"))
+{
+}
+
+bool QLinuxFbDevice::open()
+{
+ int fd = qt_safe_open(devicePath().toLocal8Bit().constData(), O_RDWR | O_CLOEXEC);
+ if (fd == -1) {
+ qErrnoWarning("Could not open DRM device %s", qPrintable(devicePath()));
+ return false;
+ }
+
+ uint64_t hasDumbBuf = 0;
+ if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &hasDumbBuf) == -1 || !hasDumbBuf) {
+ qWarning("Dumb buffers not supported");
+ qt_safe_close(fd);
+ return false;
+ }
+
+ setFd(fd);
+
+ qCDebug(qLcFbDrm, "DRM device %s opened", qPrintable(devicePath()));
+
+ return true;
+}
+
+void QLinuxFbDevice::close()
+{
+ for (Output &output : m_outputs)
+ output.kmsOutput.cleanup(this); // restore mode
+
+ m_outputs.clear();
+
+ if (fd() != -1) {
+ qCDebug(qLcFbDrm, "Closing DRM device");
+ qt_safe_close(fd());
+ setFd(-1);
+ }
+}
+
+void *QLinuxFbDevice::nativeDisplay() const
+{
+ Q_UNREACHABLE();
+ return nullptr;
+}
+
+QPlatformScreen *QLinuxFbDevice::createScreen(const QKmsOutput &output)
+{
+ qCDebug(qLcFbDrm, "Got a new output: %s", qPrintable(output.name));
+ Output o;
+ o.kmsOutput = output;
+ m_outputs.append(o);
+ return nullptr; // no platformscreen, we are not a platform plugin
+}
+
+void QLinuxFbDevice::registerScreen(QPlatformScreen *screen,
+ const QPoint &virtualPos,
+ const QList<QPlatformScreen *> &virtualSiblings)
+{
+ Q_UNUSED(screen);
+ Q_UNUSED(virtualPos);
+ Q_UNUSED(virtualSiblings);
+ Q_UNREACHABLE();
+}
+
+bool QLinuxFbDevice::createFramebuffer(QLinuxFbDevice::Output *output, int bufferIdx)
+{
+ const QSize size = output->currentRes();
+ const uint32_t w = size.width();
+ const uint32_t h = size.height();
+ drm_mode_create_dumb creq = {
+ h,
+ w,
+ 32,
+ 0, 0, 0, 0
+ };
+ if (drmIoctl(fd(), DRM_IOCTL_MODE_CREATE_DUMB, &creq) == -1) {
+ qErrnoWarning(errno, "Failed to create dumb buffer");
+ return false;
+ }
+
+ Framebuffer &fb(output->fb[bufferIdx]);
+ fb.handle = creq.handle;
+ fb.pitch = creq.pitch;
+ fb.size = creq.size;
+ qCDebug(qLcFbDrm, "Got a dumb buffer for size %dx%d, handle %u, pitch %u, size %u",
+ w, h, fb.handle, fb.pitch, (uint) fb.size);
+
+ if (drmModeAddFB(fd(), w, h, 24, 32, fb.pitch, fb.handle, &fb.fb) == -1) {
+ qErrnoWarning(errno, "Failed to add FB");
+ return false;
+ }
+
+ drm_mode_map_dumb mreq = {
+ fb.handle,
+ 0, 0
+ };
+ if (drmIoctl(fd(), DRM_IOCTL_MODE_MAP_DUMB, &mreq) == -1) {
+ qErrnoWarning(errno, "Failed to map dumb buffer");
+ return false;
+ }
+ fb.p = mmap(0, fb.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd(), mreq.offset);
+ if (fb.p == MAP_FAILED) {
+ qErrnoWarning(errno, "Failed to mmap dumb buffer");
+ return false;
+ }
+
+ qCDebug(qLcFbDrm, "FB is %u, mapped at %p", fb.fb, fb.p);
+ memset(fb.p, 0, fb.size);
+
+ fb.wrapper = QImage(static_cast<uchar *>(fb.p), w, h, fb.pitch, QImage::Format_ARGB32);
+
+ return true;
+}
+
+void QLinuxFbDevice::createFramebuffers()
+{
+ for (Output &output : m_outputs) {
+ for (int i = 0; i < BUFFER_COUNT; ++i) {
+ if (!createFramebuffer(&output, i))
+ return;
+ }
+ output.backFb = 0;
+ output.flipped = false;
+ }
+}
+
+void QLinuxFbDevice::destroyFramebuffer(QLinuxFbDevice::Output *output, int bufferIdx)
+{
+ Framebuffer &fb(output->fb[bufferIdx]);
+ if (fb.p != MAP_FAILED)
+ munmap(fb.p, fb.size);
+ if (fb.fb) {
+ if (drmModeRmFB(fd(), fb.fb) == -1)
+ qErrnoWarning("Failed to remove fb");
+ }
+ if (fb.handle) {
+ drm_mode_destroy_dumb dreq = { fb.handle };
+ if (drmIoctl(fd(), DRM_IOCTL_MODE_DESTROY_DUMB, &dreq) == -1)
+ qErrnoWarning(errno, "Failed to destroy dumb buffer %u", fb.handle);
+ }
+ fb = Framebuffer();
+}
+
+void QLinuxFbDevice::destroyFramebuffers()
+{
+ for (Output &output : m_outputs) {
+ for (int i = 0; i < BUFFER_COUNT; ++i)
+ destroyFramebuffer(&output, i);
+ }
+}
+
+void QLinuxFbDevice::setMode()
+{
+ for (Output &output : m_outputs) {
+ drmModeModeInfo &modeInfo(output.kmsOutput.modes[output.kmsOutput.mode]);
+ if (drmModeSetCrtc(fd(), output.kmsOutput.crtc_id, output.fb[0].fb, 0, 0,
+ &output.kmsOutput.connector_id, 1, &modeInfo) == -1) {
+ qErrnoWarning(errno, "Failed to set mode");
+ return;
+ }
+
+ output.kmsOutput.mode_set = true; // have cleanup() to restore the mode
+ output.kmsOutput.setPowerState(this, QPlatformScreen::PowerStateOn);
+ }
+}
+
+void QLinuxFbDevice::pageFlipHandler(int fd, unsigned int sequence,
+ unsigned int tv_sec, unsigned int tv_usec,
+ void *user_data)
+{
+ Q_UNUSED(fd);
+ Q_UNUSED(sequence);
+ Q_UNUSED(tv_sec);
+ Q_UNUSED(tv_usec);
+
+ Output *output = static_cast<Output *>(user_data);
+ output->backFb = (output->backFb + 1) % BUFFER_COUNT;
+}
+
+void QLinuxFbDevice::swapBuffers(Output *output)
+{
+ Framebuffer &fb(output->fb[output->backFb]);
+ if (drmModePageFlip(fd(), output->kmsOutput.crtc_id, fb.fb, DRM_MODE_PAGE_FLIP_EVENT, output) == -1) {
+ qErrnoWarning(errno, "Page flip failed");
+ return;
+ }
+
+ const int fbIdx = output->backFb;
+ while (output->backFb == fbIdx) {
+ drmEventContext drmEvent = {
+ DRM_EVENT_CONTEXT_VERSION,
+ nullptr,
+ pageFlipHandler
+ };
+ // Blocks until there is something to read on the drm fd
+ // and calls back pageFlipHandler once the flip completes.
+ drmHandleEvent(fd(), &drmEvent);
+ }
+}
+
+QLinuxFbDrmScreen::QLinuxFbDrmScreen(const QStringList &args)
+ : m_screenConfig(nullptr),
+ m_device(nullptr)
+{
+ Q_UNUSED(args);
+}
+
+QLinuxFbDrmScreen::~QLinuxFbDrmScreen()
+{
+ if (m_device) {
+ m_device->destroyFramebuffers();
+ m_device->close();
+ delete m_device;
+ }
+ delete m_screenConfig;
+}
+
+bool QLinuxFbDrmScreen::initialize()
+{
+ m_screenConfig = new QKmsScreenConfig;
+ m_device = new QLinuxFbDevice(m_screenConfig);
+ if (!m_device->open())
+ return false;
+
+ // Discover outputs. Calls back Device::createScreen().
+ m_device->createScreens();
+ // Now off to dumb buffer specifics.
+ m_device->createFramebuffers();
+ // Do the modesetting.
+ m_device->setMode();
+
+ QLinuxFbDevice::Output *output(m_device->output(0));
+
+ mGeometry = QRect(QPoint(0, 0), output->currentRes());
+ mDepth = 32;
+ mFormat = QImage::Format_ARGB32;
+ mPhysicalSize = output->kmsOutput.physical_size;
+ qCDebug(qLcFbDrm) << mGeometry << mPhysicalSize;
+
+ QFbScreen::initializeCompositor();
+
+ mCursor = new QFbCursor(this);
+
+ return true;
+}
+
+QRegion QLinuxFbDrmScreen::doRedraw()
+{
+ const QRegion dirty = QFbScreen::doRedraw();
+ if (dirty.isEmpty())
+ return dirty;
+
+ QLinuxFbDevice::Output *output(m_device->output(0));
+
+ for (int i = 0; i < BUFFER_COUNT; ++i)
+ output->dirty[i] += dirty;
+
+ if (output->fb[output->backFb].wrapper.isNull())
+ return dirty;
+
+ QPainter pntr(&output->fb[output->backFb].wrapper);
+ // Image has alpha but no need for blending at this stage.
+ // Do not waste time with the default SourceOver.
+ pntr.setCompositionMode(QPainter::CompositionMode_Source);
+ for (const QRect &rect : qAsConst(output->dirty[output->backFb]))
+ pntr.drawImage(rect, mScreenImage, rect);
+ pntr.end();
+
+ output->dirty[output->backFb] = QRegion();
+
+ m_device->swapBuffers(output);
+
+ return dirty;
+}
+
+QPixmap QLinuxFbDrmScreen::grabWindow(WId wid, int x, int y, int width, int height) const
+{
+ Q_UNUSED(wid);
+ Q_UNUSED(x);
+ Q_UNUSED(y);
+ Q_UNUSED(width);
+ Q_UNUSED(height);
+
+ return QPixmap();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qgammatables.cpp b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.h
index 1d76f7ee3c..50a9576798 100644
--- a/src/gui/painting/qgammatables.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.h
@@ -3,7 +3,7 @@
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the QtGui module of the Qt Toolkit.
+** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,28 +37,32 @@
**
****************************************************************************/
-#include <private/qdrawhelper_p.h>
+#ifndef QLINUXFBDRMSCREEN_H
+#define QLINUXFBDRMSCREEN_H
+
+#include <QtFbSupport/private/qfbscreen_p.h>
QT_BEGIN_NAMESPACE
+class QKmsScreenConfig;
+class QLinuxFbDevice;
-QDrawHelperGammaTables::QDrawHelperGammaTables(qreal smoothing)
+class QLinuxFbDrmScreen : public QFbScreen
{
- const qreal gray_gamma = 2.31;
- for (int i=0; i<256; ++i)
- qt_pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047));
- for (int i=0; i<2048; ++i)
- qt_pow_invgamma[i] = uchar(qRound(qPow(i / qreal(2047.0), 1 / gray_gamma) * 255));
+ Q_OBJECT
+public:
+ QLinuxFbDrmScreen(const QStringList &args);
+ ~QLinuxFbDrmScreen();
- refresh(smoothing);
-}
+ bool initialize() override;
+ QRegion doRedraw() override;
+ QPixmap grabWindow(WId wid, int x, int y, int width, int height) const override;
-void QDrawHelperGammaTables::refresh(qreal smoothing)
-{
- for (int i=0; i<256; ++i) {
- qt_pow_rgb_gamma[i] = uchar(qRound(qPow(i / qreal(255.0), smoothing) * 255));
- qt_pow_rgb_invgamma[i] = uchar(qRound(qPow(i / qreal(255.), 1 / smoothing) * 255));
- }
-}
+private:
+ QKmsScreenConfig *m_screenConfig;
+ QLinuxFbDevice *m_device;
+};
QT_END_NAMESPACE
+
+#endif // QLINUXFBDRMSCREEN_H
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
index c1c235588e..ce193bdf90 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
@@ -39,6 +39,9 @@
#include "qlinuxfbintegration.h"
#include "qlinuxfbscreen.h"
+#if QT_CONFIG(kms)
+#include "qlinuxfbdrmscreen.h"
+#endif
#include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h>
#include <QtServiceSupport/private/qgenericunixservices_p.h>
@@ -69,10 +72,16 @@
QT_BEGIN_NAMESPACE
QLinuxFbIntegration::QLinuxFbIntegration(const QStringList &paramList)
- : m_fontDb(new QGenericUnixFontDatabase),
+ : m_primaryScreen(nullptr),
+ m_fontDb(new QGenericUnixFontDatabase),
m_services(new QGenericUnixServices)
{
- m_primaryScreen = new QLinuxFbScreen(paramList);
+#if QT_CONFIG(kms)
+ if (qEnvironmentVariableIntValue("QT_QPA_FB_DRM") != 0)
+ m_primaryScreen = new QLinuxFbDrmScreen(paramList);
+#endif
+ if (!m_primaryScreen)
+ m_primaryScreen = new QLinuxFbScreen(paramList);
}
QLinuxFbIntegration::~QLinuxFbIntegration()
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h
index e48a1bae28..9934a8cd54 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h
+++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h
@@ -46,7 +46,7 @@
QT_BEGIN_NAMESPACE
class QAbstractEventDispatcher;
-class QLinuxFbScreen;
+class QFbScreen;
class QFbVtHandler;
class QLinuxFbIntegration : public QPlatformIntegration, public QPlatformNativeInterface
@@ -74,7 +74,7 @@ public:
private:
void createInputHandlers();
- QLinuxFbScreen *m_primaryScreen;
+ QFbScreen *m_primaryScreen;
QPlatformInputContext *m_inputContext;
QScopedPointer<QPlatformFontDatabase> m_fontDb;
QScopedPointer<QPlatformServices> m_services;
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
index 246c959fd3..dc7ea08dc5 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
@@ -414,7 +414,7 @@ QRegion QLinuxFbScreen::doRedraw()
mBlitter->setCompositionMode(QPainter::CompositionMode_Source);
for (const QRect &rect : touched)
- mBlitter->drawImage(rect, *mScreenImage, rect);
+ mBlitter->drawImage(rect, mScreenImage, rect);
return touched;
}
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.h b/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
index 1e98191569..c7ce455e6a 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
+++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
@@ -54,11 +54,11 @@ public:
QLinuxFbScreen(const QStringList &args);
~QLinuxFbScreen();
- bool initialize();
+ bool initialize() override;
- QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
+ QPixmap grabWindow(WId wid, int x, int y, int width, int height) const override;
- QRegion doRedraw() Q_DECL_OVERRIDE;
+ QRegion doRedraw() override;
private:
QStringList mArgs;
diff --git a/src/plugins/platforms/minimalegl/minimalegl.pro b/src/plugins/platforms/minimalegl/minimalegl.pro
index 88466e7f36..b7dde9069f 100644
--- a/src/plugins/platforms/minimalegl/minimalegl.pro
+++ b/src/plugins/platforms/minimalegl/minimalegl.pro
@@ -14,14 +14,17 @@ DEFINES += QT_EGL_NO_X11
SOURCES = main.cpp \
qminimaleglintegration.cpp \
qminimaleglwindow.cpp \
- qminimaleglbackingstore.cpp \
qminimaleglscreen.cpp
HEADERS = qminimaleglintegration.h \
qminimaleglwindow.h \
- qminimaleglbackingstore.h \
qminimaleglscreen.h
+qtConfig(opengl) {
+ SOURCES += qminimaleglbackingstore.cpp
+ HEADERS += qminimaleglbackingstore.h
+}
+
CONFIG += egl
OTHER_FILES += \
diff --git a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
index c564e1e431..81512b1561 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
+++ b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
@@ -40,8 +40,9 @@
#include "qminimaleglintegration.h"
#include "qminimaleglwindow.h"
-#include "qminimaleglbackingstore.h"
-
+#ifndef QT_NO_OPENGL
+# include "qminimaleglbackingstore.h"
+#endif
#include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h>
#if defined(Q_OS_UNIX)
@@ -127,13 +128,18 @@ QPlatformBackingStore *QMinimalEglIntegration::createPlatformBackingStore(QWindo
#ifdef QEGL_EXTRA_DEBUG
qWarning("QMinimalEglIntegration::createWindowSurface %p\n", window);
#endif
+#ifndef QT_NO_OPENGL
return new QMinimalEglBackingStore(window);
+#else
+ return nullptr;
+#endif
}
-
+#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *QMinimalEglIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
return static_cast<QMinimalEglScreen *>(context->screen()->handle())->platformContext();
}
+#endif
QPlatformFontDatabase *QMinimalEglIntegration::fontDatabase() const
{
diff --git a/src/plugins/platforms/minimalegl/qminimaleglintegration.h b/src/plugins/platforms/minimalegl/qminimaleglintegration.h
index 529e89f85a..d0ab75bd3c 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglintegration.h
+++ b/src/plugins/platforms/minimalegl/qminimaleglintegration.h
@@ -55,8 +55,9 @@ public:
QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
+#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
-
+#endif
QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/minimalegl/qminimaleglscreen.cpp b/src/plugins/platforms/minimalegl/qminimaleglscreen.cpp
index d3d091fab7..0175d2dbdd 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglscreen.cpp
+++ b/src/plugins/platforms/minimalegl/qminimaleglscreen.cpp
@@ -41,7 +41,9 @@
#include "qminimaleglwindow.h"
#include <QtEglSupport/private/qeglconvenience_p.h>
-#include <QtEglSupport/private/qeglplatformcontext_p.h>
+#ifndef QT_NO_OPENGL
+# include <QtEglSupport/private/qeglplatformcontext_p.h>
+#endif
#ifdef Q_OPENKODE
#include <KD/kd.h>
@@ -52,6 +54,8 @@ QT_BEGIN_NAMESPACE
// #define QEGL_EXTRA_DEBUG
+#ifndef QT_NO_OPENGL
+
class QMinimalEglContext : public QEGLPlatformContext
{
public:
@@ -68,6 +72,8 @@ public:
}
};
+#endif
+
QMinimalEglScreen::QMinimalEglScreen(EGLNativeDisplayType display)
: m_depth(32)
, m_format(QImage::Format_Invalid)
@@ -161,9 +167,10 @@ void QMinimalEglScreen::createAndSetPlatformContext()
}
// qWarning("Created surface %dx%d\n", w, h);
+#ifndef QT_NO_OPENGL
QEGLPlatformContext *platformContext = new QMinimalEglContext(platformFormat, 0, m_dpy);
m_platformContext = platformContext;
-
+#endif
EGLint w,h; // screen size detection
eglQuerySurface(m_dpy, m_surface, EGL_WIDTH, &w);
eglQuerySurface(m_dpy, m_surface, EGL_HEIGHT, &h);
@@ -191,6 +198,7 @@ QImage::Format QMinimalEglScreen::format() const
createAndSetPlatformContext();
return m_format;
}
+#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *QMinimalEglScreen::platformContext() const
{
if (!m_platformContext) {
@@ -199,5 +207,5 @@ QPlatformOpenGLContext *QMinimalEglScreen::platformContext() const
}
return m_platformContext;
}
-
+#endif
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/minimalegl/qminimaleglscreen.h b/src/plugins/platforms/minimalegl/qminimaleglscreen.h
index ba605835a8..24098b8127 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglscreen.h
+++ b/src/plugins/platforms/minimalegl/qminimaleglscreen.h
@@ -59,9 +59,9 @@ public:
QRect geometry() const Q_DECL_OVERRIDE;
int depth() const Q_DECL_OVERRIDE;
QImage::Format format() const Q_DECL_OVERRIDE;
-
+#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *platformContext() const;
-
+#endif
EGLSurface surface() const { return m_surface; }
private:
diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro
index 9da3d6811b..0b052adf0f 100644
--- a/src/plugins/platforms/qnx/qnx.pro
+++ b/src/plugins/platforms/qnx/qnx.pro
@@ -7,8 +7,6 @@ QT += \
# Uncomment this to build with support for IMF once it becomes available in the BBNDK
#CONFIG += qqnx_imf
-CONFIG += qqnx_screeneventthread
-
# Uncomment these to enable debugging output for various aspects of the plugin
#DEFINES += QQNXBUFFER_DEBUG
#DEFINES += QQNXBUTTON_DEBUG
@@ -47,7 +45,8 @@ SOURCES = main.cpp \
qqnxservices.cpp \
qqnxcursor.cpp \
qqnxrasterwindow.cpp \
- qqnxglobal.cpp
+ qqnxglobal.cpp \
+ qqnxscreeneventthread.cpp
HEADERS = main.h \
qqnxbuffer.h \
@@ -67,13 +66,8 @@ HEADERS = main.h \
qqnxrasterwindow.h \
qqnxscreeneventfilter.h \
qqnxglobal.h \
- qqnxlgmon.h
-
-CONFIG(qqnx_screeneventthread) {
- DEFINES += QQNX_SCREENEVENTTHREAD
- SOURCES += qqnxscreeneventthread.cpp
- HEADERS += qqnxscreeneventthread.h
-}
+ qqnxlgmon.h \
+ qqnxscreeneventthread.h
LIBS += -lscreen
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
index 7229d7d2a8..eee0581709 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
@@ -40,9 +40,7 @@
#include "qqnxglobal.h"
#include "qqnxintegration.h"
-#if defined(QQNX_SCREENEVENTTHREAD)
#include "qqnxscreeneventthread.h"
-#endif
#include "qqnxnativeinterface.h"
#include "qqnxrasterbackingstore.h"
#include "qqnxscreen.h"
@@ -125,9 +123,7 @@ static inline QQnxIntegration::Options parseOptions(const QStringList &paramList
QQnxIntegration::QQnxIntegration(const QStringList &paramList)
: QPlatformIntegration()
-#if defined(QQNX_SCREENEVENTTHREAD)
, m_screenEventThread(0)
-#endif
, m_navigatorEventHandler(new QQnxNavigatorEventHandler())
, m_virtualKeyboard(0)
#if defined(QQNX_PPS)
@@ -169,10 +165,8 @@ QQnxIntegration::QQnxIntegration(const QStringList &paramList)
#endif
// Create/start event thread
-#if defined(QQNX_SCREENEVENTTHREAD)
m_screenEventThread = new QQnxScreenEventThread(ms_screenContext, m_screenEventHandler);
m_screenEventThread->start();
-#endif
#if defined(QQNX_PPS)
// Create/start the keyboard class.
@@ -235,10 +229,8 @@ QQnxIntegration::~QQnxIntegration()
#endif
delete m_navigatorEventHandler;
-#if defined(QQNX_SCREENEVENTTHREAD)
// Stop/destroy screen event thread
delete m_screenEventThread;
-#endif
// In case the event-dispatcher was never transferred to QCoreApplication
delete m_eventDispatcher;
diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h
index 6f2af82100..b2008baa0c 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.h
+++ b/src/plugins/platforms/qnx/qqnxintegration.h
@@ -48,9 +48,7 @@
QT_BEGIN_NAMESPACE
-#if defined(QQNX_SCREENEVENTTHREAD)
class QQnxScreenEventThread;
-#endif
class QQnxFileDialogHelper;
class QQnxNativeInterface;
class QQnxWindow;
@@ -142,9 +140,7 @@ private:
static void removeWindow(screen_window_t qnxWindow);
static screen_context_t ms_screenContext;
-#if defined(QQNX_SCREENEVENTTHREAD)
QQnxScreenEventThread *m_screenEventThread;
-#endif
QQnxNavigatorEventHandler *m_navigatorEventHandler;
QQnxAbstractVirtualKeyboard *m_virtualKeyboard;
#if defined(QQNX_PPS)
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
index beda6e1a49..5d230e2145 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
@@ -40,9 +40,7 @@
#include "qqnxglobal.h"
#include "qqnxscreeneventhandler.h"
-#if defined(QQNX_SCREENEVENTTHREAD)
#include "qqnxscreeneventthread.h"
-#endif
#include "qqnxintegration.h"
#include "qqnxkeytranslator.h"
#include "qqnxscreen.h"
@@ -67,9 +65,7 @@ QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration)
, m_lastButtonState(Qt::NoButton)
, m_lastMouseWindow(0)
, m_touchDevice(0)
-#if defined(QQNX_SCREENEVENTTHREAD)
, m_eventThread(0)
-#endif
, m_focusLostTimer(-1)
{
// Create a touch device
@@ -198,7 +194,6 @@ void QQnxScreenEventHandler::injectKeyboardEvent(int flags, int sym, int modifie
}
}
-#if defined(QQNX_SCREENEVENTTHREAD)
void QQnxScreenEventHandler::setScreenEventThread(QQnxScreenEventThread *eventThread)
{
m_eventThread = eventThread;
@@ -233,7 +228,6 @@ void QQnxScreenEventHandler::processEventsFromScreenThread()
m_eventThread->unlock();
}
-#endif
void QQnxScreenEventHandler::handleKeyboardEvent(screen_event_t event)
{
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h
index 80798a8a2d..d872f9b9aa 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h
@@ -48,9 +48,7 @@ QT_BEGIN_NAMESPACE
class QQnxIntegration;
class QQnxScreenEventFilter;
-#if defined(QQNX_SCREENEVENTTHREAD)
class QQnxScreenEventThread;
-#endif
class QQnxScreenEventHandler : public QObject
{
@@ -66,9 +64,7 @@ public:
static void injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap);
-#if defined(QQNX_SCREENEVENTTHREAD)
void setScreenEventThread(QQnxScreenEventThread *eventThread);
-#endif
Q_SIGNALS:
void newWindowCreated(void *window);
@@ -77,10 +73,8 @@ Q_SIGNALS:
protected:
void timerEvent(QTimerEvent *event) override;
-#if defined(QQNX_SCREENEVENTTHREAD)
private Q_SLOTS:
void processEventsFromScreenThread();
-#endif
private:
void handleKeyboardEvent(screen_event_t event);
@@ -105,9 +99,7 @@ private:
QTouchDevice *m_touchDevice;
QWindowSystemInterface::TouchPoint m_touchPoints[MaximumTouchPoints];
QList<QQnxScreenEventFilter*> m_eventFilters;
-#if defined(QQNX_SCREENEVENTTHREAD)
QQnxScreenEventThread *m_eventThread;
-#endif
int m_focusLostTimer;
};
diff --git a/src/plugins/platforms/vnc/qvncscreen.cpp b/src/plugins/platforms/vnc/qvncscreen.cpp
index 34def45767..91a8933dba 100644
--- a/src/plugins/platforms/vnc/qvncscreen.cpp
+++ b/src/plugins/platforms/vnc/qvncscreen.cpp
@@ -150,10 +150,10 @@ QPixmap QVncScreen::grabWindow(WId wid, int x, int y, int width, int height) con
{
if (!wid) {
if (width < 0)
- width = mScreenImage->width() - x;
+ width = mScreenImage.width() - x;
if (height < 0)
- height = mScreenImage->height() - y;
- return QPixmap::fromImage(*mScreenImage).copy(x, y, width, height);
+ height = mScreenImage.height() - y;
+ return QPixmap::fromImage(mScreenImage).copy(x, y, width, height);
}
QFbWindow *window = windowForId(wid);
@@ -165,7 +165,7 @@ QPixmap QVncScreen::grabWindow(WId wid, int x, int y, int width, int height) con
height = geom.height() - y;
QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));
rect &= window->geometry();
- return QPixmap::fromImage(*mScreenImage).copy(rect);
+ return QPixmap::fromImage(mScreenImage).copy(rect);
}
return QPixmap();
@@ -183,5 +183,10 @@ bool QVNCScreen::swapBytes() const
}
#endif
+QFbScreen::Flags QVncScreen::flags() const
+{
+ return QFbScreen::DontForceFirstWindowToFullScreen;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/vnc/qvncscreen.h b/src/plugins/platforms/vnc/qvncscreen.h
index 785abd6dc2..4b7171b5a9 100644
--- a/src/plugins/platforms/vnc/qvncscreen.h
+++ b/src/plugins/platforms/vnc/qvncscreen.h
@@ -64,12 +64,14 @@ public:
QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
QRegion doRedraw() Q_DECL_OVERRIDE;
- QImage *image() const { return mScreenImage; }
+ QImage *image() { return &mScreenImage; }
void enableClientCursor(QVncClient *client);
void disableClientCursor(QVncClient *client);
QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
+ Flags flags() const Q_DECL_OVERRIDE;
+
void clearDirty() { dirtyRegion = QRegion(); }
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
index e035e3924a..8621e93120 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
+++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
@@ -53,7 +53,7 @@ class QWindowsAccessibility : public QPlatformAccessibility
public:
QWindowsAccessibility();
static bool handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult);
- void notifyAccessibilityUpdate(QAccessibleEvent *event) Q_DECL_OVERRIDE;
+ void notifyAccessibilityUpdate(QAccessibleEvent *event) override;
static IAccessible *wrap(QAccessibleInterface *acc);
static QWindow *windowHelper(const QAccessibleInterface *iface);
};
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
index 85aab84c2c..25b1577772 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
@@ -1052,11 +1052,24 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BS
return S_FALSE;
}
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accValue(VARIANT, BSTR)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accValue(VARIANT, BSTR value)
{
QAccessibleInterface *accessible = accessibleInterface();
accessibleDebugClientCalls(accessible);
- return DISP_E_MEMBERNOTFOUND;
+
+ if (!accessible || !accessible->isValid()) {
+ return E_FAIL;
+ }
+
+ QString qstrValue = QString::fromWCharArray(value);
+
+ if (accessible->valueInterface()) {
+ accessible->valueInterface()->setCurrentValue(qstrValue);
+ } else {
+ accessible->setText(QAccessible::Value, qstrValue);
+ }
+
+ return S_OK;
}
// moz: [important]
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index ec6a8f62ae..27632de688 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -102,6 +102,7 @@ enum WindowsEventType // Simplify event types
TouchEvent = TouchEventFlag + 1,
NonClientMouseEvent = NonClientEventFlag + MouseEventFlag + 1,
NonClientHitTest = NonClientEventFlag + 2,
+ NonClientCreate = NonClientEventFlag + 3,
KeyEvent = KeyEventFlag + 1,
KeyDownEvent = KeyEventFlag + KeyDownEventFlag + 1,
KeyboardLayoutChangeEvent = KeyEventFlag + 2,
@@ -177,6 +178,8 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
return QtWindows::HideEvent;
case WM_SIZE:
return QtWindows::ResizeEvent;
+ case WM_NCCREATE:
+ return QtWindows::NonClientCreate;
case WM_NCCALCSIZE:
return QtWindows::CalculateSize;
case WM_NCHITTEST:
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h
index 46a7fcc676..9e62266697 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.h
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.h
@@ -57,15 +57,15 @@ public:
QWindowsBackingStore(QWindow *window);
~QWindowsBackingStore();
- QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
- void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
- void resize(const QSize &size, const QRegion &r) Q_DECL_OVERRIDE;
- bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE;
- void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
+ QPaintDevice *paintDevice() override;
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
+ void resize(const QSize &size, const QRegion &r) override;
+ bool scroll(const QRegion &area, int dx, int dy) override;
+ void beginPaint(const QRegion &) override;
HDC getDC() const;
- QImage toImage() const Q_DECL_OVERRIDE;
+ QImage toImage() const override;
private:
QScopedPointer<QWindowsNativeImage> m_image;
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp
index d4a7e27762..11cd1756e6 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.cpp
+++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp
@@ -149,8 +149,7 @@ static void cleanClipboardPostRoutine()
QWindowsClipboard *QWindowsClipboard::m_instance = 0;
-QWindowsClipboard::QWindowsClipboard() :
- m_data(0), m_clipboardViewer(0), m_nextClipboardViewer(0), m_formatListenerRegistered(false)
+QWindowsClipboard::QWindowsClipboard()
{
QWindowsClipboard::m_instance = this;
qAddPostRoutine(cleanClipboardPostRoutine);
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.h b/src/plugins/platforms/windows/qwindowsclipboard.h
index 992d34d492..4f3e7437f6 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.h
+++ b/src/plugins/platforms/windows/qwindowsclipboard.h
@@ -52,8 +52,8 @@ class QWindowsClipboardRetrievalMimeData : public QWindowsInternalMimeData {
public:
protected:
- IDataObject *retrieveDataObject() const Q_DECL_OVERRIDE;
- void releaseDataObject(IDataObject *) const Q_DECL_OVERRIDE;
+ IDataObject *retrieveDataObject() const override;
+ void releaseDataObject(IDataObject *) const override;
};
class QWindowsClipboard : public QPlatformClipboard
@@ -64,10 +64,10 @@ public:
void registerViewer(); // Call in initialization, when context is up.
void cleanup();
- QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
- void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
- bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
- bool ownsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
+ QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;
+ void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) override;
+ bool supportsMode(QClipboard::Mode mode) const override;
+ bool ownsMode(QClipboard::Mode mode) const override;
inline bool clipboardViewerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result);
@@ -85,10 +85,10 @@ private:
static QWindowsClipboard *m_instance;
QWindowsClipboardRetrievalMimeData m_retrievalData;
- QWindowsOleDataObject *m_data;
- HWND m_clipboardViewer;
- HWND m_nextClipboardViewer;
- bool m_formatListenerRegistered;
+ QWindowsOleDataObject *m_data = nullptr;
+ HWND m_clipboardViewer = 0;
+ HWND m_nextClipboardViewer = 0;
+ bool m_formatListenerRegistered = false;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 1a03df6ac2..4248d5685e 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -68,6 +68,7 @@
#include <QtCore/QHash>
#include <QtCore/QStringList>
#include <QtCore/QDebug>
+#include <QtCore/QOperatingSystemVersion>
#include <QtCore/QSysInfo>
#include <QtCore/QScopedArrayPointer>
#include <QtCore/private/qsystemlibrary_p.h>
@@ -127,6 +128,28 @@ static inline QWindowsSessionManager *platformSessionManager() {
}
#endif
+static inline int windowDpiAwareness(HWND hwnd)
+{
+ return QWindowsContext::user32dll.getWindowDpiAwarenessContext && QWindowsContext::user32dll.getWindowDpiAwarenessContext
+ ? QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext(QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd))
+ : -1;
+}
+
+// Note: This only works within WM_NCCREATE
+static bool enableNonClientDpiScaling(HWND hwnd)
+{
+ bool result = false;
+ if (QWindowsContext::user32dll.enableNonClientDpiScaling && windowDpiAwareness(hwnd) == 2) {
+ result = QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE;
+ if (!result) {
+ const DWORD errorCode = GetLastError();
+ qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
+ hwnd, errorCode);
+ }
+ }
+ return result;
+}
+
/*!
\class QWindowsUser32DLL
\brief Struct that contains dynamically resolved symbols of User32.dll.
@@ -142,14 +165,6 @@ static inline QWindowsSessionManager *platformSessionManager() {
\internal
\ingroup qt-lighthouse-win
*/
-QWindowsUser32DLL::QWindowsUser32DLL() :
- isTouchWindow(0),
- registerTouchWindow(0), unregisterTouchWindow(0),
- getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0),
- addClipboardFormatListener(0), removeClipboardFormatListener(0),
- getDisplayAutoRotationPreferences(0), setDisplayAutoRotationPreferences(0)
-{
-}
void QWindowsUser32DLL::init()
{
@@ -161,6 +176,12 @@ void QWindowsUser32DLL::init()
getDisplayAutoRotationPreferences = (GetDisplayAutoRotationPreferences)library.resolve("GetDisplayAutoRotationPreferences");
setDisplayAutoRotationPreferences = (SetDisplayAutoRotationPreferences)library.resolve("SetDisplayAutoRotationPreferences");
+
+ if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS10) { // Appears in 10.0.14393, October 2016
+ enableNonClientDpiScaling = (EnableNonClientDpiScaling)library.resolve("EnableNonClientDpiScaling");
+ getWindowDpiAwarenessContext = (GetWindowDpiAwarenessContext)library.resolve("GetWindowDpiAwarenessContext");
+ getAwarenessFromDpiAwarenessContext = (GetAwarenessFromDpiAwarenessContext)library.resolve("GetAwarenessFromDpiAwarenessContext");
+ }
}
bool QWindowsUser32DLL::initTouch()
@@ -176,16 +197,9 @@ bool QWindowsUser32DLL::initTouch()
return isTouchWindow && registerTouchWindow && unregisterTouchWindow && getTouchInputInfo && closeTouchInputHandle;
}
-QWindowsShcoreDLL::QWindowsShcoreDLL()
- : getProcessDpiAwareness(0)
- , setProcessDpiAwareness(0)
- , getDpiForMonitor(0)
-{
-}
-
void QWindowsShcoreDLL::init()
{
- if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS8_1)
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1)
return;
QSystemLibrary library(QStringLiteral("SHCore"));
getProcessDpiAwareness = (GetProcessDpiAwareness)library.resolve("GetProcessDpiAwareness");
@@ -211,14 +225,13 @@ QWindowsContext *QWindowsContext::m_instance = 0;
typedef QHash<HWND, QWindowsWindow *> HandleBaseWindowHash;
struct QWindowsContextPrivate {
-
QWindowsContextPrivate();
- unsigned m_systemInfo;
+ unsigned m_systemInfo = 0;
QSet<QString> m_registeredWindowClassNames;
HandleBaseWindowHash m_windows;
- HDC m_displayContext;
- int m_defaultDPI;
+ HDC m_displayContext = 0;
+ int m_defaultDPI = 96;
QWindowsKeyMapper m_keyMapper;
QWindowsMouseHandler m_mouseHandler;
QWindowsMimeConverter m_mimeConverter;
@@ -229,15 +242,13 @@ struct QWindowsContextPrivate {
#endif
const HRESULT m_oleInitializeResult;
const QByteArray m_eventType;
- QWindow *m_lastActiveWindow;
- bool m_asyncExpose;
+ QWindow *m_lastActiveWindow = nullptr;
+ bool m_asyncExpose = false;
};
QWindowsContextPrivate::QWindowsContextPrivate()
- : m_systemInfo(0)
- , m_oleInitializeResult(OleInitialize(NULL))
+ : m_oleInitializeResult(OleInitialize(NULL))
, m_eventType(QByteArrayLiteral("windows_generic_MSG"))
- , m_lastActiveWindow(0), m_asyncExpose(0)
{
QWindowsContext::user32dll.init();
QWindowsContext::shcoredll.init();
@@ -379,6 +390,11 @@ void QWindowsContext::setWindowCreationContext(const QSharedPointer<QWindowCreat
d->m_creationContext = ctx;
}
+QSharedPointer<QWindowCreationContext> QWindowsContext::windowCreationContext() const
+{
+ return d->m_creationContext;
+}
+
int QWindowsContext::defaultDPI() const
{
return d->m_defaultDPI;
@@ -807,7 +823,9 @@ static inline QWindowsInputContext *windowsInputContext()
bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
QtWindows::WindowsEventType et,
- WPARAM wParam, LPARAM lParam, LRESULT *result)
+ WPARAM wParam, LPARAM lParam,
+ LRESULT *result,
+ QWindowsWindow **platformWindowPtr)
{
*result = 0;
@@ -838,6 +856,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
}
QWindowsWindow *platformWindow = findPlatformWindow(hwnd);
+ *platformWindowPtr = platformWindow;
if (platformWindow) {
filterResult = 0;
if (QWindowSystemInterface::handleNativeEvent(platformWindow->window(), d->m_eventType, &msg, &filterResult)) {
@@ -919,6 +938,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::MoveEvent:
d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return true;
+ case QtWindows::NonClientCreate:
+ if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS10 && d->m_creationContext->window->isTopLevel())
+ enableNonClientDpiScaling(msg.hwnd);
+ return false;
case QtWindows::CalculateSize:
return QWindowsGeometryHint::handleCalculateSize(d->m_creationContext->customMargins, msg, result);
case QtWindows::GeometryChangingEvent:
@@ -1019,9 +1042,6 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return true;
case QtWindows::ThemeChanged: {
// Switch from Aero to Classic changes margins.
- const Qt::WindowFlags flags = platformWindow->window()->flags();
- if ((flags & Qt::WindowType_Mask) != Qt::Desktop && !(flags & Qt::FramelessWindowHint))
- platformWindow->setFlag(QWindowsWindow::FrameDirty);
if (QWindowsTheme *theme = QWindowsTheme::instance())
theme->windowsThemeChanged(platformWindow->window());
return true;
@@ -1194,6 +1214,37 @@ QTouchDevice *QWindowsContext::touchDevice() const
return d->m_mouseHandler.touchDevice();
}
+static inline bool isEmptyRect(const RECT &rect)
+{
+ return rect.right - rect.left == 0 && rect.bottom - rect.top == 0;
+}
+
+static inline QMargins marginsFromRects(const RECT &frame, const RECT &client)
+{
+ return QMargins(client.left - frame.left, client.top - frame.top,
+ frame.right - client.right, frame.bottom - client.bottom);
+}
+
+static RECT rectFromNcCalcSize(UINT message, WPARAM wParam, LPARAM lParam, int n)
+{
+ RECT result = {0, 0, 0, 0};
+ if (message == WM_NCCALCSIZE && wParam)
+ result = reinterpret_cast<const NCCALCSIZE_PARAMS *>(lParam)->rgrc[n];
+ return result;
+}
+
+static inline bool isMinimized(HWND hwnd)
+{
+ WINDOWPLACEMENT windowPlacement;
+ windowPlacement.length = sizeof(WINDOWPLACEMENT);
+ return GetWindowPlacement(hwnd, &windowPlacement) && windowPlacement.showCmd == SW_SHOWMINIMIZED;
+}
+
+static inline bool isTopLevel(HWND hwnd)
+{
+ return (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CHILD) == 0;
+}
+
/*!
\brief Windows functions for actual windows.
@@ -1207,7 +1258,9 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR
{
LRESULT result;
const QtWindows::WindowsEventType et = windowsEventType(message, wParam, lParam);
- const bool handled = QWindowsContext::instance()->windowsProc(hwnd, message, et, wParam, lParam, &result);
+ QWindowsWindow *platformWindow = nullptr;
+ const RECT ncCalcSizeFrame = rectFromNcCalcSize(message, wParam, lParam, 0);
+ const bool handled = QWindowsContext::instance()->windowsProc(hwnd, message, et, wParam, lParam, &result, &platformWindow);
if (QWindowsContext::verbose > 1 && lcQpaEvents().isDebugEnabled()) {
if (const char *eventName = QWindowsGuiEventDispatcher::windowsMessageName(message)) {
qCDebug(lcQpaEvents) << "EVENT: hwd=" << hwnd << eventName << hex << "msg=0x" << message
@@ -1217,6 +1270,24 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR
}
if (!handled)
result = DefWindowProc(hwnd, message, wParam, lParam);
+
+ // Capture WM_NCCALCSIZE on top level windows and obtain the window margins by
+ // subtracting the rectangles before and after processing. This will correctly
+ // capture client code overriding the message and allow for per-monitor margins
+ // for High DPI (QTBUG-53255, QTBUG-40578).
+ if (message == WM_NCCALCSIZE && !isEmptyRect(ncCalcSizeFrame) && isTopLevel(hwnd) && !isMinimized(hwnd)) {
+ const QMargins margins =
+ marginsFromRects(ncCalcSizeFrame, rectFromNcCalcSize(message, wParam, lParam, 0));
+ if (margins.left() >= 0) {
+ if (platformWindow) {
+ platformWindow->setFrameMargins(margins);
+ } else {
+ const QSharedPointer<QWindowCreationContext> ctx = QWindowsContext::instance()->windowCreationContext();
+ if (!ctx.isNull())
+ ctx->margins = margins;
+ }
+ }
+ }
return result;
}
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index 9dfde67797..b50010321b 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -80,7 +80,6 @@ class QTouchDevice;
struct QWindowsUser32DLL
{
- QWindowsUser32DLL();
inline void init();
inline bool initTouch();
@@ -94,30 +93,36 @@ struct QWindowsUser32DLL
typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
typedef BOOL (WINAPI *GetDisplayAutoRotationPreferences)(DWORD *);
typedef BOOL (WINAPI *SetDisplayAutoRotationPreferences)(DWORD);
+ typedef BOOL (WINAPI *EnableNonClientDpiScaling)(HWND);
+ typedef int (WINAPI *GetWindowDpiAwarenessContext)(HWND);
+ typedef int (WINAPI *GetAwarenessFromDpiAwarenessContext)(int);
// Touch functions from Windows 7 onwards (also for use with Q_CC_MSVC).
- IsTouchWindow isTouchWindow;
- RegisterTouchWindow registerTouchWindow;
- UnregisterTouchWindow unregisterTouchWindow;
- GetTouchInputInfo getTouchInputInfo;
- CloseTouchInputHandle closeTouchInputHandle;
+ IsTouchWindow isTouchWindow = nullptr;
+ RegisterTouchWindow registerTouchWindow = nullptr;
+ UnregisterTouchWindow unregisterTouchWindow = nullptr;
+ GetTouchInputInfo getTouchInputInfo = nullptr;
+ CloseTouchInputHandle closeTouchInputHandle = nullptr;
// Windows Vista onwards
- SetProcessDPIAware setProcessDPIAware;
+ SetProcessDPIAware setProcessDPIAware = nullptr;
// Clipboard listeners are present on Windows Vista onwards
// but missing in MinGW 4.9 stub libs. Can be removed in MinGW 5.
- AddClipboardFormatListener addClipboardFormatListener;
- RemoveClipboardFormatListener removeClipboardFormatListener;
+ AddClipboardFormatListener addClipboardFormatListener = nullptr;
+ RemoveClipboardFormatListener removeClipboardFormatListener = nullptr;
// Rotation API
- GetDisplayAutoRotationPreferences getDisplayAutoRotationPreferences;
- SetDisplayAutoRotationPreferences setDisplayAutoRotationPreferences;
+ GetDisplayAutoRotationPreferences getDisplayAutoRotationPreferences = nullptr;
+ SetDisplayAutoRotationPreferences setDisplayAutoRotationPreferences = nullptr;
+
+ EnableNonClientDpiScaling enableNonClientDpiScaling = nullptr;
+ GetWindowDpiAwarenessContext getWindowDpiAwarenessContext = nullptr;
+ GetAwarenessFromDpiAwarenessContext getAwarenessFromDpiAwarenessContext = nullptr;
};
// Shell scaling library (Windows 8.1 onwards)
struct QWindowsShcoreDLL {
- QWindowsShcoreDLL();
void init();
inline bool isValid() const { return getProcessDpiAwareness && setProcessDpiAwareness && getDpiForMonitor; }
@@ -125,9 +130,9 @@ struct QWindowsShcoreDLL {
typedef HRESULT (WINAPI *SetProcessDpiAwareness)(int);
typedef HRESULT (WINAPI *GetDpiForMonitor)(HMONITOR,int,UINT *,UINT *);
- GetProcessDpiAwareness getProcessDpiAwareness;
- SetProcessDpiAwareness setProcessDpiAwareness;
- GetDpiForMonitor getDpiForMonitor;
+ GetProcessDpiAwareness getProcessDpiAwareness = nullptr;
+ SetProcessDpiAwareness setProcessDpiAwareness = nullptr;
+ GetDpiForMonitor getDpiForMonitor = nullptr;
};
class QWindowsContext
@@ -181,12 +186,14 @@ public:
inline bool windowsProc(HWND hwnd, UINT message,
QtWindows::WindowsEventType et,
- WPARAM wParam, LPARAM lParam, LRESULT *result);
+ WPARAM wParam, LPARAM lParam, LRESULT *result,
+ QWindowsWindow **platformWindowPtr);
QWindow *keyGrabber() const;
void setKeyGrabber(QWindow *hwnd);
void setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx);
+ QSharedPointer<QWindowCreationContext> windowCreationContext() const;
void setTabletAbsoluteRange(int a);
void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness);
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index 6fff5f9ab1..df2e22733b 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -104,9 +104,9 @@ public:
explicit QWindowsCursor(const QPlatformScreen *screen);
- void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE;
- QPoint pos() const Q_DECL_OVERRIDE;
- void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
+ void changeCursor(QCursor * widgetCursor, QWindow * widget) override;
+ QPoint pos() const override;
+ void setPos(const QPoint &pos) override;
static HCURSOR createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor = 1);
static HCURSOR createPixmapCursor(const PixmapCursor &pc, qreal scaleFactor = 1) { return createPixmapCursor(pc.pixmap, pc.hotSpot, scaleFactor); }
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 8f1358de6c..94257bd4ac 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -212,15 +212,6 @@ private:
*/
template <class BaseClass>
-QWindowsDialogHelperBase<BaseClass>::QWindowsDialogHelperBase() :
- m_nativeDialog(0),
- m_ownerWindow(0),
- m_timerId(0),
- m_thread(0)
-{
-}
-
-template <class BaseClass>
void QWindowsDialogHelperBase<BaseClass>::cleanupThread()
{
if (m_thread) { // Thread may be running if the dialog failed to close.
@@ -549,11 +540,11 @@ public:
IFACEMETHODIMP OnOverwrite(IFileDialog *, IShellItem *, FDE_OVERWRITE_RESPONSE *) { return S_OK; }
QWindowsNativeFileDialogEventHandler(QWindowsNativeFileDialogBase *nativeFileDialog) :
- m_ref(1), m_nativeFileDialog(nativeFileDialog) {}
+ m_nativeFileDialog(nativeFileDialog) {}
virtual ~QWindowsNativeFileDialogEventHandler() {}
private:
- long m_ref;
+ long m_ref = 1;
QWindowsNativeFileDialogBase *m_nativeFileDialog;
};
@@ -590,12 +581,12 @@ public:
inline static QWindowsNativeFileDialogBase *create(QFileDialogOptions::AcceptMode am, const QWindowsFileDialogSharedData &data);
- void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
+ void setWindowTitle(const QString &title) override;
inline void setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::AcceptMode acceptMode, QFileDialogOptions::FileDialogOptions options);
inline void setDirectory(const QUrl &directory);
inline void updateDirectory() { setDirectory(m_data.directory()); }
inline QString directory() const;
- void doExec(HWND owner = 0) Q_DECL_OVERRIDE;
+ void doExec(HWND owner = 0) override;
virtual void setNameFilters(const QStringList &f);
inline void selectNameFilter(const QString &filter);
inline void updateSelectedNameFilter() { selectNameFilter(m_data.selectedNameFilter()); }
@@ -624,7 +615,7 @@ signals:
void filterSelected(const QString & filter);
public slots:
- void close() Q_DECL_OVERRIDE;
+ void close() override;
protected:
explicit QWindowsNativeFileDialogBase(const QWindowsFileDialogSharedData &data);
@@ -641,19 +632,18 @@ protected:
QWindowsFileDialogSharedData &data() { return m_data; }
private:
- IFileDialog *m_fileDialog;
- IFileDialogEvents *m_dialogEvents;
- DWORD m_cookie;
+ IFileDialog *m_fileDialog = nullptr;
+ IFileDialogEvents *m_dialogEvents = nullptr;
+ DWORD m_cookie = 0;
QStringList m_nameFilters;
- bool m_hideFiltersDetails;
- bool m_hasDefaultSuffix;
+ bool m_hideFiltersDetails = false;
+ bool m_hasDefaultSuffix = false;
QWindowsFileDialogSharedData m_data;
QString m_title;
};
QWindowsNativeFileDialogBase::QWindowsNativeFileDialogBase(const QWindowsFileDialogSharedData &data) :
- m_fileDialog(0), m_dialogEvents(0), m_cookie(0), m_hideFiltersDetails(false),
- m_hasDefaultSuffix(false), m_data(data)
+ m_data(data)
{
}
@@ -1165,9 +1155,9 @@ class QWindowsNativeSaveFileDialog : public QWindowsNativeFileDialogBase
public:
explicit QWindowsNativeSaveFileDialog(const QWindowsFileDialogSharedData &data)
: QWindowsNativeFileDialogBase(data) {}
- void setNameFilters(const QStringList &f) Q_DECL_OVERRIDE;
- QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
- QList<QUrl> dialogResult() const Q_DECL_OVERRIDE;
+ void setNameFilters(const QStringList &f) override;
+ QList<QUrl> selectedFiles() const override;
+ QList<QUrl> dialogResult() const override;
};
// Return the first suffix from the name filter "Foo files (*.foo;*.bar)" -> "foo".
@@ -1241,8 +1231,8 @@ class QWindowsNativeOpenFileDialog : public QWindowsNativeFileDialogBase
public:
explicit QWindowsNativeOpenFileDialog(const QWindowsFileDialogSharedData &data) :
QWindowsNativeFileDialogBase(data) {}
- QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
- QList<QUrl> dialogResult() const Q_DECL_OVERRIDE;
+ QList<QUrl> selectedFiles() const override;
+ QList<QUrl> dialogResult() const override;
private:
inline IFileOpenDialog *openFileDialog() const
@@ -1309,19 +1299,19 @@ class QWindowsFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDi
{
public:
QWindowsFileDialogHelper() {}
- virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const Q_DECL_OVERRIDE { return false; }
- virtual bool defaultNameFilterDisables() const Q_DECL_OVERRIDE
+ bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const override { return false; }
+ bool defaultNameFilterDisables() const override
{ return false; }
- virtual void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
- virtual QUrl directory() const Q_DECL_OVERRIDE;
- virtual void selectFile(const QUrl &filename) Q_DECL_OVERRIDE;
- virtual QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
- virtual void setFilter() Q_DECL_OVERRIDE;
- virtual void selectNameFilter(const QString &filter) Q_DECL_OVERRIDE;
- virtual QString selectedNameFilter() const Q_DECL_OVERRIDE;
+ void setDirectory(const QUrl &directory) override;
+ QUrl directory() const override;
+ void selectFile(const QUrl &filename) override;
+ QList<QUrl> selectedFiles() const override;
+ void setFilter() override;
+ void selectNameFilter(const QString &filter) override;
+ QString selectedNameFilter() const override;
private:
- QWindowsNativeDialogBase *createNativeDialog() Q_DECL_OVERRIDE;
+ QWindowsNativeDialogBase *createNativeDialog() override;
inline QWindowsNativeFileDialogBase *nativeFileDialog() const
{ return static_cast<QWindowsNativeFileDialogBase *>(nativeDialog()); }
@@ -1447,13 +1437,13 @@ public:
static QWindowsXpNativeFileDialog *create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data);
- void setWindowTitle(const QString &t) Q_DECL_OVERRIDE { m_title = t; }
- void doExec(HWND owner = 0) Q_DECL_OVERRIDE;
+ void setWindowTitle(const QString &t) override { m_title = t; }
+ void doExec(HWND owner = 0) override;
int existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam);
public slots:
- void close() Q_DECL_OVERRIDE {}
+ void close() override {}
private:
typedef BOOL (APIENTRY *PtrGetOpenFileNameW)(LPOPENFILENAMEW);
@@ -1689,19 +1679,19 @@ class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFile
{
public:
QWindowsXpFileDialogHelper() {}
- bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const Q_DECL_OVERRIDE { return false; }
- bool defaultNameFilterDisables() const Q_DECL_OVERRIDE
+ bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const override { return false; }
+ bool defaultNameFilterDisables() const override
{ return true; }
- void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE;
- QUrl directory() const Q_DECL_OVERRIDE;
- void selectFile(const QUrl &url) Q_DECL_OVERRIDE;
- QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE;
- void setFilter() Q_DECL_OVERRIDE {}
- void selectNameFilter(const QString &) Q_DECL_OVERRIDE;
- QString selectedNameFilter() const Q_DECL_OVERRIDE;
+ void setDirectory(const QUrl &directory) override;
+ QUrl directory() const override;
+ void selectFile(const QUrl &url) override;
+ QList<QUrl> selectedFiles() const override;
+ void setFilter() override {}
+ void selectNameFilter(const QString &) override;
+ QString selectedNameFilter() const override;
private:
- QWindowsNativeDialogBase *createNativeDialog() Q_DECL_OVERRIDE;
+ QWindowsNativeDialogBase *createNativeDialog() override;
inline QWindowsXpNativeFileDialog *nativeFileDialog() const
{ return static_cast<QWindowsXpNativeFileDialog *>(nativeDialog()); }
@@ -1773,13 +1763,13 @@ public:
explicit QWindowsNativeColorDialog(const SharedPointerColor &color);
- void setWindowTitle(const QString &) Q_DECL_OVERRIDE {}
+ void setWindowTitle(const QString &) override {}
public slots:
- void close() Q_DECL_OVERRIDE {}
+ void close() override {}
private:
- void doExec(HWND owner = 0) Q_DECL_OVERRIDE;
+ void doExec(HWND owner = 0) override;
COLORREF m_customColors[CustomColorCount];
QPlatformDialogHelper::DialogCode m_code;
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
index b3101a1419..55f112c57a 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
@@ -69,19 +69,19 @@ public:
typedef QSharedPointer<QWindowsNativeDialogBase> QWindowsNativeDialogBasePtr;
~QWindowsDialogHelperBase() { cleanupThread(); }
- void exec() Q_DECL_OVERRIDE;
+ void exec() override;
bool show(Qt::WindowFlags windowFlags,
- Qt::WindowModality windowModality,
- QWindow *parent) Q_DECL_OVERRIDE;
- void hide() Q_DECL_OVERRIDE;
+ Qt::WindowModality windowModality,
+ QWindow *parent) override;
+ void hide() override;
virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return true; }
protected:
- QWindowsDialogHelperBase();
+ QWindowsDialogHelperBase() {}
QWindowsNativeDialogBase *nativeDialog() const;
inline bool hasNativeDialog() const { return m_nativeDialog; }
- void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE;
+ void timerEvent(QTimerEvent *) override;
private:
virtual QWindowsNativeDialogBase *createNativeDialog() = 0;
@@ -91,9 +91,9 @@ private:
void cleanupThread();
QWindowsNativeDialogBasePtr m_nativeDialog;
- HWND m_ownerWindow;
- int m_timerId;
- QThread *m_thread;
+ HWND m_ownerWindow = 0;
+ int m_timerId = 0;
+ QThread *m_thread = nullptr;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 26a5131927..550415e889 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -84,7 +84,7 @@ public:
void setPixmap(const QPixmap &p);
protected:
- void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE
+ void paintEvent(QPaintEvent *) override
{
QPainter painter(this);
painter.drawPixmap(0, 0, m_pixmap);
@@ -190,6 +190,20 @@ static inline Qt::KeyboardModifiers toQtKeyboardModifiers(DWORD keyState)
return modifiers;
}
+static inline Qt::MouseButtons toQtMouseButtons(DWORD keyState)
+{
+ Qt::MouseButtons buttons = Qt::NoButton;
+
+ if (keyState & MK_LBUTTON)
+ buttons |= Qt::LeftButton;
+ if (keyState & MK_RBUTTON)
+ buttons |= Qt::RightButton;
+ if (keyState & MK_MBUTTON)
+ buttons |= Qt::MidButton;
+
+ return buttons;
+}
+
/*!
\class QWindowsOleDropSource
\brief Implementation of IDropSource
@@ -405,16 +419,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
break;
}
- // grfKeyState is broken on CE & some Windows XP versions,
- // therefore we need to check the state manually
- if ((GetAsyncKeyState(VK_LBUTTON) == 0)
- && (GetAsyncKeyState(VK_MBUTTON) == 0)
- && (GetAsyncKeyState(VK_RBUTTON) == 0)) {
- hr = ResultFromScode(DRAGDROP_S_DROP);
- break;
- }
-
- const Qt::MouseButtons buttons = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState);
+ const Qt::MouseButtons buttons = toQtMouseButtons(grfKeyState);
if (m_currentButtons == Qt::NoButton) {
m_currentButtons = buttons;
} else {
@@ -489,8 +494,7 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
\ingroup qt-lighthouse-win
*/
-QWindowsOleDropTarget::QWindowsOleDropTarget(QWindow *w) :
- m_refs(1), m_window(w), m_chosenEffect(0), m_lastKeyState(0)
+QWindowsOleDropTarget::QWindowsOleDropTarget(QWindow *w) : m_window(w)
{
qCDebug(lcQpaMime) << __FUNCTION__ << this << w;
}
@@ -538,7 +542,7 @@ void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState,
QWindowsDrag *windowsDrag = QWindowsDrag::instance();
const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect);
QGuiApplicationPrivate::modifier_buttons = toQtKeyboardModifiers(grfKeyState);
- QGuiApplicationPrivate::mouse_buttons = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState);
+ QGuiApplicationPrivate::mouse_buttons = toQtMouseButtons(grfKeyState);
const QPlatformDragQtResponse response =
QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(), m_lastPoint, actions);
@@ -682,10 +686,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
bool QWindowsDrag::m_canceled = false;
-QWindowsDrag::QWindowsDrag() :
- m_dropDataObject(0), m_cachedDropTargetHelper(0)
-{
-}
+QWindowsDrag::QWindowsDrag() = default;
QWindowsDrag::~QWindowsDrag()
{
diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h
index e81bc7dc61..983f3a67b4 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.h
+++ b/src/plugins/platforms/windows/qwindowsdrag.h
@@ -54,7 +54,7 @@ class QPlatformScreen;
class QWindowsDropMimeData : public QWindowsInternalMimeData {
public:
QWindowsDropMimeData() {}
- IDataObject *retrieveDataObject() const Q_DECL_OVERRIDE;
+ IDataObject *retrieveDataObject() const override;
};
class QWindowsOleDropTarget : public IDropTarget
@@ -77,12 +77,12 @@ public:
private:
void handleDrag(QWindow *window, DWORD grfKeyState, const QPoint &, LPDWORD pdwEffect);
- ULONG m_refs;
+ ULONG m_refs = 1;
QWindow *const m_window;
QRect m_answerRect;
QPoint m_lastPoint;
- DWORD m_chosenEffect;
- DWORD m_lastKeyState;
+ DWORD m_chosenEffect = 0;
+ DWORD m_lastKeyState = 0;
};
class QWindowsDrag : public QPlatformDrag
@@ -91,12 +91,12 @@ public:
QWindowsDrag();
virtual ~QWindowsDrag();
- QMimeData *platformDropData() Q_DECL_OVERRIDE { return &m_dropData; }
+ QMimeData *platformDropData() override { return &m_dropData; }
- Qt::DropAction drag(QDrag *drag) Q_DECL_OVERRIDE;
+ Qt::DropAction drag(QDrag *drag) override;
static QWindowsDrag *instance();
- void cancelDrag() Q_DECL_OVERRIDE { QWindowsDrag::m_canceled = true; }
+ void cancelDrag() override { QWindowsDrag::m_canceled = true; }
static bool isCanceled() { return QWindowsDrag::m_canceled; }
IDataObject *dropDataObject() const { return m_dropDataObject; }
@@ -110,9 +110,9 @@ private:
static bool m_canceled;
QWindowsDropMimeData m_dropData;
- IDataObject *m_dropDataObject;
+ IDataObject *m_dropDataObject = nullptr;
- IDropTargetHelper* m_cachedDropTargetHelper;
+ IDropTargetHelper* m_cachedDropTargetHelper = nullptr;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index a4738dc100..4632c9c157 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -384,8 +384,6 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
QPlatformOpenGLContext *share)
: m_staticContext(staticContext)
, m_eglDisplay(staticContext->display())
- , m_api(EGL_OPENGL_ES_API)
- , m_swapInterval(-1)
{
if (!m_staticContext)
return;
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index 48a19f81e5..47878a7169 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -117,12 +117,12 @@ public:
EGLDisplay display() const { return m_display; }
- QWindowsOpenGLContext *createContext(QOpenGLContext *context) Q_DECL_OVERRIDE;
- void *moduleHandle() const Q_DECL_OVERRIDE { return libGLESv2.moduleHandle(); }
- QOpenGLContext::OpenGLModuleType moduleType() const Q_DECL_OVERRIDE { return QOpenGLContext::LibGLES; }
+ QWindowsOpenGLContext *createContext(QOpenGLContext *context) override;
+ void *moduleHandle() const override { return libGLESv2.moduleHandle(); }
+ QOpenGLContext::OpenGLModuleType moduleType() const override { return QOpenGLContext::LibGLES; }
- void *createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) Q_DECL_OVERRIDE;
- void destroyWindowSurface(void *nativeSurface) Q_DECL_OVERRIDE;
+ void *createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) override;
+ void destroyWindowSurface(void *nativeSurface) override;
QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config, const QSurfaceFormat &referenceFormat);
@@ -145,18 +145,18 @@ public:
QPlatformOpenGLContext *share);
~QWindowsEGLContext();
- bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- void doneCurrent() Q_DECL_OVERRIDE;
- void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- QFunctionPointer getProcAddress(const char *procName) Q_DECL_OVERRIDE;
+ bool makeCurrent(QPlatformSurface *surface) override;
+ void doneCurrent() override;
+ void swapBuffers(QPlatformSurface *surface) override;
+ QFunctionPointer getProcAddress(const char *procName) override;
- QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
- bool isSharing() const Q_DECL_OVERRIDE { return m_shareContext != EGL_NO_CONTEXT; }
- bool isValid() const Q_DECL_OVERRIDE { return m_eglContext != EGL_NO_CONTEXT; }
+ QSurfaceFormat format() const override { return m_format; }
+ bool isSharing() const override { return m_shareContext != EGL_NO_CONTEXT; }
+ bool isValid() const override { return m_eglContext != EGL_NO_CONTEXT; }
- void *nativeContext() const Q_DECL_OVERRIDE { return m_eglContext; }
- void *nativeDisplay() const Q_DECL_OVERRIDE { return m_eglDisplay; }
- void *nativeConfig() const Q_DECL_OVERRIDE { return m_eglConfig; }
+ void *nativeContext() const override { return m_eglContext; }
+ void *nativeDisplay() const override { return m_eglDisplay; }
+ void *nativeConfig() const override { return m_eglConfig; }
private:
EGLConfig chooseConfig(const QSurfaceFormat &format);
@@ -167,8 +167,8 @@ private:
EGLDisplay m_eglDisplay;
EGLConfig m_eglConfig;
QSurfaceFormat m_format;
- EGLenum m_api;
- int m_swapInterval;
+ EGLenum m_api = EGL_OPENGL_ES_API;
+ int m_swapInterval = -1;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsgdiintegration.h b/src/plugins/platforms/windows/qwindowsgdiintegration.h
index 46af20a083..ec67a99bc9 100644
--- a/src/plugins/platforms/windows/qwindowsgdiintegration.h
+++ b/src/plugins/platforms/windows/qwindowsgdiintegration.h
@@ -51,9 +51,9 @@ public:
explicit QWindowsGdiIntegration(const QStringList &paramList);
virtual ~QWindowsGdiIntegration();
- QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
- QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const Q_DECL_OVERRIDE;
- QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformNativeInterface *nativeInterface() const override;
+ QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const override;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
private:
QScopedPointer<QWindowsGdiIntegrationPrivate> d;
diff --git a/src/plugins/platforms/windows/qwindowsgdinativeinterface.h b/src/plugins/platforms/windows/qwindowsgdinativeinterface.h
index f0464bc823..c86d3cbb47 100644
--- a/src/plugins/platforms/windows/qwindowsgdinativeinterface.h
+++ b/src/plugins/platforms/windows/qwindowsgdinativeinterface.h
@@ -48,7 +48,7 @@ class QWindowsGdiNativeInterface : public QWindowsNativeInterface
{
Q_OBJECT
public:
- void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs) Q_DECL_OVERRIDE;
+ void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *bs) override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index c1eb664324..751807e897 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -825,13 +825,6 @@ static inline QOpenGLContextData createDummyWindowOpenGLContextData()
\ingroup qt-lighthouse-win
*/
-QWindowsOpenGLContextFormat::QWindowsOpenGLContextFormat() :
- profile(QSurfaceFormat::NoProfile),
- version(0),
- options(0)
-{
-}
-
QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current()
{
QWindowsOpenGLContextFormat result;
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h
index 4c804a612e..23d2fd0d09 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsglcontext.h
@@ -72,24 +72,23 @@ struct QWindowsOpenGLAdditionalFormat
struct QOpenGLContextData
{
QOpenGLContextData(HGLRC r, HWND h, HDC d) : renderingContext(r), hwnd(h), hdc(d) {}
- QOpenGLContextData() : renderingContext(0), hwnd(0), hdc(0) {}
+ QOpenGLContextData() {}
- HGLRC renderingContext;
- HWND hwnd;
- HDC hdc;
+ HGLRC renderingContext = 0;
+ HWND hwnd = 0;
+ HDC hdc = 0;
};
class QOpenGLStaticContext;
struct QWindowsOpenGLContextFormat
{
- QWindowsOpenGLContextFormat();
static QWindowsOpenGLContextFormat current();
void apply(QSurfaceFormat *format) const;
- QSurfaceFormat::OpenGLContextProfile profile;
- int version; //! majorVersion<<8 + minorVersion
- QSurfaceFormat::FormatOptions options;
+ QSurfaceFormat::OpenGLContextProfile profile = QSurfaceFormat::NoProfile;
+ int version = 0; //! majorVersion<<8 + minorVersion
+ QSurfaceFormat::FormatOptions options = 0;
};
#ifndef QT_NO_DEBUG_STREAM
@@ -194,22 +193,22 @@ class QWindowsGLContext : public QWindowsOpenGLContext
public:
explicit QWindowsGLContext(QOpenGLStaticContext *staticContext, QOpenGLContext *context);
~QWindowsGLContext();
- bool isSharing() const Q_DECL_OVERRIDE { return m_context->shareHandle(); }
- bool isValid() const Q_DECL_OVERRIDE { return m_renderingContext && !m_lost; }
- QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_obtainedFormat; }
+ bool isSharing() const override { return m_context->shareHandle(); }
+ bool isValid() const override { return m_renderingContext && !m_lost; }
+ QSurfaceFormat format() const override { return m_obtainedFormat; }
- void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE;
+ void swapBuffers(QPlatformSurface *surface) override;
- bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE;
- void doneCurrent() Q_DECL_OVERRIDE;
+ bool makeCurrent(QPlatformSurface *surface) override;
+ void doneCurrent() override;
typedef void (*GL_Proc) ();
- QFunctionPointer getProcAddress(const char *procName) Q_DECL_OVERRIDE;
+ QFunctionPointer getProcAddress(const char *procName) override;
HGLRC renderingContext() const { return m_renderingContext; }
- void *nativeContext() const Q_DECL_OVERRIDE { return m_renderingContext; }
+ void *nativeContext() const override { return m_renderingContext; }
private:
inline void releaseDCs();
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 8adbd494c4..e7ebf73d5d 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -166,15 +166,8 @@ Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id); // from qlocale_win.cpp
HIMC QWindowsInputContext::m_defaultContext = 0;
-QWindowsInputContext::CompositionContext::CompositionContext() :
- hwnd(0), haveCaret(false), position(0), isComposing(false),
- factor(1)
-{
-}
-
QWindowsInputContext::QWindowsInputContext() :
m_WM_MSIME_MOUSE(RegisterWindowMessage(L"MSIMEMouseOperation")),
- m_endCompositionRecursionGuard(false),
m_languageId(currentInputLanguageId()),
m_locale(qt_localeFromLCID(m_languageId))
{
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h
index a7fa2c4f94..617ef30cef 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.h
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.h
@@ -57,15 +57,13 @@ class QWindowsInputContext : public QPlatformInputContext
struct CompositionContext
{
- CompositionContext();
-
- HWND hwnd;
- bool haveCaret;
+ HWND hwnd = 0;
+ bool haveCaret = false;
QString composition;
- int position;
- bool isComposing;
+ int position = 0;
+ bool isComposing = false;
QPointer<QObject> focusObject;
- qreal factor;
+ qreal factor = 1;
};
public:
explicit QWindowsInputContext();
@@ -73,13 +71,13 @@ public:
static void setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled);
- bool hasCapability(Capability capability) const Q_DECL_OVERRIDE;
- QLocale locale() const Q_DECL_OVERRIDE { return m_locale; }
+ bool hasCapability(Capability capability) const override;
+ QLocale locale() const override { return m_locale; }
- void reset() Q_DECL_OVERRIDE;
- void update(Qt::InputMethodQueries) Q_DECL_OVERRIDE;
- void invokeAction(QInputMethod::Action, int cursorPosition) Q_DECL_OVERRIDE;
- void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
+ void reset() override;
+ void update(Qt::InputMethodQueries) override;
+ void invokeAction(QInputMethod::Action, int cursorPosition) override;
+ void setFocusObject(QObject *object) override;
bool startComposition(HWND hwnd);
bool composition(HWND hwnd, LPARAM lParam);
@@ -104,7 +102,7 @@ private:
const DWORD m_WM_MSIME_MOUSE;
static HIMC m_defaultContext;
CompositionContext m_compositionContext;
- bool m_endCompositionRecursionGuard;
+ bool m_endCompositionRecursionGuard = false;
LCID m_languageId;
QLocale m_locale;
};
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index f49ad0e767..2f88989b3c 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -129,9 +129,9 @@ struct QWindowsIntegrationPrivate
explicit QWindowsIntegrationPrivate(const QStringList &paramList);
~QWindowsIntegrationPrivate();
- unsigned m_options;
+ unsigned m_options = 0;
QWindowsContext m_context;
- QPlatformFontDatabase *m_fontDatabase;
+ QPlatformFontDatabase *m_fontDatabase = nullptr;
#ifndef QT_NO_CLIPBOARD
QWindowsClipboard m_clipboard;
# ifndef QT_NO_DRAGANDDROP
@@ -209,8 +209,6 @@ static inline unsigned parseOptions(const QStringList &paramList,
}
QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramList)
- : m_options(0)
- , m_fontDatabase(0)
{
Q_INIT_RESOURCE(openglblacklists);
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index a668470993..7647b0f4a6 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -70,34 +70,34 @@ public:
explicit QWindowsIntegration(const QStringList &paramList);
virtual ~QWindowsIntegration();
- bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
- QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const override;
#ifndef QT_NO_OPENGL
- QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
- QOpenGLContext::OpenGLModuleType openGLModuleType() Q_DECL_OVERRIDE;
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
+ QOpenGLContext::OpenGLModuleType openGLModuleType() override;
static QWindowsStaticOpenGLContext *staticOpenGLContext();
#endif
- QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE;
- void initialize() Q_DECL_OVERRIDE;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
+ void initialize() override;
#ifndef QT_NO_CLIPBOARD
- QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE;
+ QPlatformClipboard *clipboard() const override;
# ifndef QT_NO_DRAGANDDROP
- QPlatformDrag *drag() const Q_DECL_OVERRIDE;
+ QPlatformDrag *drag() const override;
# endif
#endif // !QT_NO_CLIPBOARD
- QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
+ QPlatformInputContext *inputContext() const override;
#ifndef QT_NO_ACCESSIBILITY
- QPlatformAccessibility *accessibility() const Q_DECL_OVERRIDE;
+ QPlatformAccessibility *accessibility() const override;
#endif
- QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
- QStringList themeNames() const Q_DECL_OVERRIDE;
- QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE;
- QPlatformServices *services() const Q_DECL_OVERRIDE;
- QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE;
+ QPlatformFontDatabase *fontDatabase() const override;
+ QStringList themeNames() const override;
+ QPlatformTheme *createPlatformTheme(const QString &name) const override;
+ QPlatformServices *services() const override;
+ QVariant styleHint(StyleHint hint) const override;
- Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE;
- QList<int> possibleKeys(const QKeyEvent *e) const Q_DECL_OVERRIDE;
+ Qt::KeyboardModifiers queryKeyboardModifiers() const override;
+ QList<int> possibleKeys(const QKeyEvent *e) const override;
static QWindowsIntegration *instance() { return m_instance; }
@@ -106,10 +106,10 @@ public:
unsigned options() const;
- void beep() const Q_DECL_OVERRIDE;
+ void beep() const override;
#if !defined(QT_NO_SESSIONMANAGER)
- QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const Q_DECL_OVERRIDE;
+ QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const override;
#endif
protected:
diff --git a/src/plugins/platforms/windows/qwindowsinternalmimedata.h b/src/plugins/platforms/windows/qwindowsinternalmimedata.h
index 4d775b1f21..a7df1ee6e0 100644
--- a/src/plugins/platforms/windows/qwindowsinternalmimedata.h
+++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.h
@@ -52,9 +52,9 @@ class QDebug;
// Implementation in qwindowsclipboard.cpp.
class QWindowsInternalMimeData : public QInternalMimeData {
public:
- bool hasFormat_sys(const QString &mimetype) const Q_DECL_OVERRIDE;
- QStringList formats_sys() const Q_DECL_OVERRIDE;
- QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
+ bool hasFormat_sys(const QString &mimetype) const override;
+ QStringList formats_sys() const override;
+ QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const override;
protected:
virtual IDataObject *retrieveDataObject() const = 0;
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 00c4a6191e..6375f89531 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -144,13 +144,11 @@ struct KeyRecord {
static const int QT_MAX_KEY_RECORDINGS = 64; // User has LOTS of fingers...
struct KeyRecorder
{
- KeyRecorder() : nrecs(0) {}
-
inline KeyRecord *findKey(int code, bool remove);
inline void storeKey(int code, int ascii, int state, const QString& text);
inline void clearKeys();
- int nrecs;
+ int nrecs = 0;
KeyRecord deleted_record; // A copy of last entry removed from records[]
KeyRecord records[QT_MAX_KEY_RECORDINGS];
};
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 30d438a127..71fd12d71b 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -893,14 +893,14 @@ public:
QWindowsMimeHtml();
// for converting from Qt
- bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
- bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const override;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const override;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
// for converting to Qt
- bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE;
- QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
- QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE;
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const override;
+ QString mimeForFormat(const FORMATETC &formatetc) const override;
private:
int CF_HTML;
@@ -1025,14 +1025,14 @@ class QWindowsMimeImage : public QWindowsMime
public:
QWindowsMimeImage();
// for converting from Qt
- bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
- bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const override;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const override;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
// for converting to Qt
- bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE;
- QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
- QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE;
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const override;
+ QString mimeForFormat(const FORMATETC &formatetc) const override;
private:
bool hasOriginalDIBV5(IDataObject *pDataObj) const;
UINT CF_PNG;
@@ -1179,14 +1179,14 @@ public:
QBuiltInMimes();
// for converting from Qt
- bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
- bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const override;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const override;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
// for converting to Qt
- bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE;
- QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
- QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE;
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const override;
+ QString mimeForFormat(const FORMATETC &formatetc) const override;
private:
QMap<int, QString> outFormats;
@@ -1299,14 +1299,14 @@ public:
QLastResortMimes();
// for converting from Qt
- bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
- bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE;
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const override;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const override;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
// for converting to Qt
- bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE;
- QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
- QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE;
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
+ QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const override;
+ QString mimeForFormat(const FORMATETC &formatetc) const override;
private:
QMap<int, QString> formats;
@@ -1496,9 +1496,7 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const
\sa QWindowsMime
*/
-QWindowsMimeConverter::QWindowsMimeConverter() : m_internalMimeCount(0)
-{
-}
+QWindowsMimeConverter::QWindowsMimeConverter() = default;
QWindowsMimeConverter::~QWindowsMimeConverter()
{
diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h
index 4c0cbf9f31..1ed2aa933f 100644
--- a/src/plugins/platforms/windows/qwindowsmime.h
+++ b/src/plugins/platforms/windows/qwindowsmime.h
@@ -96,7 +96,7 @@ private:
void ensureInitialized() const;
mutable QList<QWindowsMime *> m_mimes;
- mutable int m_internalMimeCount;
+ mutable int m_internalMimeCount = 0;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index 3f6230172e..81349f2998 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -185,14 +185,7 @@ static inline QTouchDevice *createTouchDevice()
\ingroup qt-lighthouse-win
*/
-QWindowsMouseHandler::QWindowsMouseHandler() :
- m_windowUnderMouse(0),
- m_trackedWindow(0),
- m_touchDevice(Q_NULLPTR),
- m_leftButtonDown(false),
- m_previousCaptureWindow(0)
-{
-}
+QWindowsMouseHandler::QWindowsMouseHandler() = default;
QTouchDevice *QWindowsMouseHandler::ensureTouchDevice()
{
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index eaa6e45b9f..cee5dbf165 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -108,6 +108,7 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc
}
break;
case QWindow::OpenGLSurface:
+ case QWindow::OpenVGSurface:
break;
}
qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h
index 9fc43ddcce..4a67400b15 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.h
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h
@@ -68,13 +68,13 @@ class QWindowsNativeInterface : public QPlatformNativeInterface
Q_PROPERTY(QVariant gpu READ gpu STORED false)
public:
- void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
+ void *nativeResourceForIntegration(const QByteArray &resource) override;
#ifndef QT_NO_OPENGL
- void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) Q_DECL_OVERRIDE;
+ void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) override;
#endif
- void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) Q_DECL_OVERRIDE;
+ void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) override;
#ifndef QT_NO_CURSOR
- void *nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor) Q_DECL_OVERRIDE;
+ void *nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor) override;
#endif
Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate,
const QString &windowName,
@@ -92,17 +92,17 @@ public:
QVariant gpu() const;
- QVariantMap windowProperties(QPlatformWindow *window) const Q_DECL_OVERRIDE;
- QVariant windowProperty(QPlatformWindow *window, const QString &name) const Q_DECL_OVERRIDE;
- QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const Q_DECL_OVERRIDE;
- void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value) Q_DECL_OVERRIDE;
+ QVariantMap windowProperties(QPlatformWindow *window) const override;
+ QVariant windowProperty(QPlatformWindow *window, const QString &name) const override;
+ QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const override;
+ void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value) override;
static QWindowsWindowFunctions::WindowActivationBehavior windowActivationBehavior()
{ return QWindowsNativeInterface::m_windowActivationBehavior; }
static void setWindowActivationBehavior(QWindowsWindowFunctions::WindowActivationBehavior b)
{ QWindowsNativeInterface::m_windowActivationBehavior = b; }
- QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE;
+ QFunctionPointer platformFunction(const QByteArray &function) const override;
private:
static QWindowsWindowFunctions::WindowActivationBehavior m_windowActivationBehavior;
diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp
index a1a8c0b499..9b71061aa5 100644
--- a/src/plugins/platforms/windows/qwindowsole.cpp
+++ b/src/plugins/platforms/windows/qwindowsole.cpp
@@ -74,9 +74,8 @@ QT_BEGIN_NAMESPACE
*/
QWindowsOleDataObject::QWindowsOleDataObject(QMimeData *mimeData) :
- m_refs(1), data(mimeData),
- CF_PERFORMEDDROPEFFECT(RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT)),
- performedEffect(DROPEFFECT_NONE)
+ data(mimeData),
+ CF_PERFORMEDDROPEFFECT(RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT))
{
qCDebug(lcQpaMime) << __FUNCTION__ << mimeData->formats();
}
@@ -267,8 +266,7 @@ QWindowsOleDataObject::EnumDAdvise(LPENUMSTATDATA FAR*)
\ingroup qt-lighthouse-win
*/
-QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs) :
- m_dwRefs(1), m_nIndex(0), m_isNull(false)
+QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs)
{
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaMime) << __FUNCTION__ << fmtetcs;
@@ -285,8 +283,7 @@ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs)
}
}
-QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<LPFORMATETC> &lpfmtetcs) :
- m_dwRefs(1), m_nIndex(0), m_isNull(false)
+QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<LPFORMATETC> &lpfmtetcs)
{
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaMime) << __FUNCTION__;
diff --git a/src/plugins/platforms/windows/qwindowsole.h b/src/plugins/platforms/windows/qwindowsole.h
index dc31c793e9..643011272b 100644
--- a/src/plugins/platforms/windows/qwindowsole.h
+++ b/src/plugins/platforms/windows/qwindowsole.h
@@ -82,10 +82,10 @@ public:
STDMETHOD(EnumDAdvise)(LPENUMSTATDATA FAR* ppenumAdvise);
private:
- ULONG m_refs;
+ ULONG m_refs = 1;
QPointer<QMimeData> data;
- int CF_PERFORMEDDROPEFFECT;
- DWORD performedEffect;
+ const int CF_PERFORMEDDROPEFFECT;
+ DWORD performedEffect = DROPEFFECT_NONE;
};
class QWindowsOleEnumFmtEtc : public IEnumFORMATETC
@@ -111,10 +111,10 @@ public:
private:
bool copyFormatEtc(LPFORMATETC dest, const FORMATETC *src) const;
- ULONG m_dwRefs;
- ULONG m_nIndex;
+ ULONG m_dwRefs = 1;
+ ULONG m_nIndex = 0;
QVector<LPFORMATETC> m_lpfmtetcs;
- bool m_isNull;
+ bool m_isNull = false;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h
index 39e20b55d1..e3fec59dd5 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.h
+++ b/src/plugins/platforms/windows/qwindowsopengltester.h
@@ -51,16 +51,14 @@ class QVariant;
struct GpuDescription
{
- GpuDescription() : vendorId(0), deviceId(0), revision(0), subSysId(0) {}
-
static GpuDescription detect();
QString toString() const;
QVariant toVariant() const;
- uint vendorId;
- uint deviceId;
- uint revision;
- uint subSysId;
+ uint vendorId = 0;
+ uint deviceId = 0;
+ uint revision = 0;
+ uint subSysId = 0;
QVersionNumber driverVersion;
QByteArray driverName;
QByteArray description;
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 23d43a95a5..fa2fe6942a 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -56,13 +56,6 @@
QT_BEGIN_NAMESPACE
-QWindowsScreenData::QWindowsScreenData() :
- dpi(96, 96), depth(32), format(QImage::Format_ARGB32_Premultiplied),
- flags(VirtualDesktop), orientation(Qt::LandscapeOrientation),
- refreshRateHz(60)
-{
-}
-
static inline QDpi deviceDPI(HDC hdc)
{
return QDpi(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
@@ -407,10 +400,7 @@ QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTy
\ingroup qt-lighthouse-win
*/
-QWindowsScreenManager::QWindowsScreenManager() :
- m_lastDepth(-1), m_lastHorizontalResolution(0), m_lastVerticalResolution(0)
-{
-}
+QWindowsScreenManager::QWindowsScreenManager() = default;
/*!
\brief Triggers synchronization of screens (WM_DISPLAYCHANGE).
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 02a9dc3bc3..00722e2fa4 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -59,18 +59,16 @@ struct QWindowsScreenData
LockScreen = 0x4 // Temporary screen existing during user change, etc.
};
- QWindowsScreenData();
-
QRect geometry;
QRect availableGeometry;
- QDpi dpi;
+ QDpi dpi{96, 96};
QSizeF physicalSizeMM;
- int depth;
- QImage::Format format;
- unsigned flags;
+ int depth = 32;
+ QImage::Format format = QImage::Format_ARGB32_Premultiplied;
+ unsigned flags = VirtualDesktop;
QString name;
- Qt::ScreenOrientation orientation;
- qreal refreshRateHz;
+ Qt::ScreenOrientation orientation = Qt::LandscapeOrientation;
+ qreal refreshRateHz = 60;
};
class QWindowsScreen : public QPlatformScreen
@@ -82,23 +80,23 @@ public:
explicit QWindowsScreen(const QWindowsScreenData &data);
- QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; }
- QRect availableGeometry() const Q_DECL_OVERRIDE { return m_data.availableGeometry; }
- int depth() const Q_DECL_OVERRIDE { return m_data.depth; }
- QImage::Format format() const Q_DECL_OVERRIDE { return m_data.format; }
- QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_data.physicalSizeMM; }
- QDpi logicalDpi() const Q_DECL_OVERRIDE { return m_data.dpi; }
- qreal pixelDensity() const Q_DECL_OVERRIDE;
- qreal devicePixelRatio() const Q_DECL_OVERRIDE { return 1.0; }
- qreal refreshRate() const Q_DECL_OVERRIDE { return m_data.refreshRateHz; }
- QString name() const Q_DECL_OVERRIDE { return m_data.name; }
- Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_data.orientation; }
- QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE;
- QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE;
+ QRect geometry() const override { return m_data.geometry; }
+ QRect availableGeometry() const override { return m_data.availableGeometry; }
+ int depth() const override { return m_data.depth; }
+ QImage::Format format() const override { return m_data.format; }
+ QSizeF physicalSize() const override { return m_data.physicalSizeMM; }
+ QDpi logicalDpi() const override { return m_data.dpi; }
+ qreal pixelDensity() const override;
+ qreal devicePixelRatio() const override { return 1.0; }
+ qreal refreshRate() const override { return m_data.refreshRateHz; }
+ QString name() const override { return m_data.name; }
+ Qt::ScreenOrientation orientation() const override { return m_data.orientation; }
+ QList<QPlatformScreen *> virtualSiblings() const override;
+ QWindow *topLevelAt(const QPoint &point) const override;
static QWindow *windowAt(const QPoint &point, unsigned flags);
- QPixmap grabWindow(WId window, int qX, int qY, int qWidth, int qHeight) const Q_DECL_OVERRIDE;
- QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE;
+ QPixmap grabWindow(WId window, int qX, int qY, int qWidth, int qHeight) const override;
+ QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const override;
static Qt::ScreenOrientation orientationPreference();
static bool setOrientationPreference(Qt::ScreenOrientation o);
@@ -106,7 +104,7 @@ public:
inline void handleChanges(const QWindowsScreenData &newData);
#ifndef QT_NO_CURSOR
- QPlatformCursor *cursor() const Q_DECL_OVERRIDE { return m_cursor.data(); }
+ QPlatformCursor *cursor() const override { return m_cursor.data(); }
const CursorPtr &cursorPtr() const { return m_cursor; }
#else
QPlatformCursor *cursor() const { return 0; }
@@ -140,9 +138,9 @@ private:
void removeScreen(int index);
WindowsScreenList m_screens;
- int m_lastDepth;
- WORD m_lastHorizontalResolution;
- WORD m_lastVerticalResolution;
+ int m_lastDepth = -1;
+ WORD m_lastHorizontalResolution = 0;
+ WORD m_lastVerticalResolution = 0;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowssessionmanager.cpp b/src/plugins/platforms/windows/qwindowssessionmanager.cpp
index 2db9e44388..500fdc750c 100644
--- a/src/plugins/platforms/windows/qwindowssessionmanager.cpp
+++ b/src/plugins/platforms/windows/qwindowssessionmanager.cpp
@@ -44,9 +44,6 @@ QT_BEGIN_NAMESPACE
QWindowsSessionManager::QWindowsSessionManager(const QString &id, const QString &key)
: QPlatformSessionManager(id, key)
- , m_isActive(false)
- , m_blockUserInput(false)
- , m_canceled(false)
{
}
diff --git a/src/plugins/platforms/windows/qwindowssessionmanager.h b/src/plugins/platforms/windows/qwindowssessionmanager.h
index 25d0636650..4c4256f2b0 100644
--- a/src/plugins/platforms/windows/qwindowssessionmanager.h
+++ b/src/plugins/platforms/windows/qwindowssessionmanager.h
@@ -59,15 +59,15 @@ class QWindowsSessionManager : public QPlatformSessionManager
public:
explicit QWindowsSessionManager(const QString &id, const QString &key);
- bool allowsInteraction() Q_DECL_OVERRIDE;
- bool allowsErrorInteraction() Q_DECL_OVERRIDE;
+ bool allowsInteraction() override;
+ bool allowsErrorInteraction() override;
void blocksInteraction() { m_blockUserInput = true; }
bool isInteractionBlocked() const { return m_blockUserInput; }
- void release() Q_DECL_OVERRIDE;
+ void release() override;
- void cancel() Q_DECL_OVERRIDE;
+ void cancel() override;
void clearCancellation() { m_canceled = false; }
bool wasCanceled() const { return m_canceled; }
@@ -75,9 +75,9 @@ public:
bool isActive() const { return m_isActive;}
private:
- bool m_isActive;
- bool m_blockUserInput;
- bool m_canceled;
+ bool m_isActive = false;
+ bool m_blockUserInput = false;
+ bool m_canceled = false;
Q_DISABLE_COPY(QWindowsSessionManager)
};
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h
index 2c05dcddfc..97eceaf2cc 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.h
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.h
@@ -57,9 +57,6 @@ class QRect;
struct QWindowsWinTab32DLL
{
- QWindowsWinTab32DLL() : wTOpen(0), wTClose(0), wTInfo(0), wTEnable(0), wTOverlap(0), wTPacketsGet(0), wTGet(0),
- wTQueueSizeGet(0), wTQueueSizeSet(0) {}
-
bool init();
typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL);
@@ -72,15 +69,15 @@ struct QWindowsWinTab32DLL
typedef int (API *PtrWTQueueSizeGet)(HCTX);
typedef BOOL (API *PtrWTQueueSizeSet)(HCTX, int);
- PtrWTOpen wTOpen;
- PtrWTClose wTClose;
- PtrWTInfo wTInfo;
- PtrWTEnable wTEnable;
- PtrWTOverlap wTOverlap;
- PtrWTPacketsGet wTPacketsGet;
- PtrWTGet wTGet;
- PtrWTQueueSizeGet wTQueueSizeGet;
- PtrWTQueueSizeSet wTQueueSizeSet;
+ PtrWTOpen wTOpen = nullptr;
+ PtrWTClose wTClose = nullptr;
+ PtrWTInfo wTInfo = nullptr;
+ PtrWTEnable wTEnable = nullptr;
+ PtrWTOverlap wTOverlap = nullptr;
+ PtrWTPacketsGet wTPacketsGet = nullptr;
+ PtrWTGet wTGet = nullptr;
+ PtrWTQueueSizeGet wTQueueSizeGet = nullptr;
+ PtrWTQueueSizeSet wTQueueSizeSet = nullptr;
};
struct QWindowsTabletDeviceData
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index 0384899efa..15b627cce0 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -58,15 +58,15 @@ public:
static QWindowsTheme *instance() { return m_instance; }
- bool usePlatformNativeDialog(DialogType type) const Q_DECL_OVERRIDE;
- QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const Q_DECL_OVERRIDE;
- QVariant themeHint(ThemeHint) const Q_DECL_OVERRIDE;
- const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE
+ bool usePlatformNativeDialog(DialogType type) const override;
+ QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override;
+ QVariant themeHint(ThemeHint) const override;
+ const QPalette *palette(Palette type = SystemPalette) const override
{ return m_palettes[type]; }
- const QFont *font(Font type = SystemFont) const Q_DECL_OVERRIDE
+ const QFont *font(Font type = SystemFont) const override
{ return m_fonts[type]; }
- QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const Q_DECL_OVERRIDE;
+ QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override;
QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions = 0) const override;
diff --git a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
index 0361aa90f5..ad71987ec8 100644
--- a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
+++ b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
@@ -63,7 +63,7 @@ class QWindowsThreadPoolRunner
explicit Runnable(QMutex *m, QWaitCondition *c, RunnableFunction f)
: m_mutex(m), m_condition(c), m_function(f) {}
- void run() Q_DECL_OVERRIDE
+ void run() override
{
m_function();
m_mutex->lock();
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index a9b061ad73..bb5f3a8d75 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -114,6 +114,35 @@ static QByteArray debugWinExStyle(DWORD exStyle)
return rc;
}
+static QByteArray debugWinSwpPos(UINT flags)
+{
+ QByteArray rc = "0x";
+ rc += QByteArray::number(flags, 16);
+ if (flags & SWP_FRAMECHANGED)
+ rc += " SWP_FRAMECHANGED";
+ if (flags & SWP_HIDEWINDOW)
+ rc += " SWP_HIDEWINDOW";
+ if (flags & SWP_NOACTIVATE)
+ rc += " SWP_NOACTIVATE";
+ if (flags & SWP_NOCOPYBITS)
+ rc += " SWP_NOCOPYBITS";
+ if (flags & SWP_NOMOVE)
+ rc += " SWP_NOMOVE";
+ if (flags & SWP_NOOWNERZORDER)
+ rc += " SWP_NOOWNERZORDER";
+ if (flags & SWP_NOREDRAW)
+ rc += " SWP_NOREDRAW";
+ if (flags & SWP_NOSENDCHANGING)
+ rc += " SWP_NOSENDCHANGING";
+ if (flags & SWP_NOSIZE)
+ rc += " SWP_NOSIZE";
+ if (flags & SWP_NOZORDER)
+ rc += " SWP_NOZORDER";
+ if (flags & SWP_SHOWWINDOW)
+ rc += " SWP_SHOWWINDOW";
+ return rc;
+}
+
static inline QSize qSizeOfRect(const RECT &rect)
{
return QSize(rect.right -rect.left, rect.bottom - rect.top);
@@ -137,8 +166,9 @@ QDebug operator<<(QDebug d, const RECT &r)
{
QDebugStateSaver saver(d);
d.nospace();
- d << "RECT: left/top=" << r.left << ',' << r.top
- << " right/bottom=" << r.right << ',' << r.bottom;
+ d << "RECT(left=" << r.left << ", top=" << r.top
+ << ", right=" << r.right << ", bottom=" << r.bottom
+ << " (" << r.right - r.left << 'x' << r.bottom - r.top << "))";
return d;
}
@@ -148,12 +178,23 @@ QDebug operator<<(QDebug d, const POINT &p)
return d;
}
+QDebug operator<<(QDebug d, const WINDOWPOS &wp)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d.noquote();
+ d << "WINDOWPOS(flags=" << debugWinSwpPos(wp.flags) << ", hwnd="
+ << wp.hwnd << ", hwndInsertAfter=" << wp.hwndInsertAfter << ", x=" << wp.x
+ << ", y=" << wp.y << ", cx=" << wp.cx << ", cy=" << wp.cy << ')';
+ return d;
+}
+
QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p)
{
QDebugStateSaver saver(d);
d.nospace();
- d << "NCCALCSIZE_PARAMS " << qrectFromRECT(p.rgrc[0])
- << ' ' << qrectFromRECT(p.rgrc[1]) << ' ' << qrectFromRECT(p.rgrc[2]);
+ d << "NCCALCSIZE_PARAMS(rgrc=[" << p.rgrc[0] << ' ' << p.rgrc[1] << ' '
+ << p.rgrc[2] << "], lppos=" << *p.lppos << ')';
return d;
}
@@ -173,6 +214,7 @@ QDebug operator<<(QDebug d, const WINDOWPLACEMENT &wp)
{
QDebugStateSaver saver(d);
d.nospace();
+ d.noquote();
d << "WINDOWPLACEMENT(flags=0x" << hex << wp.flags << dec << ", showCmd="
<< wp.showCmd << ", ptMinPosition=" << wp.ptMinPosition << ", ptMaxPosition=" << wp.ptMaxPosition
<< ", rcNormalPosition=" << wp.rcNormalPosition;
@@ -935,9 +977,7 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
DWORD style_, DWORD exStyle_) :
geometryHint(w, cm), window(w), style(style_), exStyle(exStyle_),
requestedGeometry(geometry), obtainedGeometry(geometry),
- margins(QWindowsGeometryHint::frame(style, exStyle)), customMargins(cm),
- frameX(CW_USEDEFAULT), frameY(CW_USEDEFAULT),
- frameWidth(CW_USEDEFAULT), frameHeight(CW_USEDEFAULT)
+ margins(QWindowsGeometryHint::frame(style, exStyle)), customMargins(cm)
{
// Geometry of toplevels does not consider window frames.
// TODO: No concept of WA_wasMoved yet that would indicate a
@@ -990,17 +1030,8 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) :
QWindowsBaseWindow(aWindow),
m_data(data),
- m_flags(WithinCreate),
- m_hdc(0),
- m_windowState(Qt::WindowNoState),
- m_opacity(1.0),
m_cursor(new CursorHandle),
- m_dropTarget(0),
- m_savedStyle(0),
- m_format(aWindow->requestedFormat()),
- m_iconSmall(0),
- m_iconBig(0),
- m_surface(0)
+ m_format(aWindow->requestedFormat())
{
// Clear the creation context as the window can be found in QWindowsContext's map.
QWindowsContext::instance()->setWindowCreationContext(QSharedPointer<QWindowCreationContext>());
@@ -1639,7 +1670,6 @@ QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
QWindowsWindowData result = m_data;
result.flags = creationData.flags;
result.embedded = creationData.embedded;
- setFlag(FrameDirty);
return result;
}
@@ -1647,7 +1677,6 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
{
qCDebug(lcQpaWindows) << __FUNCTION__ << this << window()
<< "\n from " << m_windowState << " to " << state;
- setFlag(FrameDirty);
m_windowState = state;
QWindowSystemInterface::handleWindowStateChanged(window(), state);
switch (state) {
@@ -1724,8 +1753,6 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
const bool visible = isVisible();
- setFlag(FrameDirty);
-
if ((oldState == Qt::WindowFullScreen) != (newState == Qt::WindowFullScreen)) {
if (newState == Qt::WindowFullScreen) {
#ifndef Q_FLATTEN_EXPOSE
@@ -1819,7 +1846,6 @@ void QWindowsWindow::setStyle(unsigned s) const
{
qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << debugWinStyle(s);
setFlag(WithinSetStyle);
- setFlag(FrameDirty);
SetWindowLongPtr(m_data.hwnd, GWL_STYLE, s);
clearFlag(WithinSetStyle);
}
@@ -1828,7 +1854,6 @@ void QWindowsWindow::setExStyle(unsigned s) const
{
qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << ' ' << this << ' ' << window()
<< " 0x" << QByteArray::number(s, 16);
- setFlag(FrameDirty);
SetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE, s);
}
@@ -1884,22 +1909,17 @@ bool QWindowsWindow::handleGeometryChanging(MSG *message) const
return QWindowsWindow::handleGeometryChangingMessage(message, window(), margins);
}
-QMargins QWindowsWindow::frameMargins() const
+void QWindowsWindow::setFrameMargins(const QMargins &newMargins)
{
- // Frames are invalidated by style changes (window state, flags).
- // As they are also required for geometry calculations in resize
- // event sequences, introduce a dirty flag mechanism to be able
- // to cache results.
- if (testFlag(FrameDirty)) {
- // Always skip calculating style-dependent margins for windows claimed to be frameless.
- // This allows users to remove the margins by handling WM_NCCALCSIZE with WS_THICKFRAME set
- // to ensure Areo snap still works (QTBUG-40578).
- m_data.frame = m_data.flags & Qt::FramelessWindowHint
- ? QMargins(0, 0, 0, 0)
- : QWindowsGeometryHint::frame(style(), exStyle());
- clearFlag(FrameDirty);
+ if (m_data.frame != newMargins) {
+ qCDebug(lcQpaWindows) << __FUNCTION__ << window() << m_data.frame << "->" << newMargins;
+ m_data.frame = newMargins;
}
- return m_data.frame + m_data.customMargins;
+}
+
+QMargins QWindowsWindow::frameMargins() const
+{
+ return m_data.frame;
}
void QWindowsWindow::setOpacity(qreal level)
@@ -2315,7 +2335,6 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
const QPoint topLeft = currentFrameGeometry.topLeft();
QRect newFrame = currentFrameGeometry.marginsRemoved(oldCustomMargins) + m_data.customMargins;
newFrame.moveTo(topLeft);
- setFlag(FrameDirty);
qCDebug(lcQpaWindows) << __FUNCTION__ << oldCustomMargins << "->" << newCustomMargins
<< currentFrameGeometry << "->" << newFrame;
SetWindowPos(m_data.hwnd, 0, newFrame.x(), newFrame.y(), newFrame.width(), newFrame.height(), SWP_NOZORDER | SWP_FRAMECHANGED);
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 924f242e6e..54c9900771 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -89,22 +89,20 @@ struct QWindowCreationContext
QRect obtainedGeometry;
QMargins margins;
QMargins customMargins; // User-defined, additional frame for WM_NCCALCSIZE
- int frameX; // Passed on to CreateWindowEx(), including frame.
- int frameY;
- int frameWidth;
- int frameHeight;
+ int frameX = CW_USEDEFAULT; // Passed on to CreateWindowEx(), including frame.
+ int frameY = CW_USEDEFAULT;
+ int frameWidth = CW_USEDEFAULT;
+ int frameHeight = CW_USEDEFAULT;
};
struct QWindowsWindowData
{
- QWindowsWindowData() : hwnd(0), embedded(false) {}
-
Qt::WindowFlags flags;
QRect geometry;
QMargins frame; // Do not use directly for windows, see FrameDirty.
QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
- HWND hwnd;
- bool embedded;
+ HWND hwnd = 0;
+ bool embedded = false;
static QWindowsWindowData create(const QWindow *w,
const QWindowsWindowData &parameters,
@@ -116,11 +114,11 @@ class QWindowsBaseWindow : public QPlatformWindow
public:
explicit QWindowsBaseWindow(QWindow *window) : QPlatformWindow(window) {}
- WId winId() const Q_DECL_OVERRIDE { return WId(handle()); }
- QRect geometry() const Q_DECL_OVERRIDE { return geometry_sys(); }
- QMargins frameMargins() const Q_DECL_OVERRIDE { return frameMargins_sys(); }
- QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
- QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
+ WId winId() const override { return WId(handle()); }
+ QRect geometry() const override { return geometry_sys(); }
+ QMargins frameMargins() const override { return frameMargins_sys(); }
+ QPoint mapToGlobal(const QPoint &pos) const override;
+ QPoint mapFromGlobal(const QPoint &pos) const override;
using QPlatformWindow::screenForGeometry;
@@ -152,11 +150,11 @@ public:
explicit QWindowsDesktopWindow(QWindow *window)
: QWindowsBaseWindow(window), m_hwnd(GetDesktopWindow()) {}
- QMargins frameMargins() const Q_DECL_OVERRIDE { return QMargins(); }
- bool isTopLevel() const Q_DECL_OVERRIDE { return true; }
+ QMargins frameMargins() const override { return QMargins(); }
+ bool isTopLevel() const override { return true; }
protected:
- HWND handle() const Q_DECL_OVERRIDE { return m_hwnd; }
+ HWND handle() const override { return m_hwnd; }
private:
const HWND m_hwnd;
@@ -167,15 +165,15 @@ class QWindowsForeignWindow : public QWindowsBaseWindow
public:
explicit QWindowsForeignWindow(QWindow *window, HWND hwnd);
- void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE;
- void setGeometry(const QRect &rect) Q_DECL_OVERRIDE { setGeometry_sys(rect); }
- void setVisible(bool visible) Q_DECL_OVERRIDE;
- void raise() Q_DECL_OVERRIDE { raise_sys(); }
- void lower() Q_DECL_OVERRIDE { lower_sys(); }
- void setWindowTitle(const QString &title) Q_DECL_OVERRIDE { setWindowTitle_sys(title); }
+ void setParent(const QPlatformWindow *window) override;
+ void setGeometry(const QRect &rect) override { setGeometry_sys(rect); }
+ void setVisible(bool visible) override;
+ void raise() override { raise_sys(); }
+ void lower() override { lower_sys(); }
+ void setWindowTitle(const QString &title) override { setWindowTitle_sys(title); }
protected:
- HWND handle() const Q_DECL_OVERRIDE { return m_hwnd; }
+ HWND handle() const override { return m_hwnd; }
private:
const HWND m_hwnd;
@@ -189,7 +187,6 @@ public:
{
AutoMouseCapture = 0x1, //! Automatic mouse capture on button press.
WithinSetParent = 0x2,
- FrameDirty = 0x4, //! Frame outdated by setStyle, recalculate in next query.
OpenGLSurface = 0x10,
OpenGL_ES2 = 0x20,
OpenGLDoubleBuffered = 0x40,
@@ -216,52 +213,53 @@ public:
using QPlatformWindow::screenForGeometry;
- QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
- void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
- QRect geometry() const Q_DECL_OVERRIDE { return m_data.geometry; }
- QRect normalGeometry() const Q_DECL_OVERRIDE;
+ QSurfaceFormat format() const override { return m_format; }
+ void setGeometry(const QRect &rect) override;
+ QRect geometry() const override { return m_data.geometry; }
+ QRect normalGeometry() const override;
- void setVisible(bool visible) Q_DECL_OVERRIDE;
+ void setVisible(bool visible) override;
bool isVisible() const;
- bool isExposed() const Q_DECL_OVERRIDE { return testFlag(Exposed); }
- bool isActive() const Q_DECL_OVERRIDE;
- bool isEmbedded(const QPlatformWindow *parentWindow = 0) const Q_DECL_OVERRIDE;
- QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
- QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE;
+ bool isExposed() const override { return testFlag(Exposed); }
+ bool isActive() const override;
+ bool isEmbedded(const QPlatformWindow *parentWindow = 0) const override;
+ QPoint mapToGlobal(const QPoint &pos) const override;
+ QPoint mapFromGlobal(const QPoint &pos) const override;
- void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
- void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
+ void setWindowFlags(Qt::WindowFlags flags) override;
+ void setWindowState(Qt::WindowState state) override;
- void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE;
+ void setParent(const QPlatformWindow *window) override;
- void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
- void raise() Q_DECL_OVERRIDE { raise_sys(); }
- void lower() Q_DECL_OVERRIDE { lower_sys(); }
+ void setWindowTitle(const QString &title) override;
+ void raise() override { raise_sys(); }
+ void lower() override { lower_sys(); }
- void windowEvent(QEvent *event) Q_DECL_OVERRIDE;
+ void windowEvent(QEvent *event) override;
- void propagateSizeHints() Q_DECL_OVERRIDE;
+ void propagateSizeHints() override;
static bool handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp);
bool handleGeometryChanging(MSG *message) const;
- QMargins frameMargins() const Q_DECL_OVERRIDE;
+ QMargins frameMargins() const override;
+ void setFrameMargins(const QMargins &newMargins);
- void setOpacity(qreal level) Q_DECL_OVERRIDE;
- void setMask(const QRegion &region) Q_DECL_OVERRIDE;
+ void setOpacity(qreal level) override;
+ void setMask(const QRegion &region) override;
qreal opacity() const { return m_opacity; }
- void requestActivateWindow() Q_DECL_OVERRIDE;
+ void requestActivateWindow() override;
- bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE;
- bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
+ bool setKeyboardGrabEnabled(bool grab) override;
+ bool setMouseGrabEnabled(bool grab) override;
inline bool hasMouseCapture() const { return GetCapture() == m_data.hwnd; }
- bool startSystemResize(const QPoint &pos, Qt::Corner corner) Q_DECL_OVERRIDE;
+ bool startSystemResize(const QPoint &pos, Qt::Corner corner) override;
- void setFrameStrutEventsEnabled(bool enabled) Q_DECL_OVERRIDE;
- bool frameStrutEventsEnabled() const Q_DECL_OVERRIDE { return testFlag(FrameStrutEventsEnabled); }
+ void setFrameStrutEventsEnabled(bool enabled) override;
+ bool frameStrutEventsEnabled() const override { return testFlag(FrameStrutEventsEnabled); }
// QWindowsBaseWindow overrides
- HWND handle() const Q_DECL_OVERRIDE { return m_data.hwnd; }
- bool isTopLevel() const Q_DECL_OVERRIDE;
+ HWND handle() const override { return m_data.hwnd; }
+ bool isTopLevel() const override;
QMargins customMargins() const { return m_data.customMargins; }
void setCustomMargins(const QMargins &m);
@@ -301,14 +299,14 @@ public:
void setEnabled(bool enabled);
bool isEnabled() const;
- void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE;
+ void setWindowIcon(const QIcon &icon) override;
void *surface(void *nativeConfig, int *err);
- void invalidateSurface() Q_DECL_OVERRIDE;
+ void invalidateSurface() override;
void aboutToMakeCurrent();
- void setAlertState(bool enabled) Q_DECL_OVERRIDE;
- bool isAlertState() const Q_DECL_OVERRIDE { return testFlag(AlertState); }
+ void setAlertState(bool enabled) override;
+ bool isAlertState() const override { return testFlag(AlertState); }
void alertWindow(int durationMs = 0);
void stopAlertWindow();
@@ -335,20 +333,20 @@ private:
void fireExpose(const QRegion &region, bool force=false);
mutable QWindowsWindowData m_data;
- mutable unsigned m_flags;
- HDC m_hdc;
- Qt::WindowState m_windowState;
- qreal m_opacity;
+ mutable unsigned m_flags = WithinCreate;
+ HDC m_hdc = 0;
+ Qt::WindowState m_windowState = Qt::WindowNoState;
+ qreal m_opacity = 1;
#ifndef QT_NO_CURSOR
CursorHandlePtr m_cursor;
#endif
- QWindowsOleDropTarget *m_dropTarget;
- unsigned m_savedStyle;
+ QWindowsOleDropTarget *m_dropTarget = nullptr;
+ unsigned m_savedStyle = 0;
QRect m_savedFrameGeometry;
const QSurfaceFormat m_format;
- HICON m_iconSmall;
- HICON m_iconBig;
- void *m_surface;
+ HICON m_iconSmall = 0;
+ HICON m_iconBig = 0;
+ void *m_surface = nullptr;
};
#ifndef QT_NO_DEBUG_STREAM
@@ -357,6 +355,7 @@ QDebug operator<<(QDebug d, const POINT &);
QDebug operator<<(QDebug d, const MINMAXINFO &i);
QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p);
QDebug operator<<(QDebug d, const WINDOWPLACEMENT &);
+QDebug operator<<(QDebug d, const WINDOWPOS &);
#endif // !QT_NO_DEBUG_STREAM
// ---------- QWindowsGeometryHint inline functions.
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index 20e0b81da9..7d3ecc8aa2 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -99,5 +99,5 @@ RESOURCES += $$PWD/openglblacklists.qrc
qtConfig(accessibility): include($$PWD/accessible/accessible.pri)
-DEFINES *= LIBEGL_NAME=$${LIBEGL_NAME}
-DEFINES *= LIBGLESV2_NAME=$${LIBGLESV2_NAME}
+DEFINES *= LIBEGL_NAME=$${LIBQTANGLE_NAME}
+DEFINES *= LIBGLESV2_NAME=$${LIBQTANGLE_NAME}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 9e275efa25..2834ff3224 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -131,7 +131,7 @@ typedef struct qt_xcb_ge_event_t {
static inline bool isXIEvent(xcb_generic_event_t *event, int opCode)
{
- qt_xcb_ge_event_t *e = (qt_xcb_ge_event_t *)event;
+ qt_xcb_ge_event_t *e = reinterpret_cast<qt_xcb_ge_event_t *>(event);
return e->extension == opCode;
}
#endif // XCB_USE_XINPUT2
@@ -251,7 +251,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
// Find a fake screen
const auto scrs = virtualDesktop->screens();
for (QPlatformScreen *scr : scrs) {
- QXcbScreen *xcbScreen = (QXcbScreen *)scr;
+ QXcbScreen *xcbScreen = static_cast<QXcbScreen *>(scr);
if (xcbScreen->output() == XCB_NONE) {
screen = xcbScreen;
break;
@@ -377,7 +377,7 @@ void QXcbConnection::destroyScreen(QXcbScreen *screen)
// When primary screen is removed, set the new primary screen
// which belongs to the primary virtual desktop.
if (screen->isPrimary()) {
- QXcbScreen *newPrimary = (QXcbScreen *)virtualDesktop->screens().at(0);
+ QXcbScreen *newPrimary = static_cast<QXcbScreen *>(virtualDesktop->screens().at(0));
newPrimary->setPrimary(true);
const int idx = m_screens.indexOf(newPrimary);
if (idx > 0)
@@ -711,7 +711,7 @@ QXcbConnection::~QXcbConnection()
delete m_glIntegration;
#ifdef XCB_USE_XLIB
- XCloseDisplay((Display *)m_xlib_display);
+ XCloseDisplay(static_cast<Display *>(m_xlib_display));
#else
xcb_disconnect(xcb_connection());
#endif
@@ -754,7 +754,7 @@ QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id)
#define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \
{ \
- event_t *e = (event_t *)event; \
+ event_t *e = reinterpret_cast<event_t *>(event); \
if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->windowMember)) { \
handled = eventListener->handleGenericEvent(event, &result); \
if (!handled) \
@@ -765,7 +765,7 @@ break;
#define HANDLE_KEYBOARD_EVENT(event_t, handler) \
{ \
- event_t *e = (event_t *)event; \
+ event_t *e = reinterpret_cast<event_t *>(event); \
if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->event)) { \
handled = eventListener->handleGenericEvent(event, &result); \
if (!handled) \
@@ -1184,11 +1184,11 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state);
HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
case XCB_MAPPING_NOTIFY:
- m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event);
+ m_keyboard->handleMappingNotifyEvent(reinterpret_cast<xcb_mapping_notify_event_t *>(event));
break;
case XCB_SELECTION_REQUEST:
{
- xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)event;
+ xcb_selection_request_event_t *sr = reinterpret_cast<xcb_selection_request_event_t *>(event);
#ifndef QT_NO_DRAGANDDROP
if (sr->selection == atom(QXcbAtom::XdndSelection))
m_drag->handleSelectionRequest(sr);
@@ -1202,19 +1202,19 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
break;
}
case XCB_SELECTION_CLEAR:
- setTime(((xcb_selection_clear_event_t *)event)->time);
+ setTime((reinterpret_cast<xcb_selection_clear_event_t *>(event))->time);
#ifndef QT_NO_CLIPBOARD
- m_clipboard->handleSelectionClearRequest((xcb_selection_clear_event_t *)event);
+ m_clipboard->handleSelectionClearRequest(reinterpret_cast<xcb_selection_clear_event_t *>(event));
#endif
handled = true;
break;
case XCB_SELECTION_NOTIFY:
- setTime(((xcb_selection_notify_event_t *)event)->time);
+ setTime((reinterpret_cast<xcb_selection_notify_event_t *>(event))->time);
handled = false;
break;
case XCB_PROPERTY_NOTIFY:
{
- xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event;
+ xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event);
if (pn->atom == atom(QXcbAtom::_NET_WORKAREA)) {
QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(pn->window);
if (virtualDesktop)
@@ -1239,7 +1239,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
if (!handled) {
if (response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) {
- xcb_xfixes_selection_notify_event_t *notify_event = (xcb_xfixes_selection_notify_event_t *)event;
+ xcb_xfixes_selection_notify_event_t *notify_event = reinterpret_cast<xcb_xfixes_selection_notify_event_t *>(event);
setTime(notify_event->timestamp);
#ifndef QT_NO_CLIPBOARD
m_clipboard->handleXFixesSelectionRequest(notify_event);
@@ -1249,10 +1249,10 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
handled = true;
} else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) {
- updateScreens((xcb_randr_notify_event_t *)event);
+ updateScreens(reinterpret_cast<xcb_randr_notify_event_t *>(event));
handled = true;
} else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
- xcb_randr_screen_change_notify_event_t *change_event = (xcb_randr_screen_change_notify_event_t *)event;
+ xcb_randr_screen_change_notify_event_t *change_event = reinterpret_cast<xcb_randr_screen_change_notify_event_t *>(event);
for (QXcbScreen *s : qAsConst(m_screens)) {
if (s->root() == change_event->root )
s->handleScreenChange(change_event);
@@ -1361,7 +1361,7 @@ void QXcbEventReader::run()
void QXcbEventReader::addEvent(xcb_generic_event_t *event)
{
if ((event->response_type & ~0x80) == XCB_CLIENT_MESSAGE
- && ((xcb_client_message_event_t *)event)->type == m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION))
+ && (reinterpret_cast<xcb_client_message_event_t *>(event))->type == m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION))
m_connection = 0;
m_events << event;
}
@@ -1427,7 +1427,7 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id)
event.type = atom(a);
event.data.data32[0] = id;
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event));
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char *>(&event)));
Q_XCB_CALL(xcb_destroy_window(m_connection, eventListener));
xcb_flush(xcb_connection());
}
@@ -1447,7 +1447,7 @@ namespace
if ((event->response_type & ~0x80) != type) {
return false;
} else {
- xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event;
+ xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event);
if ((pn->window == window) && (pn->atom == atom))
return true;
}
@@ -1475,7 +1475,7 @@ xcb_timestamp_t QXcbConnection::getTimestamp()
event = checkEvent(checker);
}
- xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event;
+ xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event);
xcb_timestamp_t timestamp = pn->time;
free(event);
@@ -1499,7 +1499,8 @@ xcb_window_t QXcbConnection::getQtSelectionOwner()
{
if (!m_qtSelectionOwner) {
xcb_screen_t *xcbScreen = primaryVirtualDesktop()->screen();
- int x = 0, y = 0, w = 3, h = 3;
+ int16_t x = 0, y = 0;
+ uint16_t w = 3, h = 3;
m_qtSelectionOwner = xcb_generate_id(xcb_connection());
Q_XCB_CALL(xcb_create_window(xcb_connection(),
XCB_COPY_FROM_PARENT, // depth -- same as root
@@ -1688,7 +1689,7 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex,
for (int j = nextIndex; j < eventqueue->size(); ++j) {
xcb_generic_event_t *next = eventqueue->at(j);
if (isValid(next) && next->response_type == XCB_CONFIGURE_NOTIFY
- && ((xcb_configure_notify_event_t *)next)->event == ((xcb_configure_notify_event_t*)event)->event)
+ && reinterpret_cast<xcb_configure_notify_event_t *>(next)->event == reinterpret_cast<xcb_configure_notify_event_t *>(event)->event)
{
return true;
}
@@ -1717,7 +1718,7 @@ void QXcbConnection::processXcbEvents()
(*eventqueue)[i] = 0;
if (!(event->response_type & ~0x80)) {
- handleXcbError((xcb_generic_error_t *)event);
+ handleXcbError(reinterpret_cast<xcb_generic_error_t *>(event));
continue;
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 60f0f487c5..3754890796 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -703,7 +703,7 @@ Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_MOVABLE_TYPE);
#endif
#endif
-#define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display()))
+#define DISPLAY_FROM_XCB(object) (reinterpret_cast<Display *>(object->connection()->xlib_display()))
#define CREATE_VISUALINFO_FROM_DEFAULT_VISUALID(object) ((XVisualInfo *)(object->connection()->createVisualInfoForDefaultVisualId()))
template<typename T>
diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
index 6df631bff3..7e64906476 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
+++ b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp
@@ -51,11 +51,18 @@ QT_BEGIN_NAMESPACE
const char *QGtk3Theme::name = "gtk3";
-static QString gtkSetting(const gchar *propertyName)
+template <typename T>
+static T gtkSetting(const gchar *propertyName)
{
GtkSettings *settings = gtk_settings_get_default();
- gchararray value;
+ T value;
g_object_get(settings, propertyName, &value, NULL);
+ return value;
+}
+
+static QString gtkSetting(const gchar *propertyName)
+{
+ gchararray value = gtkSetting<gchararray>(propertyName);
QString str = QString::fromUtf8(value);
g_free(value);
return str;
@@ -98,6 +105,18 @@ QGtk3Theme::QGtk3Theme()
QVariant QGtk3Theme::themeHint(QPlatformTheme::ThemeHint hint) const
{
switch (hint) {
+ case QPlatformTheme::CursorFlashTime:
+ return QVariant(gtkSetting<gint>("gtk-cursor-blink-time"));
+ case QPlatformTheme::MouseDoubleClickDistance:
+ return QVariant(gtkSetting<gint>("gtk-double-click-distance"));
+ case QPlatformTheme::MouseDoubleClickInterval:
+ return QVariant(gtkSetting<gint>("gtk-double-click-time"));
+ case QPlatformTheme::MousePressAndHoldInterval:
+ return QVariant(gtkSetting<guint>("gtk-long-press-time"));
+ case QPlatformTheme::PasswordMaskDelay:
+ return QVariant(gtkSetting<guint>("gtk-entry-password-hint-timeout"));
+ case QPlatformTheme::StartDragDistance:
+ return QVariant(gtkSetting<gint>("gtk-dnd-drag-threshold"));
case QPlatformTheme::SystemIconThemeName:
return QVariant(gtkSetting("gtk-icon-theme-name"));
case QPlatformTheme::SystemIconFallbackThemeName:
diff --git a/src/printsupport/kernel/qplatformprintplugin.cpp b/src/printsupport/kernel/qplatformprintplugin.cpp
index 9bc4b61829..a80f369040 100644
--- a/src/printsupport/kernel/qplatformprintplugin.cpp
+++ b/src/printsupport/kernel/qplatformprintplugin.cpp
@@ -42,6 +42,7 @@
#include "qprinterinfo.h"
#include "private/qfactoryloader_p.h"
#include <qcoreapplication.h>
+#include <qdebug.h>
#ifndef QT_NO_PRINTER
@@ -79,8 +80,17 @@ QPlatformPrinterSupport *QPlatformPrinterSupportPlugin::get()
{
if (!printerSupport) {
const QMultiMap<int, QString> keyMap = loader()->keyMap();
- if (!keyMap.isEmpty())
- printerSupport = qLoadPlugin<QPlatformPrinterSupport, QPlatformPrinterSupportPlugin>(loader(), keyMap.constBegin().value());
+ QMultiMap<int, QString>::const_iterator it = keyMap.cbegin();
+ if (!qEnvironmentVariableIsEmpty("QT_PRINTER_MODULE")) {
+ QString module = QString::fromLocal8Bit(qgetenv("QT_PRINTER_MODULE"));
+ QMultiMap<int, QString>::const_iterator it2 = std::find_if(keyMap.cbegin(), keyMap.cend(), [module](const QString &value){ return value == module; });
+ if (it2 == keyMap.cend())
+ qWarning() << "Unable to load printer plugin" << module;
+ else
+ it = it2;
+ }
+ if (it != keyMap.cend())
+ printerSupport = qLoadPlugin<QPlatformPrinterSupport, QPlatformPrinterSupportPlugin>(loader(), it.value());
if (printerSupport)
qAddPostRoutine(cleanupPrinterSupport);
}
diff --git a/src/src.pro b/src/src.pro
index b13bc4fa43..13aa08c12a 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -78,8 +78,8 @@ src_testlib.subdir = $$PWD/testlib
src_testlib.target = sub-testlib
src_testlib.depends = src_corelib # testlib links only to corelib, but see below for the headers
-src_3rdparty_pcre.subdir = $$PWD/3rdparty/pcre
-src_3rdparty_pcre.target = sub-3rdparty-pcre
+src_3rdparty_pcre2.subdir = $$PWD/3rdparty/pcre2
+src_3rdparty_pcre2.target = sub-3rdparty-pcre2
src_3rdparty_harfbuzzng.subdir = $$PWD/3rdparty/harfbuzz-ng
src_3rdparty_harfbuzzng.target = sub-3rdparty-harfbuzzng
@@ -137,9 +137,9 @@ src_android.subdir = $$PWD/android
}
}
SUBDIRS += src_tools_bootstrap src_tools_moc src_tools_rcc
-qtConfig(regularexpression):pcre {
- SUBDIRS += src_3rdparty_pcre
- src_corelib.depends += src_3rdparty_pcre
+qtConfig(regularexpression):pcre2 {
+ SUBDIRS += src_3rdparty_pcre2
+ src_corelib.depends += src_3rdparty_pcre2
}
SUBDIRS += src_corelib src_tools_qlalr
TOOLS = src_tools_moc src_tools_rcc src_tools_qlalr
@@ -197,7 +197,7 @@ android: SUBDIRS += src_android
TR_EXCLUDE = \
src_tools_bootstrap src_tools_moc src_tools_rcc src_tools_uic src_tools_qlalr \
src_tools_bootstrap_dbus src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml \
- src_3rdparty_pcre src_3rdparty_harfbuzzng src_3rdparty_freetype
+ src_3rdparty_pcre2 src_3rdparty_harfbuzzng src_3rdparty_freetype
sub-tools.depends = $$TOOLS
QMAKE_EXTRA_TARGETS = sub-tools
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 7b76f1f970..1f07ff3f91 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -104,6 +104,9 @@
#if defined(Q_OS_MACX)
#include <IOKit/pwr_mgt/IOPMLib.h>
+#include <mach/task.h>
+#include <mach/mach_init.h>
+#include <CoreFoundation/CFPreferences.h>
#endif
#include <vector>
@@ -138,6 +141,40 @@ static bool debuggerPresent()
return pid != 0;
#elif defined(Q_OS_WIN)
return IsDebuggerPresent();
+#elif defined(Q_OS_MACOS)
+ auto equals = [](CFStringRef str1, CFStringRef str2) -> bool {
+ return CFStringCompare(str1, str2, kCFCompareCaseInsensitive) == kCFCompareEqualTo;
+ };
+
+ // Check if there is an exception handler for the process:
+ mach_msg_type_number_t portCount = 0;
+ exception_mask_t masks[EXC_TYPES_COUNT];
+ mach_port_t ports[EXC_TYPES_COUNT];
+ exception_behavior_t behaviors[EXC_TYPES_COUNT];
+ thread_state_flavor_t flavors[EXC_TYPES_COUNT];
+ exception_mask_t mask = EXC_MASK_ALL & ~(EXC_MASK_RESOURCE | EXC_MASK_GUARD);
+ kern_return_t result = task_get_exception_ports(mach_task_self(), mask, masks, &portCount,
+ ports, behaviors, flavors);
+ if (result == KERN_SUCCESS) {
+ for (mach_msg_type_number_t portIndex = 0; portIndex < portCount; ++portIndex) {
+ if (MACH_PORT_VALID(ports[portIndex])) {
+ return true;
+ }
+ }
+ }
+
+ // Ok, no debugger attached. So, let's see if CrashReporter will throw up a dialog. If so, we
+ // leave it to the OS to do the stack trace.
+ CFStringRef crashReporterType = static_cast<CFStringRef>(
+ CFPreferencesCopyAppValue(CFSTR("DialogType"), CFSTR("com.apple.CrashReporter")));
+ if (crashReporterType == nullptr)
+ return true;
+
+ const bool createsStackTrace =
+ !equals(crashReporterType, CFSTR("server")) &&
+ !equals(crashReporterType, CFSTR("none"));
+ CFRelease(crashReporterType);
+ return createsStackTrace;
#else
// TODO
return false;
diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
index d51f9e98a4..0a61497588 100644
--- a/src/tools/bootstrap/bootstrap.pro
+++ b/src/tools/bootstrap/bootstrap.pro
@@ -28,6 +28,7 @@ SOURCES += \
../../corelib/global/qlogging.cpp \
../../corelib/global/qmalloc.cpp \
../../corelib/global/qnumeric.cpp \
+ ../../corelib/global/qoperatingsystemversion.cpp \
../../corelib/io/qabstractfileengine.cpp \
../../corelib/io/qbuffer.cpp \
../../corelib/io/qdatastream.cpp \
@@ -96,7 +97,8 @@ unix:SOURCES += ../../corelib/io/qfilesystemengine_unix.cpp \
../../corelib/io/qfilesystemiterator_unix.cpp \
../../corelib/io/qfsfileengine_unix.cpp
-win32:SOURCES += ../../corelib/io/qfilesystemengine_win.cpp \
+win32:SOURCES += ../../corelib/global/qoperatingsystemversion_win.cpp \
+ ../../corelib/io/qfilesystemengine_win.cpp \
../../corelib/io/qfilesystemiterator_win.cpp \
../../corelib/io/qfsfileengine_win.cpp \
../../corelib/kernel/qcoreapplication_win.cpp \
@@ -107,6 +109,7 @@ mac {
../../corelib/kernel/qcoreapplication_mac.cpp \
../../corelib/kernel/qcore_mac.cpp
OBJECTIVE_SOURCES += \
+ ../../corelib/global/qoperatingsystemversion_darwin.mm \
../../corelib/kernel/qcore_mac_objc.mm \
../../corelib/kernel/qcore_foundation.mm
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index ccc6d795d7..fc1bafc7a7 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -515,7 +515,7 @@ void Generator::generateCode()
for (int i = 0; i < extraList.count(); ++i) {
fprintf(out, " &%s::staticMetaObject,\n", extraList.at(i).constData());
}
- fprintf(out, " Q_NULLPTR\n};\n\n");
+ fprintf(out, " nullptr\n};\n\n");
}
//
@@ -527,24 +527,24 @@ void Generator::generateCode()
fprintf(out, "const QMetaObject %s::staticMetaObject = {\n", cdef->qualified.constData());
if (isQObject)
- fprintf(out, " { Q_NULLPTR, ");
+ fprintf(out, " { nullptr, ");
else if (cdef->superclassList.size() && (!cdef->hasQGadget || knownGadgets.contains(purestSuperClass)))
fprintf(out, " { &%s::staticMetaObject, ", purestSuperClass.constData());
else
- fprintf(out, " { Q_NULLPTR, ");
+ fprintf(out, " { nullptr, ");
fprintf(out, "qt_meta_stringdata_%s.data,\n"
" qt_meta_data_%s, ", qualifiedClassNameIdentifier.constData(),
qualifiedClassNameIdentifier.constData());
if (hasStaticMetaCall)
fprintf(out, " qt_static_metacall, ");
else
- fprintf(out, " Q_NULLPTR, ");
+ fprintf(out, " nullptr, ");
if (extraList.isEmpty())
- fprintf(out, "Q_NULLPTR, ");
+ fprintf(out, "nullptr, ");
else
fprintf(out, "qt_meta_extradata_%s, ", qualifiedClassNameIdentifier.constData());
- fprintf(out, "Q_NULLPTR}\n};\n\n");
+ fprintf(out, "nullptr}\n};\n\n");
if(isQt)
return;
@@ -559,7 +559,7 @@ void Generator::generateCode()
// Generate smart cast function
//
fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData());
- fprintf(out, " if (!_clname) return Q_NULLPTR;\n");
+ fprintf(out, " if (!_clname) return nullptr;\n");
fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata0))\n"
" return static_cast<void*>(const_cast< %s*>(this));\n",
qualifiedClassNameIdentifier.constData(), cdef->classname.constData());
@@ -584,7 +584,7 @@ void Generator::generateCode()
QByteArray superClass = purestSuperClass;
fprintf(out, " return %s::qt_metacast(_clname);\n", superClass.constData());
} else {
- fprintf(out, " return Q_NULLPTR;\n");
+ fprintf(out, " return nullptr;\n");
}
fprintf(out, "}\n");
@@ -1481,7 +1481,7 @@ void Generator::generateSignal(FunctionDef *def,int index)
fprintf(out, "QPrivateSignal");
fprintf(out, ")%s\n{\n"
- " QMetaObject::activate(%s, &staticMetaObject, %d, Q_NULLPTR);\n"
+ " QMetaObject::activate(%s, &staticMetaObject, %d, nullptr);\n"
"}\n", constQualifier, thisPtr.constData(), index);
return;
}
@@ -1511,7 +1511,7 @@ void Generator::generateSignal(FunctionDef *def,int index)
fprintf(out, " void *_a[] = { ");
if (def->normalizedType == "void") {
- fprintf(out, "Q_NULLPTR");
+ fprintf(out, "nullptr");
} else {
if (def->returnTypeIsVolatile)
fprintf(out, "const_cast<void*>(reinterpret_cast<const volatile void*>(&_t0))");
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index 11bf8d7937..f5639ffe31 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -1005,22 +1005,20 @@ static void mergeStringLiterals(Symbols *_symbols)
}
}
-QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteArray &relativeTo)
+static QByteArray searchIncludePaths(const QList<Parser::IncludePath> &includepaths,
+ const QByteArray &include)
{
- // #### stringery
QFileInfo fi;
- if (!relativeTo.isEmpty())
- fi.setFile(QFileInfo(QString::fromLocal8Bit(relativeTo.constData())).dir(), QString::fromLocal8Bit(include.constData()));
- for (int j = 0; j < Preprocessor::includes.size() && !fi.exists(); ++j) {
- const IncludePath &p = Preprocessor::includes.at(j);
+ for (int j = 0; j < includepaths.size() && !fi.exists(); ++j) {
+ const Parser::IncludePath &p = includepaths.at(j);
if (p.isFrameworkPath) {
const int slashPos = include.indexOf('/');
if (slashPos == -1)
continue;
fi.setFile(QString::fromLocal8Bit(p.path + '/' + include.left(slashPos) + ".framework/Headers/"),
- QString::fromLocal8Bit(include.mid(slashPos + 1).constData()));
+ QString::fromLocal8Bit(include.mid(slashPos + 1)));
} else {
- fi.setFile(QString::fromLocal8Bit(p.path.constData()), QString::fromLocal8Bit(include.constData()));
+ fi.setFile(QString::fromLocal8Bit(p.path), QString::fromLocal8Bit(include));
}
// try again, maybe there's a file later in the include paths with the same name
// (186067)
@@ -1035,6 +1033,21 @@ QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteAr
return fi.canonicalFilePath().toLocal8Bit();
}
+QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteArray &relativeTo)
+{
+ if (!relativeTo.isEmpty()) {
+ QFileInfo fi;
+ fi.setFile(QFileInfo(QString::fromLocal8Bit(relativeTo)).dir(), QString::fromLocal8Bit(include));
+ if (fi.exists() && !fi.isDir())
+ return fi.canonicalFilePath().toLocal8Bit();
+ }
+
+ auto it = nonlocalIncludePathResolutionCache.find(include);
+ if (it == nonlocalIncludePathResolutionCache.end())
+ it = nonlocalIncludePathResolutionCache.insert(include, searchIncludePaths(includes, include));
+ return it.value();
+}
+
void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
{
currentFilenames.push(filename);
diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h
index a7eb1a19e1..39f56d6e92 100644
--- a/src/tools/moc/preprocessor.h
+++ b/src/tools/moc/preprocessor.h
@@ -61,6 +61,7 @@ public:
static bool preprocessOnly;
QList<QByteArray> frameworks;
QSet<QByteArray> preprocessedIncludes;
+ QHash<QByteArray, QByteArray> nonlocalIncludePathResolutionCache;
Macros macros;
QByteArray resolveInclude(const QByteArray &filename, const QByteArray &relativeTo);
Symbols preprocessed(const QByteArray &filename, QFile *device);
diff --git a/src/tools/uic/cpp/cppwriteincludes.cpp b/src/tools/uic/cpp/cppwriteincludes.cpp
index a99d6adf07..dcbe400224 100644
--- a/src/tools/uic/cpp/cppwriteincludes.cpp
+++ b/src/tools/uic/cpp/cppwriteincludes.cpp
@@ -114,8 +114,9 @@ void WriteIncludes::acceptUI(DomUI *node)
TreeWalker::acceptUI(node);
- if (!m_uic->option().includeFile.isEmpty())
- m_globalIncludes.insert(m_uic->option().includeFile, true);
+ const auto includeFile = m_uic->option().includeFile;
+ if (!includeFile.isEmpty())
+ m_globalIncludes.insert(includeFile);
writeHeaders(m_globalIncludes, true);
writeHeaders(m_localIncludes, false);
@@ -272,10 +273,11 @@ void WriteIncludes::insertInclude(const QString &header, bool global)
fprintf(stderr, "%s %s %d\n", Q_FUNC_INFO, qPrintable(header), global);
OrderedSet &includes = global ? m_globalIncludes : m_localIncludes;
- if (includes.contains(header))
+ // Insert (if not already done).
+ const bool isNewHeader = includes.insert(header).second;
+ if (!isNewHeader)
return;
- // Insert. Also remember base name for quick check of suspicious custom plugins
- includes.insert(header, false);
+ // Also remember base name for quick check of suspicious custom plugins
const QString lowerBaseName = QFileInfo(header).completeBaseName ().toLower();
m_includeBaseNames.insert(lowerBaseName);
}
@@ -286,13 +288,11 @@ void WriteIncludes::writeHeaders(const OrderedSet &headers, bool global)
const QChar closingQuote = global ? QLatin1Char('>') : QLatin1Char('"');
// Check for the old headers 'qslider.h' and replace by 'QtGui/QSlider'
- const OrderedSet::const_iterator cend = headers.constEnd();
- for (OrderedSet::const_iterator sit = headers.constBegin(); sit != cend; ++sit) {
- const StringMap::const_iterator hit = m_oldHeaderToNewHeader.constFind(sit.key());
- const bool mapped = hit != m_oldHeaderToNewHeader.constEnd();
- const QString header = mapped ? hit.value() : sit.key();
- if (!QStringRef(&header).trimmed().isEmpty())
- m_output << "#include " << openingQuote << header << closingQuote << QLatin1Char('\n');
+ for (const QString &header : headers) {
+ const QString value = m_oldHeaderToNewHeader.value(header, header);
+ const auto trimmed = QStringRef(&value).trimmed();
+ if (!trimmed.isEmpty())
+ m_output << "#include " << openingQuote << trimmed << closingQuote << QLatin1Char('\n');
}
}
diff --git a/src/tools/uic/cpp/cppwriteincludes.h b/src/tools/uic/cpp/cppwriteincludes.h
index 397c6a26e1..7a6a499536 100644
--- a/src/tools/uic/cpp/cppwriteincludes.h
+++ b/src/tools/uic/cpp/cppwriteincludes.h
@@ -35,6 +35,8 @@
#include <qset.h>
#include <qstring.h>
+#include <set>
+
QT_BEGIN_NAMESPACE
class QTextStream;
@@ -72,7 +74,7 @@ private:
void add(const QString &className, bool determineHeader = true, const QString &header = QString(), bool global = false);
private:
- typedef QMap<QString, bool> OrderedSet;
+ typedef std::set<QString> OrderedSet;
void insertIncludeForClass(const QString &className, QString header = QString(), bool global = false);
void insertInclude(const QString &header, bool global);
void writeHeaders(const OrderedSet &headers, bool global);
diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp
index e6fda103fb..bd9f0c6e01 100644
--- a/src/widgets/accessible/simplewidgets.cpp
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -468,21 +468,15 @@ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> >
QAccessibleDisplay::relations(QAccessible::Relation match /* = QAccessible::AllRelations */) const
{
QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > rels = QAccessibleWidget::relations(match);
- if (match & QAccessible::Labelled) {
- QVarLengthArray<QObject *, 4> relatedObjects;
-
#ifndef QT_NO_SHORTCUT
+ if (match & QAccessible::Labelled) {
if (QLabel *label = qobject_cast<QLabel*>(object())) {
- relatedObjects.append(label->buddy());
- }
-#endif
- for (int i = 0; i < relatedObjects.count(); ++i) {
const QAccessible::Relation rel = QAccessible::Labelled;
- QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(relatedObjects.at(i));
- if (iface)
+ if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(label->buddy()))
rels.append(qMakePair(iface, rel));
}
}
+#endif
return rels;
}
diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp
index 6df020dd58..08c5a40c7c 100644
--- a/src/widgets/dialogs/qfileinfogatherer.cpp
+++ b/src/widgets/dialogs/qfileinfogatherer.cpp
@@ -65,6 +65,18 @@ Q_AUTOTEST_EXPORT bool qt_test_isFetchedRoot()
}
#endif
+static QString translateDriveName(const QFileInfo &drive)
+{
+ QString driveName = drive.absoluteFilePath();
+#ifdef Q_OS_WIN
+ if (driveName.startsWith(QLatin1Char('/'))) // UNC host
+ return drive.fileName();
+ if (driveName.endsWith(QLatin1Char('/')))
+ driveName.chop(1);
+#endif // Q_OS_WIN
+ return driveName;
+}
+
/*!
Creates thread
*/
@@ -82,6 +94,16 @@ QFileInfoGatherer::QFileInfoGatherer(QObject *parent)
watcher = new QFileSystemWatcher(this);
connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(list(QString)));
connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateFile(QString)));
+
+# if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ const QVariant listener = watcher->property("_q_driveListener");
+ if (listener.canConvert<QObject *>()) {
+ if (QObject *driveListener = listener.value<QObject *>()) {
+ connect(driveListener, SIGNAL(driveAdded()), this, SLOT(driveAdded()));
+ connect(driveListener, SIGNAL(driveRemoved(QString)), this, SLOT(driveRemoved()));
+ }
+ }
+# endif // Q_OS_WIN && !Q_OS_WINRT
#endif
start(LowPriority);
}
@@ -106,6 +128,20 @@ void QFileInfoGatherer::setResolveSymlinks(bool enable)
#endif
}
+void QFileInfoGatherer::driveAdded()
+{
+ fetchExtendedInformation(QString(), QStringList());
+}
+
+void QFileInfoGatherer::driveRemoved()
+{
+ QStringList drives;
+ const QFileInfoList driveInfoList = QDir::drives();
+ for (const QFileInfo &fi : driveInfoList)
+ drives.append(translateDriveName(fi));
+ newListOfFiles(QString(), drives);
+}
+
bool QFileInfoGatherer::resolveSymlinks() const
{
#ifdef Q_OS_WIN
@@ -260,18 +296,6 @@ QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const
return info;
}
-static QString translateDriveName(const QFileInfo &drive)
-{
- QString driveName = drive.absoluteFilePath();
-#if defined(Q_OS_WIN)
- if (driveName.startsWith(QLatin1Char('/'))) // UNC host
- return drive.fileName();
- if (driveName.endsWith(QLatin1Char('/')))
- driveName.chop(1);
-#endif
- return driveName;
-}
-
/*
Get specific file info's, batch the files so update when we have 100
items and every 200ms after that
diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h
index 3186e9d015..0018b6c387 100644
--- a/src/widgets/dialogs/qfileinfogatherer_p.h
+++ b/src/widgets/dialogs/qfileinfogatherer_p.h
@@ -180,6 +180,10 @@ public Q_SLOTS:
void setResolveSymlinks(bool enable);
void setIconProvider(QFileIconProvider *provider);
+private Q_SLOTS:
+ void driveAdded();
+ void driveRemoved();
+
private:
void run() Q_DECL_OVERRIDE;
// called by run():
diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp
index 80e37dab25..4f6ef49a7f 100644
--- a/src/widgets/dialogs/qwizard_win.cpp
+++ b/src/widgets/dialogs/qwizard_win.cpp
@@ -49,6 +49,7 @@
#include "qwizard.h"
#include "qpaintengine.h"
#include "qapplication.h"
+#include <QtCore/QOperatingSystemVersion>
#include <QtCore/QVariant>
#include <QtCore/QDebug>
#include <QtGui/QMouseEvent>
@@ -718,7 +719,7 @@ int QVistaHelper::topOffset()
if (vistaState() != VistaAero)
return titleBarSize() + 3;
static const int aeroOffset =
- QSysInfo::WindowsVersion == QSysInfo::WV_WINDOWS7 ?
+ QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8 ?
QStyleHelper::dpiScaled(4) : QStyleHelper::dpiScaled(13);
return aeroOffset + titleBarSize();
}
diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
index 6e10d18e11..6a9036997c 100644
--- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
+++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -2575,10 +2575,12 @@ void QGraphicsAnchorLayoutPrivate::identifyFloatItems(const QSet<AnchorData *> &
for (const AnchorData *ad : visited)
identifyNonFloatItems_helper(ad, &nonFloating);
- QSet<QGraphicsLayoutItem *> allItems;
- foreach (QGraphicsLayoutItem *item, items)
- allItems.insert(item);
- m_floatItems[orientation] = allItems - nonFloating;
+ QSet<QGraphicsLayoutItem *> floatItems;
+ for (QGraphicsLayoutItem *item : qAsConst(items)) {
+ if (!nonFloating.contains(item))
+ floatItems.insert(item);
+ }
+ m_floatItems[orientation] = std::move(floatItems);
}
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp
index 0788e0287a..d19e5d9a9f 100644
--- a/src/widgets/itemviews/qlistview.cpp
+++ b/src/widgets/itemviews/qlistview.cpp
@@ -2335,13 +2335,7 @@ void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand)
bool QListModeViewBase::doBatchedItemLayout(const QListViewLayoutInfo &info, int max)
{
doStaticLayout(info);
- if (batchStartRow > max) { // stop items layout
- flowPositions.resize(flowPositions.count());
- segmentPositions.resize(segmentPositions.count());
- segmentStartRows.resize(segmentStartRows.count());
- return true; // done
- }
- return false; // not done
+ return batchStartRow > max; // returning true stops items layout
}
QListViewItem QListModeViewBase::indexToListViewItem(const QModelIndex &index) const
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 358838b4e9..1bdfcfada2 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -2455,28 +2455,20 @@ bool QApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blockingWin
for (int i = 0; i < modalWindowList.count(); ++i) {
QWindow *modalWindow = modalWindowList.at(i);
- {
- // check if the modal window is our window or a (transient) parent of our window
- QWindow *w = window;
- while (w) {
- if (w == modalWindow) {
- *blockingWindow = 0;
- return false;
- }
- QWindow *p = w->parent();
- if (!p)
- p = w->transientParent();
- w = p;
- }
-
- // Embedded in-process windows are not visible in normal parent-child chain,
- // so check the native parent chain, too.
- const QPlatformWindow *platWin = window->handle();
- const QPlatformWindow *modalPlatWin = modalWindow->handle();
- if (platWin && modalPlatWin && platWin->isEmbedded(modalPlatWin))
- return false;
+ // A window is not blocked by another modal window if the two are
+ // the same, or if the window is a child of the modal window.
+ if (window == modalWindow || modalWindow->isAncestorOf(window, QWindow::IncludeTransients)) {
+ *blockingWindow = 0;
+ return false;
}
+ // Embedded windows are not visible in normal parent-child chain,
+ // so check the native parent chain, too.
+ const QPlatformWindow *platWin = window->handle();
+ const QPlatformWindow *modalPlatWin = modalWindow->handle();
+ if (platWin && modalPlatWin && platWin->isEmbedded(modalPlatWin))
+ return false;
+
Qt::WindowModality windowModality = modalWindow->modality();
QWidgetWindow *modalWidgetWindow = qobject_cast<QWidgetWindow *>(modalWindow);
if (windowModality == Qt::NonModal) {
@@ -3558,9 +3550,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
touchEvent->setTarget(widget);
for (int i = 0; i < touchEvent->_touchPoints.size(); ++i) {
QTouchEvent::TouchPoint &pt = touchEvent->_touchPoints[i];
- QRectF rect = pt.rect();
- rect.translate(offset);
- pt.d->rect = rect;
+ pt.d->pos = pt.pos() + offset;
pt.d->startPos = pt.startPos() + offset;
pt.d->lastPos = pt.lastPos() + offset;
}
@@ -4257,12 +4247,10 @@ bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven
QTouchEvent::TouchPoint &touchPoint = touchEvent->_touchPoints[i];
// preserve the sub-pixel resolution
- QRectF rect = touchPoint.screenRect();
- const QPointF screenPos = rect.center();
+ const QPointF screenPos = touchPoint.screenRect().center();
const QPointF delta = screenPos - screenPos.toPoint();
- rect.moveCenter(widget->mapFromGlobal(screenPos.toPoint()) + delta);
- touchPoint.d->rect = rect;
+ touchPoint.d->pos = widget->mapFromGlobal(screenPos.toPoint()) + delta;
touchPoint.d->startPos = widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta;
touchPoint.d->lastPos = widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta;
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 73c75bbc14..271844a23e 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -91,12 +91,6 @@ extern Q_GUI_EXPORT bool qt_is_gui_used;
extern QClipboard *qt_clipboard;
#endif
-#if defined (Q_OS_WIN32) || defined (Q_OS_CYGWIN)
-extern QSysInfo::WinVersion qt_winver;
-#elif defined (Q_OS_MAC)
-extern QSysInfo::MacVersion qt_macver;
-#endif
-
typedef QHash<QByteArray, QFont> FontHash;
FontHash *qt_app_fonts_hash();
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index ace50f13ee..1db9f5d75e 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -10357,7 +10357,7 @@ void QWidget::updateGeometry()
a window, causing the widget to be hidden. You must call show() to make
the widget visible again..
- \sa windowType(), {Window Flags Example}
+ \sa windowType(), setWindowFlag(), {Window Flags Example}
*/
void QWidget::setWindowFlags(Qt::WindowFlags flags)
{
@@ -10365,6 +10365,23 @@ void QWidget::setWindowFlags(Qt::WindowFlags flags)
d->setWindowFlags(flags);
}
+/*!
+ \since 5.9
+
+ Sets the window flag \a flag on this widget if \a on is true;
+ otherwise clears the flag.
+
+ \sa setWindowFlags(), windowFlags(), windowType()
+*/
+void QWidget::setWindowFlag(Qt::WindowType flag, bool on)
+{
+ Q_D(QWidget);
+ if (on)
+ d->setWindowFlags(data->window_flags | flag);
+ else
+ d->setWindowFlags(data->window_flags & ~flag);
+}
+
/*! \internal
Implemented in QWidgetPrivate so that QMdiSubWindowPrivate can reimplement it.
diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h
index 58413c6bd3..4c80038a4f 100644
--- a/src/widgets/kernel/qwidget.h
+++ b/src/widgets/kernel/qwidget.h
@@ -562,6 +562,7 @@ public:
void setWindowFlags(Qt::WindowFlags type);
inline Qt::WindowFlags windowFlags() const;
+ void setWindowFlag(Qt::WindowType, bool on = true);
void overrideWindowFlags(Qt::WindowFlags type);
inline Qt::WindowType windowType() const;
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 690c811140..b75088ae50 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -4872,6 +4872,8 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
QRect decorationRect, displayRect, checkRect;
d->viewItemLayout(vopt, &checkRect, &decorationRect, &displayRect, true);
sz = (decorationRect|displayRect|checkRect).size();
+ if (decorationRect.isValid() && sz.height() == decorationRect.height())
+ sz.rheight() += 2; // Prevent icons from overlapping.
}
break;
#endif // QT_NO_ITEMVIEWS
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index 007ce20175..2d1de790c4 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -84,6 +84,7 @@
#include <qtoolbutton.h>
#include <qtreeview.h>
#include <qtableview.h>
+#include <qoperatingsystemversion.h>
#include <qwizard.h>
#include <qdebug.h>
#include <qlibrary.h>
@@ -1312,7 +1313,7 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem
bdi->adornment = kThemeAdornmentFocus;
if (combo->activeSubControls & QStyle::SC_ComboBoxArrow)
bdi->state = kThemeStatePressed;
- else if (tds == kThemeStateInactive && QSysInfo::MacintoshVersion < QSysInfo::MV_10_10)
+ else if (tds == kThemeStateInactive && QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXYosemite)
bdi->state = kThemeStateActive;
else
bdi->state = tds;
@@ -1634,7 +1635,7 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti
|| slider->tickPosition == QSlider::TicksBothSides;
tdi->bounds = qt_hirectForQRect(slider->rect);
- if (isScrollbar || QSysInfo::MacintoshVersion < QSysInfo::MV_10_10) {
+ if (isScrollbar || QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXYosemite) {
tdi->min = slider->minimum;
tdi->max = slider->maximum;
tdi->value = slider->sliderPosition;
@@ -1946,7 +1947,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD
const bool button = opt->type == QStyleOption::SO_Button;
const bool viewItem = opt->type == QStyleOption::SO_ViewItem;
const bool pressed = bdi->state == kThemeStatePressed;
- const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10;
+ const bool usingYosemiteOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite;
if (button && pressed) {
if (bdi->kind == kThemePushButton) {
@@ -3581,7 +3582,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QWindow *window = w && w->window() ? w->window()->windowHandle() :
QStyleHelper::styleObjectWindow(opt->styleObject);
const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window);
- const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10;
+ const bool usingYosemiteOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite;
switch (ce) {
case CE_HeaderSection:
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
@@ -3973,7 +3974,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
bool hasIcon = !btn.icon.isNull();
bool hasText = !btn.text.isEmpty();
- if (!hasMenu && QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) {
+ if (!hasMenu && QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite) {
if (tds == kThemeStatePressed
|| (tds == kThemeStateActive
&& ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton)
@@ -4078,8 +4079,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QStyleOptionComboBox comboCopy = *cb;
comboCopy.direction = Qt::LeftToRight;
if (opt->state & QStyle::State_Small)
- comboCopy.rect.translate(0, w ? 0 : (QSysInfo::macVersion() >= QSysInfo::MV_10_10 ? 0 : -2)); // Supports Qt Quick Controls
- else if (QSysInfo::macVersion() == QSysInfo::MV_10_9)
+ comboCopy.rect.translate(0, w ? 0 : (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite ? 0 : -2)); // Supports Qt Quick Controls
+ else if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXMavericks
+ && QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXYosemite)
comboCopy.rect.translate(0, 1);
QCommonStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w);
}
@@ -5287,7 +5289,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
QWindow *window = widget && widget->window() ? widget->window()->windowHandle() :
QStyleHelper::styleObjectWindow(opt->styleObject);
const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window);
- const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10;
+ const bool usingYosemiteOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite;
switch (cc) {
case CC_Slider:
case CC_ScrollBar:
@@ -5931,7 +5933,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
drawToolbarButtonArrow(tb->rect, tds, cg);
}
if (tb->state & State_On) {
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) {
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite) {
QWindow *window = 0;
if (widget && widget->window())
window = widget->window()->windowHandle();
@@ -6295,7 +6297,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
switch (sc) {
case SC_ComboBoxEditField:{
ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10)
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite)
ret.setHeight(ret.height() - 1);
break; }
case SC_ComboBoxArrow:{
@@ -6754,7 +6756,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
case CT_ComboBox: {
sz.rwidth() += 50;
const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt);
- if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_10 || (cb && !cb->editable))
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXYosemite || (cb && !cb->editable))
sz.rheight() += 2;
break;
}
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index 7759df9959..d6a4016e4c 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -39,6 +39,7 @@
#include "qwindowsvistastyle_p.h"
#include "qwindowsvistastyle_p_p.h"
+#include <qoperatingsystemversion.h>
#include <qscreen.h>
#include <qwindow.h>
#include <private/qstyleanimation_p.h>
@@ -1752,7 +1753,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
theme.stateId = stateId;
d->drawBackground(theme);
- if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8) {
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8) {
const QRect gripperBounds = QWindowsXPStylePrivate::scrollBarGripperBounds(flags, widget, &theme);
// Draw gripper if there is enough space
if (!gripperBounds.isEmpty() && flags & State_Enabled) {
diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp
index 224ffeb6e2..64daad87ae 100644
--- a/src/widgets/util/qsystemtrayicon.cpp
+++ b/src/widgets/util/qsystemtrayicon.cpp
@@ -59,6 +59,25 @@
QT_BEGIN_NAMESPACE
+static QIcon messageIcon2qIcon(QSystemTrayIcon::MessageIcon icon)
+{
+ QStyle::StandardPixmap stdIcon = QStyle::SP_CustomBase; // silence gcc 4.9.0 about uninited variable
+ switch (icon) {
+ case QSystemTrayIcon::Information:
+ stdIcon = QStyle::SP_MessageBoxInformation;
+ break;
+ case QSystemTrayIcon::Warning:
+ stdIcon = QStyle::SP_MessageBoxWarning;
+ break;
+ case QSystemTrayIcon::Critical:
+ stdIcon = QStyle::SP_MessageBoxCritical;
+ break;
+ case QSystemTrayIcon::NoIcon:
+ return QIcon();
+ }
+ return QApplication::style()->standardIcon(stdIcon);
+}
+
/*!
\class QSystemTrayIcon
\brief The QSystemTrayIcon class provides an icon for an application in the system tray.
@@ -382,11 +401,29 @@ bool QSystemTrayIcon::supportsMessages()
\sa show(), supportsMessages()
*/
void QSystemTrayIcon::showMessage(const QString& title, const QString& msg,
- QSystemTrayIcon::MessageIcon icon, int msecs)
+ QSystemTrayIcon::MessageIcon msgIcon, int msecs)
{
Q_D(QSystemTrayIcon);
if (d->visible)
- d->showMessage_sys(title, msg, icon, msecs);
+ d->showMessage_sys(title, msg, messageIcon2qIcon(msgIcon), msgIcon, msecs);
+}
+
+/*!
+ \fn void QSystemTrayIcon::showMessage(const QString &title, const QString &message, const QIcon &icon, int millisecondsTimeoutHint)
+
+ \overload showMessage()
+
+ Shows a balloon message for the entry with the given \a title, \a message,
+ and custom icon \a icon for the time specified in \a millisecondsTimeoutHint.
+
+ \since 5.9
+*/
+void QSystemTrayIcon::showMessage(const QString &title, const QString &msg,
+ const QIcon &icon, int msecs)
+{
+ Q_D(QSystemTrayIcon);
+ if (d->visible)
+ d->showMessage_sys(title, msg, icon, QSystemTrayIcon::NoIcon, msecs);
}
void QSystemTrayIconPrivate::_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason reason)
@@ -398,9 +435,9 @@ void QSystemTrayIconPrivate::_q_emitActivated(QPlatformSystemTrayIcon::Activatio
//////////////////////////////////////////////////////////////////////
static QBalloonTip *theSolitaryBalloonTip = 0;
-void QBalloonTip::showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title,
- const QString& message, QSystemTrayIcon *trayIcon,
- const QPoint& pos, int timeout, bool showArrow)
+void QBalloonTip::showBalloon(const QIcon &icon, const QString &title,
+ const QString &message, QSystemTrayIcon *trayIcon,
+ const QPoint &pos, int timeout, bool showArrow)
{
hideBalloon();
if (message.isEmpty() && title.isEmpty())
@@ -434,8 +471,8 @@ bool QBalloonTip::isBalloonVisible()
return theSolitaryBalloonTip;
}
-QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title,
- const QString& message, QSystemTrayIcon *ti)
+QBalloonTip::QBalloonTip(const QIcon &icon, const QString &title,
+ const QString &message, QSystemTrayIcon *ti)
: QWidget(0, Qt::ToolTip), trayIcon(ti), timerId(-1)
{
setAttribute(Qt::WA_DeleteOnClose);
@@ -482,26 +519,10 @@ QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title
msgLabel->setFixedSize(limit, msgLabel->heightForWidth(limit));
}
- QIcon si;
- switch (icon) {
- case QSystemTrayIcon::Warning:
- si = style()->standardIcon(QStyle::SP_MessageBoxWarning);
- break;
- case QSystemTrayIcon::Critical:
- si = style()->standardIcon(QStyle::SP_MessageBoxCritical);
- break;
- case QSystemTrayIcon::Information:
- si = style()->standardIcon(QStyle::SP_MessageBoxInformation);
- break;
- case QSystemTrayIcon::NoIcon:
- default:
- break;
- }
-
QGridLayout *layout = new QGridLayout;
- if (!si.isNull()) {
+ if (!icon.isNull()) {
QLabel *iconLabel = new QLabel;
- iconLabel->setPixmap(si.pixmap(iconSize, iconSize));
+ iconLabel->setPixmap(icon.pixmap(iconSize, iconSize));
iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
iconLabel->setMargin(2);
layout->addWidget(iconLabel, 0, 0);
@@ -678,52 +699,6 @@ void QSystemTrayIconPrivate::remove_sys_qpa()
qpa_sys->cleanup();
}
-QRect QSystemTrayIconPrivate::geometry_sys_qpa() const
-{
- return qpa_sys->geometry();
-}
-
-void QSystemTrayIconPrivate::updateIcon_sys_qpa()
-{
- qpa_sys->updateIcon(icon);
-}
-
-void QSystemTrayIconPrivate::updateMenu_sys_qpa()
-{
- if (menu) {
- addPlatformMenu(menu);
- qpa_sys->updateMenu(menu->platformMenu());
- }
-}
-
-void QSystemTrayIconPrivate::updateToolTip_sys_qpa()
-{
- qpa_sys->updateToolTip(toolTip);
-}
-
-void QSystemTrayIconPrivate::showMessage_sys_qpa(const QString &title,
- const QString &message,
- QSystemTrayIcon::MessageIcon icon,
- int msecs)
-{
- QIcon notificationIcon;
- switch (icon) {
- case QSystemTrayIcon::Information:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
- break;
- case QSystemTrayIcon::Warning:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
- break;
- case QSystemTrayIcon::Critical:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
- break;
- default:
- break;
- }
- qpa_sys->showMessage(title, message, notificationIcon,
- static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs);
-}
-
void QSystemTrayIconPrivate::addPlatformMenu(QMenu *menu) const
{
if (menu->platformMenu())
diff --git a/src/widgets/util/qsystemtrayicon.h b/src/widgets/util/qsystemtrayicon.h
index fb238c92b0..918dd0478e 100644
--- a/src/widgets/util/qsystemtrayicon.h
+++ b/src/widgets/util/qsystemtrayicon.h
@@ -101,6 +101,7 @@ public Q_SLOTS:
void setVisible(bool visible);
inline void show() { setVisible(true); }
inline void hide() { setVisible(false); }
+ void showMessage(const QString &title, const QString &msg, const QIcon &icon, int msecs = 10000);
void showMessage(const QString &title, const QString &msg,
QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::Information, int msecs = 10000);
diff --git a/src/widgets/util/qsystemtrayicon_p.h b/src/widgets/util/qsystemtrayicon_p.h
index 79e824f4b7..3f5cab40be 100644
--- a/src/widgets/util/qsystemtrayicon_p.h
+++ b/src/widgets/util/qsystemtrayicon_p.h
@@ -84,7 +84,8 @@ public:
void updateToolTip_sys();
void updateMenu_sys();
QRect geometry_sys() const;
- void showMessage_sys(const QString &title, const QString &msg, QSystemTrayIcon::MessageIcon icon, int secs);
+ void showMessage_sys(const QString &title, const QString &msg, const QIcon &icon,
+ QSystemTrayIcon::MessageIcon msgIcon, int msecs);
static bool isSystemTrayAvailable_sys();
static bool supportsMessages_sys();
@@ -101,11 +102,7 @@ public:
private:
void install_sys_qpa();
void remove_sys_qpa();
- void updateIcon_sys_qpa();
- void updateToolTip_sys_qpa();
- void updateMenu_sys_qpa();
- QRect geometry_sys_qpa() const;
- void showMessage_sys_qpa(const QString &title, const QString &msg, QSystemTrayIcon::MessageIcon icon, int secs);
+
void addPlatformMenu(QMenu *menu) const;
};
@@ -113,16 +110,16 @@ class QBalloonTip : public QWidget
{
Q_OBJECT
public:
- static void showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title,
- const QString& msg, QSystemTrayIcon *trayIcon,
- const QPoint& pos, int timeout, bool showArrow = true);
+ static void showBalloon(const QIcon &icon, const QString &title,
+ const QString &msg, QSystemTrayIcon *trayIcon,
+ const QPoint &pos, int timeout, bool showArrow = true);
static void hideBalloon();
static bool isBalloonVisible();
static void updateBalloonPosition(const QPoint& pos);
private:
- QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title,
- const QString& msg, QSystemTrayIcon *trayIcon);
+ QBalloonTip(const QIcon &icon, const QString &title,
+ const QString &msg, QSystemTrayIcon *trayIcon);
~QBalloonTip();
void balloon(const QPoint&, int, bool);
diff --git a/src/widgets/util/qsystemtrayicon_qpa.cpp b/src/widgets/util/qsystemtrayicon_qpa.cpp
index 643f17a5fe..8399732a4a 100644
--- a/src/widgets/util/qsystemtrayicon_qpa.cpp
+++ b/src/widgets/util/qsystemtrayicon_qpa.cpp
@@ -76,7 +76,7 @@ void QSystemTrayIconPrivate::remove_sys()
QRect QSystemTrayIconPrivate::geometry_sys() const
{
if (qpa_sys)
- return geometry_sys_qpa();
+ return qpa_sys->geometry();
else
return QRect();
}
@@ -84,19 +84,21 @@ QRect QSystemTrayIconPrivate::geometry_sys() const
void QSystemTrayIconPrivate::updateIcon_sys()
{
if (qpa_sys)
- updateIcon_sys_qpa();
+ qpa_sys->updateIcon(icon);
}
void QSystemTrayIconPrivate::updateMenu_sys()
{
- if (qpa_sys)
- updateMenu_sys_qpa();
+ if (qpa_sys && menu) {
+ addPlatformMenu(menu);
+ qpa_sys->updateMenu(menu->platformMenu());
+ }
}
void QSystemTrayIconPrivate::updateToolTip_sys()
{
if (qpa_sys)
- updateToolTip_sys_qpa();
+ qpa_sys->updateToolTip(toolTip);
}
bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
@@ -118,10 +120,11 @@ bool QSystemTrayIconPrivate::supportsMessages_sys()
}
void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message,
- QSystemTrayIcon::MessageIcon icon, int msecs)
+ const QIcon &icon, QSystemTrayIcon::MessageIcon msgIcon, int msecs)
{
if (qpa_sys)
- showMessage_sys_qpa(title, message, icon, msecs);
+ qpa_sys->showMessage(title, message, icon,
+ static_cast<QPlatformSystemTrayIcon::MessageIcon>(msgIcon), msecs);
}
QT_END_NAMESPACE
diff --git a/src/widgets/util/qsystemtrayicon_win.cpp b/src/widgets/util/qsystemtrayicon_win.cpp
index 2da24e482b..638d2050fb 100644
--- a/src/widgets/util/qsystemtrayicon_win.cpp
+++ b/src/widgets/util/qsystemtrayicon_win.cpp
@@ -81,11 +81,14 @@ struct Q_NOTIFYICONIDENTIFIER {
# define NIN_BALLOONTIMEOUT (WM_USER + 4)
# define NIN_BALLOONUSERCLICK (WM_USER + 5)
# define NIF_SHOWTIP 0x00000080
+# define NIIF_LARGE_ICON 0x00000020
# define NOTIFYICON_VERSION_4 4
#endif
#define Q_MSGFLT_ALLOW 1
+Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
+
typedef HRESULT (WINAPI *PtrShell_NotifyIconGetRect)(const Q_NOTIFYICONIDENTIFIER* identifier, RECT* iconLocation);
typedef BOOL (WINAPI *PtrChangeWindowMessageFilter)(UINT message, DWORD dwFlag);
typedef BOOL (WINAPI *PtrChangeWindowMessageFilterEx)(HWND hWnd, UINT message, DWORD action, void* pChangeFilterStruct);
@@ -107,7 +110,7 @@ public:
~QSystemTrayIconSys();
bool trayMessage(DWORD msg);
void setIconContents(NOTIFYICONDATA &data);
- bool showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs);
+ bool showMessage(const QString &title, const QString &message, const QIcon &icon, uint uSecs);
QRect findIconGeometry(UINT iconId);
HICON createIcon();
bool winEvent(MSG *m, long *result);
@@ -184,7 +187,7 @@ static inline HWND createTrayIconMessageWindow()
QSystemTrayIconSys::QSystemTrayIconSys(HWND hwnd, QSystemTrayIcon *object)
: m_hwnd(hwnd), hIcon(0), q(object)
- , notifyIconSize(NOTIFYICONDATA_V2_SIZE), version(NOTIFYICON_VERSION)
+ , notifyIconSize(sizeof(NOTIFYICONDATA)), version(NOTIFYICON_VERSION_4)
, ignoreNextMouseRelease(false)
{
@@ -237,11 +240,7 @@ void QSystemTrayIconSys::setIconContents(NOTIFYICONDATA &tnd)
qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip)/sizeof(wchar_t));
}
-#ifndef NIIF_LARGE_ICON
-# define NIIF_LARGE_ICON 0x00000020
-#endif
-
-bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs)
+bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, const QIcon &icon, uint uSecs)
{
NOTIFYICONDATA tnd;
memset(&tnd, 0, notifyIconSize);
@@ -249,23 +248,32 @@ bool QSystemTrayIconSys::showMessage(const QString &title, const QString &messag
qStringToLimitedWCharArray(title, tnd.szInfoTitle, 64);
tnd.uID = q_uNOTIFYICONID;
- switch (type) {
- case QSystemTrayIcon::Information:
+ tnd.dwInfoFlags = NIIF_USER;
+
+ HICON *phIcon = &tnd.hIcon;
+ QSize size(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
+ if (version == NOTIFYICON_VERSION_4) {
+ const QSize largeIcon(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
+ QSize more = icon.actualSize(largeIcon);
+ if (more.height() > (largeIcon.height() * 3/4) || more.width() > (largeIcon.width() * 3/4)) {
+ tnd.dwInfoFlags |= NIIF_LARGE_ICON;
+ size = largeIcon;
+ }
+ phIcon = &tnd.hBalloonIcon;
+ }
+ QPixmap pm = icon.pixmap(size);
+ if (pm.isNull()) {
tnd.dwInfoFlags = NIIF_INFO;
- break;
- case QSystemTrayIcon::Warning:
- tnd.dwInfoFlags = NIIF_WARNING;
- break;
- case QSystemTrayIcon::Critical:
- tnd.dwInfoFlags = NIIF_ERROR;
- break;
- case QSystemTrayIcon::NoIcon:
- tnd.dwInfoFlags = hIcon ? NIIF_USER : NIIF_NONE;
- break;
+ } else {
+ if (pm.size() != size) {
+ qWarning("QSystemTrayIcon::showMessage: Wrong icon size (%dx%d), please add standard one: %dx%d",
+ pm.size().width(), pm.size().height(), size.width(), size.height());
+ pm = pm.scaled(size, Qt::IgnoreAspectRatio);
+ }
+ *phIcon = qt_pixmapToWinHICON(pm);
}
- if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
- tnd.dwInfoFlags |= NIIF_LARGE_ICON;
tnd.cbSize = notifyIconSize;
+ tnd.uVersion = version;
tnd.hWnd = m_hwnd;
tnd.uTimeout = uSecs;
tnd.uFlags = NIF_INFO | NIF_SHOWTIP;
@@ -296,8 +304,6 @@ bool QSystemTrayIconSys::trayMessage(DWORD msg)
return success;
}
-Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
-
HICON QSystemTrayIconSys::createIcon()
{
const HICON oldIcon = hIcon;
@@ -509,7 +515,8 @@ QRect QSystemTrayIconSys::findIconGeometry(UINT iconId)
void QSystemTrayIconPrivate::showMessage_sys(const QString &title,
const QString &messageIn,
- QSystemTrayIcon::MessageIcon type,
+ const QIcon &icon,
+ QSystemTrayIcon::MessageIcon,
int timeOut)
{
if (!sys || !allowsMessages())
@@ -522,7 +529,7 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &title,
if (message.isEmpty() && !title.isEmpty())
message.append(QLatin1Char(' '));
- sys->showMessage(title, message, type, uSecs);
+ sys->showMessage(title, message, icon, uSecs);
}
QRect QSystemTrayIconPrivate::geometry_sys() const
diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp
index ea0604b6ed..20ab0f6377 100644
--- a/src/widgets/util/qsystemtrayicon_x11.cpp
+++ b/src/widgets/util/qsystemtrayicon_x11.cpp
@@ -284,7 +284,7 @@ void QSystemTrayIconPrivate::install_sys()
QRect QSystemTrayIconPrivate::geometry_sys() const
{
if (qpa_sys)
- return geometry_sys_qpa();
+ return qpa_sys->geometry();
if (!sys)
return QRect();
return sys->globalGeometry();
@@ -307,7 +307,7 @@ void QSystemTrayIconPrivate::remove_sys()
void QSystemTrayIconPrivate::updateIcon_sys()
{
if (qpa_sys) {
- updateIcon_sys_qpa();
+ qpa_sys->updateIcon(icon);
return;
}
if (sys)
@@ -316,14 +316,16 @@ void QSystemTrayIconPrivate::updateIcon_sys()
void QSystemTrayIconPrivate::updateMenu_sys()
{
- if (qpa_sys)
- updateMenu_sys_qpa();
+ if (qpa_sys && menu) {
+ addPlatformMenu(menu);
+ qpa_sys->updateMenu(menu->platformMenu());
+ }
}
void QSystemTrayIconPrivate::updateToolTip_sys()
{
if (qpa_sys) {
- updateToolTip_sys_qpa();
+ qpa_sys->updateToolTip(toolTip);
return;
}
if (!sys)
@@ -357,10 +359,11 @@ bool QSystemTrayIconPrivate::supportsMessages_sys()
}
void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message,
- QSystemTrayIcon::MessageIcon icon, int msecs)
+ const QIcon &icon, QSystemTrayIcon::MessageIcon msgIcon, int msecs)
{
if (qpa_sys) {
- showMessage_sys_qpa(title, message, icon, msecs);
+ qpa_sys->showMessage(title, message, icon,
+ static_cast<QPlatformSystemTrayIcon::MessageIcon>(msgIcon), msecs);
return;
}
if (!sys)
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 63fe09f77e..6b0c2fd621 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -1492,6 +1492,7 @@ bool QMenuBar::eventFilter(QObject *object, QEvent *event)
case QEvent::FocusIn:
case QEvent::FocusOut:
case QEvent::ActivationChange:
+ case QEvent::Shortcut:
d->altPressed = false;
qApp->removeEventFilter(this);
break;
diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp
index 910904e96e..77a793e951 100644
--- a/src/widgets/widgets/qsplitter.cpp
+++ b/src/widgets/widgets/qsplitter.cpp
@@ -731,6 +731,12 @@ void QSplitterPrivate::setSizes_helper(const QList<int> &sizes, bool clampNegati
doResize();
}
+bool QSplitterPrivate::shouldShowWidget(const QWidget *w) const
+{
+ Q_Q(const QSplitter);
+ return q->isVisible() && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide));
+}
+
void QSplitterPrivate::setGeo(QSplitterLayoutStruct *sls, int p, int s, bool allowCollapse)
{
Q_Q(QSplitter);
@@ -827,8 +833,7 @@ void QSplitterPrivate::insertWidget_helper(int index, QWidget *widget, bool show
{
Q_Q(QSplitter);
QBoolBlocker b(blockChildAdd);
- bool needShow = show && q->isVisible() &&
- !(widget->isHidden() && widget->testAttribute(Qt::WA_WState_ExplicitShowHide));
+ const bool needShow = show && shouldShowWidget(widget);
if (widget->parentWidget() != q)
widget->setParent(q);
if (needShow)
@@ -1125,6 +1130,66 @@ void QSplitter::insertWidget(int index, QWidget *widget)
}
/*!
+ \since 5.9
+
+ Replaces the widget in the splitter's layout at the given \a index by \a widget.
+
+ Returns the widget that has just been replaced if \a index is valid and \a widget
+ is not already a child of the splitter. Otherwise, it returns null and no replacement
+ or addition is made.
+
+ The geometry of the newly inserted widget will be the same as the widget it replaces.
+ Its visible and collapsed states are also inherited.
+
+ \note The splitter takes ownership of \a widget and sets the parent of the
+ replaced widget to null.
+
+ \sa insertWidget(), indexOf()
+*/
+QWidget *QSplitter::replaceWidget(int index, QWidget *widget)
+{
+ Q_D(QSplitter);
+ if (!widget) {
+ qWarning("QSplitter::replaceWidget: Widget can't be null");
+ return nullptr;
+ }
+
+ if (index < 0 || index >= d->list.count()) {
+ qWarning("QSplitter::replaceWidget: Index %d out of range", index);
+ return nullptr;
+ }
+
+ QSplitterLayoutStruct *s = d->list.at(index);
+ QWidget *current = s->widget;
+ if (current == widget) {
+ qWarning("QSplitter::replaceWidget: Trying to replace a widget with itself");
+ return nullptr;
+ }
+
+ if (widget->parentWidget() == this) {
+ qWarning("QSplitter::replaceWidget: Trying to replace a widget with one of its siblings");
+ return nullptr;
+ }
+
+ QBoolBlocker b(d->blockChildAdd);
+
+ const QRect geom = current->geometry();
+ const bool shouldShow = d->shouldShowWidget(current);
+
+ s->widget = widget;
+ current->setParent(nullptr);
+ widget->setParent(this);
+
+ // The splitter layout struct's geometry is already set and
+ // should not change. Only set the geometry on the new widget
+ widget->setGeometry(geom);
+ widget->lower();
+ widget->setVisible(shouldShow);
+
+ return current;
+}
+
+/*!
\fn int QSplitter::indexOf(QWidget *widget) const
Returns the index in the splitter's layout of the specified \a widget. This
@@ -1232,7 +1297,7 @@ void QSplitter::childEvent(QChildEvent *c)
if (c->added() && !d->blockChildAdd && !d->findWidget(w)) {
d->insertWidget_helper(d->list.count(), w, false);
} else if (c->polished() && !d->blockChildAdd) {
- if (isVisible() && !(w->isHidden() && w->testAttribute(Qt::WA_WState_ExplicitShowHide)))
+ if (d->shouldShowWidget(w))
w->show();
} else if (c->type() == QEvent::ChildRemoved) {
for (int i = 0; i < d->list.size(); ++i) {
diff --git a/src/widgets/widgets/qsplitter.h b/src/widgets/widgets/qsplitter.h
index 9cfde9fed3..e9ef3c3f2d 100644
--- a/src/widgets/widgets/qsplitter.h
+++ b/src/widgets/widgets/qsplitter.h
@@ -71,6 +71,7 @@ public:
void addWidget(QWidget *widget);
void insertWidget(int index, QWidget *widget);
+ QWidget *replaceWidget(int index, QWidget *widget);
void setOrientation(Qt::Orientation);
Qt::Orientation orientation() const;
diff --git a/src/widgets/widgets/qsplitter_p.h b/src/widgets/widgets/qsplitter_p.h
index 4422d9a8a4..07b43e56b8 100644
--- a/src/widgets/widgets/qsplitter_p.h
+++ b/src/widgets/widgets/qsplitter_p.h
@@ -125,6 +125,7 @@ public:
int findWidgetJustBeforeOrJustAfter(int index, int delta, int &collapsibleSize) const;
void updateHandles();
void setSizes_helper(const QList<int> &sizes, bool clampNegativeSize = false);
+ bool shouldShowWidget(const QWidget *w) const;
};