summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro16
-rw-r--r--src/3rdparty/iaccessible2/generated/amd64/ia2_api_all.h5
-rw-r--r--src/3rdparty/iaccessible2/generated/amd64/ia2_api_all_i.c7
-rw-r--r--src/3rdparty/iaccessible2/generated/x86/ia2_api_all.h4
-rw-r--r--src/3rdparty/iaccessible2/generated/x86/ia2_api_all_i.c6
-rw-r--r--src/3rdparty/icc/LICENSE.txt10
-rw-r--r--src/3rdparty/icc/qt_attribution.json15
-rw-r--r--src/3rdparty/icc/sRGB2014.iccbin0 -> 3024 bytes
-rw-r--r--src/3rdparty/pcre2/AUTHORS6
-rw-r--r--src/3rdparty/pcre2/LICENCE27
-rw-r--r--src/3rdparty/pcre2/qt_attribution.json6
-rw-r--r--src/3rdparty/pcre2/src/config.h3
-rw-r--r--src/3rdparty/pcre2/src/pcre2.h374
-rw-r--r--src/3rdparty/pcre2/src/pcre2_auto_possess.c26
-rw-r--r--src/3rdparty/pcre2/src/pcre2_compile.c11755
-rw-r--r--src/3rdparty/pcre2/src/pcre2_config.c24
-rw-r--r--src/3rdparty/pcre2/src/pcre2_context.c119
-rw-r--r--src/3rdparty/pcre2/src/pcre2_dfa_match.c441
-rw-r--r--src/3rdparty/pcre2/src/pcre2_error.c41
-rw-r--r--src/3rdparty/pcre2/src/pcre2_find_bracket.c2
-rw-r--r--src/3rdparty/pcre2/src/pcre2_internal.h158
-rw-r--r--src/3rdparty/pcre2/src/pcre2_intmodedep.h180
-rw-r--r--src/3rdparty/pcre2/src/pcre2_jit_compile.c3276
-rw-r--r--src/3rdparty/pcre2/src/pcre2_jit_match.c8
-rw-r--r--src/3rdparty/pcre2/src/pcre2_match.c8429
-rw-r--r--src/3rdparty/pcre2/src/pcre2_match_data.c6
-rw-r--r--src/3rdparty/pcre2/src/pcre2_ord2utf.c2
-rw-r--r--src/3rdparty/pcre2/src/pcre2_pattern_info.c32
-rw-r--r--src/3rdparty/pcre2/src/pcre2_serialize.c5
-rw-r--r--src/3rdparty/pcre2/src/pcre2_study.c192
-rw-r--r--src/3rdparty/pcre2/src/pcre2_substitute.c14
-rw-r--r--src/3rdparty/pcre2/src/pcre2_tables.c448
-rw-r--r--src/3rdparty/pcre2/src/pcre2_ucd.c5447
-rw-r--r--src/3rdparty/pcre2/src/pcre2_ucp.h44
-rw-r--r--src/3rdparty/pcre2/src/pcre2_valid_utf.c14
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitConfig.h14
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h77
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitExecAllocator.c12
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitLir.c559
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitLir.h639
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeARM_32.c1210
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeARM_64.c224
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c845
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_32.c267
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_64.c270
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeMIPS_common.c555
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativePPC_32.c115
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativePPC_64.c162
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativePPC_common.c462
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeSPARC_32.c27
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeSPARC_common.c152
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeTILEGX-encoder.c2
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeTILEGX_64.c38
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeX86_32.c154
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeX86_64.c147
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitNativeX86_common.c774
-rw-r--r--src/3rdparty/pcre2/src/sljit/sljitUtils.c69
-rw-r--r--src/3rdparty/sqlite.pri2
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java33
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java44
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java1
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java8
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java72
-rw-r--r--src/android/templates/AndroidManifest.xml2
-rw-r--r--src/corelib/codecs/qtextcodec.cpp49
-rw-r--r--src/corelib/codecs/qtextcodec.h13
-rw-r--r--src/corelib/configure.json87
-rw-r--r--src/corelib/corelib.pro2
-rw-r--r--src/corelib/debug_script.py98
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qpair.cpp7
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qlocale.cpp17
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp5
-rw-r--r--src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp16
-rw-r--r--src/corelib/doc/snippets/qstring/main.cpp17
-rw-r--r--src/corelib/doc/snippets/qversionnumber/main.cpp8
-rw-r--r--src/corelib/doc/snippets/signalmapper/filereader.cpp117
-rw-r--r--src/corelib/doc/src/objectmodel/signalsandslots.qdoc22
-rw-r--r--src/corelib/global/global.pri20
-rw-r--r--src/corelib/global/minimum-linux.S106
-rw-r--r--src/corelib/global/qconfig-bootstrapped.h7
-rw-r--r--src/corelib/global/qendian.h235
-rw-r--r--src/corelib/global/qendian.qdoc369
-rw-r--r--src/corelib/global/qendian_p.h142
-rw-r--r--src/corelib/global/qfloat16.cpp24
-rw-r--r--src/corelib/global/qglobal.cpp307
-rw-r--r--src/corelib/global/qglobal.h48
-rw-r--r--src/corelib/global/qlogging.cpp28
-rw-r--r--src/corelib/global/qnamespace.h10
-rw-r--r--src/corelib/global/qnamespace.qdoc25
-rw-r--r--src/corelib/global/qnumeric.h18
-rw-r--r--src/corelib/global/qnumeric_p.h54
-rw-r--r--src/corelib/global/qrandom.cpp1050
-rw-r--r--src/corelib/global/qrandom.h154
-rw-r--r--src/corelib/global/qrandom_p.h (renamed from src/corelib/tools/qpodlist_p.h)71
-rw-r--r--src/corelib/global/qtypeinfo.h10
-rw-r--r--src/corelib/io/io.pri8
-rw-r--r--src/corelib/io/qabstractfileengine.cpp47
-rw-r--r--src/corelib/io/qabstractfileengine_p.h9
-rw-r--r--src/corelib/io/qdatastream.cpp32
-rw-r--r--src/corelib/io/qdatastream.h5
-rw-r--r--src/corelib/io/qdebug.cpp15
-rw-r--r--src/corelib/io/qdebug.h3
-rw-r--r--src/corelib/io/qfile.cpp122
-rw-r--r--src/corelib/io/qfile.h1
-rw-r--r--src/corelib/io/qfiledevice.cpp70
-rw-r--r--src/corelib/io/qfiledevice.h11
-rw-r--r--src/corelib/io/qfileinfo.cpp341
-rw-r--r--src/corelib/io/qfileinfo.h11
-rw-r--r--src/corelib/io/qfileinfo_p.h48
-rw-r--r--src/corelib/io/qfilesystemengine.cpp226
-rw-r--r--src/corelib/io/qfilesystemengine_p.h10
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp893
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp317
-rw-r--r--src/corelib/io/qfilesystementry.cpp5
-rw-r--r--src/corelib/io/qfilesystementry_p.h5
-rw-r--r--src/corelib/io/qfilesystemmetadata_p.h60
-rw-r--r--src/corelib/io/qfsfileengine.cpp35
-rw-r--r--src/corelib/io/qfsfileengine_p.h2
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp148
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp58
-rw-r--r--src/corelib/io/qiodevice.cpp122
-rw-r--r--src/corelib/io/qiodevice.h1
-rw-r--r--src/corelib/io/qiodevice_p.h3
-rw-r--r--src/corelib/io/qlockfile_unix.cpp12
-rw-r--r--src/corelib/io/qprocess.cpp99
-rw-r--r--src/corelib/io/qprocess.h1
-rw-r--r--src/corelib/io/qprocess_p.h6
-rw-r--r--src/corelib/io/qprocess_unix.cpp129
-rw-r--r--src/corelib/io/qprocess_win.cpp127
-rw-r--r--src/corelib/io/qresource.cpp50
-rw-r--r--src/corelib/io/qsavefile.cpp39
-rw-r--r--src/corelib/io/qsettings.cpp80
-rw-r--r--src/corelib/io/qsettings.h2
-rw-r--r--src/corelib/io/qsettings_p.h3
-rw-r--r--src/corelib/io/qstandardpaths.cpp6
-rw-r--r--src/corelib/io/qstandardpaths_unix.cpp8
-rw-r--r--src/corelib/io/qstandardpaths_win.cpp10
-rw-r--r--src/corelib/io/qstorageinfo.cpp35
-rw-r--r--src/corelib/io/qstorageinfo.h7
-rw-r--r--src/corelib/io/qtemporarydir.cpp83
-rw-r--r--src/corelib/io/qtemporaryfile.cpp502
-rw-r--r--src/corelib/io/qtemporaryfile.h4
-rw-r--r--src/corelib/io/qtemporaryfile_p.h52
-rw-r--r--src/corelib/io/qtextstream.cpp3
-rw-r--r--src/corelib/io/qtldurl.cpp42
-rw-r--r--src/corelib/io/qwindowspipereader.cpp13
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp8
-rw-r--r--src/corelib/io/qwindowspipewriter_p.h1
-rw-r--r--src/corelib/io/qwinoverlappedionotifier.cpp428
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp385
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.h4
-rw-r--r--src/corelib/itemmodels/qstringlistmodel.cpp2
-rw-r--r--src/corelib/json/qjson.cpp13
-rw-r--r--src/corelib/json/qjson_p.h129
-rw-r--r--src/corelib/json/qjsonarray.cpp21
-rw-r--r--src/corelib/json/qjsonarray.h22
-rw-r--r--src/corelib/json/qjsondocument.cpp74
-rw-r--r--src/corelib/json/qjsondocument.h23
-rw-r--r--src/corelib/json/qjsonobject.cpp22
-rw-r--r--src/corelib/json/qjsonobject.h21
-rw-r--r--src/corelib/json/qjsonvalue.cpp78
-rw-r--r--src/corelib/json/qjsonvalue.h29
-rw-r--r--src/corelib/kernel/kernel.pri3
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp3
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.h2
-rw-r--r--src/corelib/kernel/qcore_mac.cpp10
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm145
-rw-r--r--src/corelib/kernel/qcore_mac_p.h60
-rw-r--r--src/corelib/kernel/qcore_unix.cpp33
-rw-r--r--src/corelib/kernel/qcore_unix_p.h24
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp123
-rw-r--r--src/corelib/kernel/qcoreapplication.h1
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h6
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp60
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h1
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp67
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h2
-rw-r--r--src/corelib/kernel/qfunctions_fake_env_p.h2
-rw-r--r--src/corelib/kernel/qjnihelpers.cpp40
-rw-r--r--src/corelib/kernel/qjnihelpers_p.h16
-rw-r--r--src/corelib/kernel/qmath.h24
-rw-r--r--src/corelib/kernel/qmath.qdoc19
-rw-r--r--src/corelib/kernel/qmetaobject.cpp99
-rw-r--r--src/corelib/kernel/qmetaobject_p.h3
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp36
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h3
-rw-r--r--src/corelib/kernel/qmetatype.cpp1
-rw-r--r--src/corelib/kernel/qmetatype.h47
-rw-r--r--src/corelib/kernel/qobject.cpp2
-rw-r--r--src/corelib/kernel/qobject.h4
-rw-r--r--src/corelib/kernel/qobject_impl.h78
-rw-r--r--src/corelib/kernel/qobject_p.h3
-rw-r--r--src/corelib/kernel/qobjectdefs.h89
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h94
-rw-r--r--src/corelib/kernel/qsignalmapper.cpp8
-rw-r--r--src/corelib/kernel/qsignalmapper.h6
-rw-r--r--src/corelib/kernel/qtimer.h8
-rw-r--r--src/corelib/kernel/qvariant.cpp162
-rw-r--r--src/corelib/kernel/qvariant_p.h10
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp60
-rw-r--r--src/corelib/kernel/qwineventnotifier_p.h (renamed from src/corelib/io/qwinoverlappedionotifier_p.h)47
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp8
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h2
-rw-r--r--src/corelib/mimetypes/qmimetype.cpp90
-rw-r--r--src/corelib/mimetypes/qmimetype.h18
-rw-r--r--src/corelib/mimetypes/qmimetypeparser.cpp1
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp8
-rw-r--r--src/corelib/plugin/quuid.cpp313
-rw-r--r--src/corelib/plugin/quuid.h3
-rw-r--r--src/corelib/thread/qmutex.cpp2
-rw-r--r--src/corelib/thread/qresultstore.h2
-rw-r--r--src/corelib/thread/qsemaphore.cpp153
-rw-r--r--src/corelib/thread/qsemaphore.h39
-rw-r--r--src/corelib/thread/qthread.cpp47
-rw-r--r--src/corelib/thread/qthread.h124
-rw-r--r--src/corelib/thread/qthread_p.h4
-rw-r--r--src/corelib/thread/qthread_unix.cpp151
-rw-r--r--src/corelib/thread/qthread_win.cpp4
-rw-r--r--src/corelib/thread/qthreadpool.cpp35
-rw-r--r--src/corelib/thread/qthreadpool.h4
-rw-r--r--src/corelib/thread/qthreadpool_p.h12
-rw-r--r--src/corelib/tools/qbytearray.cpp100
-rw-r--r--src/corelib/tools/qbytearray.h85
-rw-r--r--src/corelib/tools/qchar.cpp23
-rw-r--r--src/corelib/tools/qchar.h7
-rw-r--r--src/corelib/tools/qcryptographichash.cpp59
-rw-r--r--src/corelib/tools/qcryptographichash.h7
-rw-r--r--src/corelib/tools/qdatetime.cpp214
-rw-r--r--src/corelib/tools/qdatetime.h29
-rw-r--r--src/corelib/tools/qdatetimeparser.cpp1005
-rw-r--r--src/corelib/tools/qdatetimeparser_p.h40
-rw-r--r--src/corelib/tools/qhash.cpp178
-rw-r--r--src/corelib/tools/qhash.h11
-rw-r--r--src/corelib/tools/qhashfunctions.h8
-rw-r--r--src/corelib/tools/qiterator.h151
-rw-r--r--src/corelib/tools/qlinkedlist.h4
-rw-r--r--src/corelib/tools/qlist.h6
-rw-r--r--src/corelib/tools/qlocale.cpp441
-rw-r--r--src/corelib/tools/qlocale.h36
-rw-r--r--src/corelib/tools/qlocale.qdoc2
-rw-r--r--src/corelib/tools/qlocale_data_p.h9174
-rw-r--r--src/corelib/tools/qlocale_mac.mm4
-rw-r--r--src/corelib/tools/qlocale_p.h62
-rw-r--r--src/corelib/tools/qlocale_win.cpp6
-rw-r--r--src/corelib/tools/qmap.cpp67
-rw-r--r--src/corelib/tools/qmap.h10
-rw-r--r--src/corelib/tools/qmessageauthenticationcode.cpp4
-rw-r--r--src/corelib/tools/qrect.h2
-rw-r--r--src/corelib/tools/qregularexpression.cpp172
-rw-r--r--src/corelib/tools/qregularexpression.h15
-rw-r--r--src/corelib/tools/qringbuffer_p.h2
-rw-r--r--src/corelib/tools/qscopedpointer.cpp6
-rw-r--r--src/corelib/tools/qscopedpointer.h13
-rw-r--r--src/corelib/tools/qsimd_p.h10
-rw-r--r--src/corelib/tools/qstring.cpp1448
-rw-r--r--src/corelib/tools/qstring.h243
-rw-r--r--src/corelib/tools/qstringalgorithms.h84
-rw-r--r--src/corelib/tools/qstringalgorithms_p.h8
-rw-r--r--src/corelib/tools/qstringbuilder.h7
-rw-r--r--src/corelib/tools/qstringiterator.qdoc8
-rw-r--r--src/corelib/tools/qstringiterator_p.h10
-rw-r--r--src/corelib/tools/qstringlist.cpp34
-rw-r--r--src/corelib/tools/qstringlist.h7
-rw-r--r--src/corelib/tools/qstringliteral.h128
-rw-r--r--src/corelib/tools/qstringview.cpp777
-rw-r--r--src/corelib/tools/qstringview.h307
-rw-r--r--src/corelib/tools/qtimezone.cpp7
-rw-r--r--src/corelib/tools/qtimezone.h8
-rw-r--r--src/corelib/tools/qtimezoneprivate.cpp2
-rw-r--r--src/corelib/tools/qtimezoneprivate_data_p.h5
-rw-r--r--src/corelib/tools/qtimezoneprivate_icu.cpp5
-rw-r--r--src/corelib/tools/qtimezoneprivate_mac.mm88
-rw-r--r--src/corelib/tools/qtimezoneprivate_tz.cpp40
-rw-r--r--src/corelib/tools/qtimezoneprivate_win.cpp2
-rw-r--r--src/corelib/tools/qvarlengtharray.h5
-rw-r--r--src/corelib/tools/qvarlengtharray.qdoc6
-rw-r--r--src/corelib/tools/qvector.h9
-rw-r--r--src/corelib/tools/qvector.qdoc7
-rw-r--r--src/corelib/tools/qversionnumber.cpp53
-rw-r--r--src/corelib/tools/qversionnumber.h4
-rw-r--r--src/corelib/tools/tools.pri5
-rw-r--r--src/corelib/xml/qxmlstream.cpp70
-rw-r--r--src/corelib/xml/qxmlstream.g105
-rw-r--r--src/corelib/xml/qxmlstream_p.h73
-rw-r--r--src/corelib/xml/qxmlutils.cpp37
-rw-r--r--src/corelib/xml/qxmlutils_p.h7
-rw-r--r--src/dbus/qdbusserver.cpp8
-rw-r--r--src/gui/configure.json54
-rw-r--r--src/gui/doc/qtgui.qdocconf1
-rw-r--r--src/gui/doc/src/external-resources.qdoc10
-rw-r--r--src/gui/doc/src/qtgui.qdoc35
-rw-r--r--src/gui/gui.pro1
-rw-r--r--src/gui/image/qbmphandler.cpp4
-rw-r--r--src/gui/image/qicon.cpp7
-rw-r--r--src/gui/image/qiconloader.cpp14
-rw-r--r--src/gui/image/qiconloader_p.h3
-rw-r--r--src/gui/image/qimage.cpp43
-rw-r--r--src/gui/image/qimage.h7
-rw-r--r--src/gui/image/qimage_conversions.cpp64
-rw-r--r--src/gui/image/qimage_darwin.mm2
-rw-r--r--src/gui/image/qimage_p.h4
-rw-r--r--src/gui/image/qimagereader.cpp11
-rw-r--r--src/gui/image/qimagewriter.cpp10
-rw-r--r--src/gui/image/qimagewriter.h3
-rw-r--r--src/gui/image/qmovie.cpp48
-rw-r--r--src/gui/image/qmovie.h2
-rw-r--r--src/gui/image/qpicture.cpp2
-rw-r--r--src/gui/image/qpicture.h12
-rw-r--r--src/gui/image/qpixmap.cpp71
-rw-r--r--src/gui/image/qpixmap_blitter.cpp4
-rw-r--r--src/gui/image/qplatformpixmap.cpp76
-rw-r--r--src/gui/image/qplatformpixmap.h8
-rw-r--r--src/gui/image/qxpmhandler.cpp5
-rw-r--r--src/gui/kernel/qclipboard.cpp2
-rw-r--r--src/gui/kernel/qcursor.cpp48
-rw-r--r--src/gui/kernel/qcursor.h4
-rw-r--r--src/gui/kernel/qdnd.cpp5
-rw-r--r--src/gui/kernel/qdnd_p.h1
-rw-r--r--src/gui/kernel/qevent.cpp6
-rw-r--r--src/gui/kernel/qguiapplication.cpp172
-rw-r--r--src/gui/kernel/qguiapplication.h2
-rw-r--r--src/gui/kernel/qguiapplication_p.h1
-rw-r--r--src/gui/kernel/qkeysequence.cpp18
-rw-r--r--src/gui/kernel/qkeysequence_p.h2
-rw-r--r--src/gui/kernel/qoffscreensurface.cpp20
-rw-r--r--src/gui/kernel/qoffscreensurface.h3
-rw-r--r--src/gui/kernel/qopenglcontext.cpp55
-rw-r--r--src/gui/kernel/qopenglcontext.h7
-rw-r--r--src/gui/kernel/qpalette.cpp8
-rw-r--r--src/gui/kernel/qplatformcursor.cpp41
-rw-r--r--src/gui/kernel/qplatformcursor.h17
-rw-r--r--src/gui/kernel/qplatformdialoghelper.cpp26
-rw-r--r--src/gui/kernel/qplatformdialoghelper.h5
-rw-r--r--src/gui/kernel/qplatformdrag.h1
-rw-r--r--src/gui/kernel/qplatformintegration.cpp31
-rw-r--r--src/gui/kernel/qplatformintegration.h10
-rw-r--r--src/gui/kernel/qplatformmenu.cpp31
-rw-r--r--src/gui/kernel/qplatformmenu.h18
-rw-r--r--src/gui/kernel/qplatformoffscreensurface.h4
-rw-r--r--src/gui/kernel/qplatformsystemtrayicon.cpp11
-rw-r--r--src/gui/kernel/qplatformsystemtrayicon.h2
-rw-r--r--src/gui/kernel/qplatformtheme.cpp4
-rw-r--r--src/gui/kernel/qplatformtheme.h3
-rw-r--r--src/gui/kernel/qplatformwindow.cpp29
-rw-r--r--src/gui/kernel/qplatformwindow.h8
-rw-r--r--src/gui/kernel/qscreen.cpp4
-rw-r--r--src/gui/kernel/qsimpledrag.cpp7
-rw-r--r--src/gui/kernel/qsimpledrag_p.h1
-rw-r--r--src/gui/kernel/qstylehints.cpp11
-rw-r--r--src/gui/kernel/qstylehints.h2
-rw-r--r--src/gui/kernel/qsurface.cpp2
-rw-r--r--src/gui/kernel/qsurface.h1
-rw-r--r--src/gui/kernel/qsurfaceformat.cpp69
-rw-r--r--src/gui/kernel/qsurfaceformat.h9
-rw-r--r--src/gui/kernel/qwindow.cpp302
-rw-r--r--src/gui/kernel/qwindow.h10
-rw-r--r--src/gui/kernel/qwindow_p.h12
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp57
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h29
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h12
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp6
-rw-r--r--src/gui/math3d/qquaternion.cpp4
-rw-r--r--src/gui/opengl/qopengl.h4
-rw-r--r--src/gui/opengl/qopenglextrafunctions.h496
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp582
-rw-r--r--src/gui/opengl/qopengltexture.cpp50
-rw-r--r--src/gui/opengl/qopengltexture.h9
-rw-r--r--src/gui/painting/painting.pri3
-rw-r--r--src/gui/painting/qbackingstore.cpp129
-rw-r--r--src/gui/painting/qbackingstore.h4
-rw-r--r--src/gui/painting/qbrush.cpp2
-rw-r--r--src/gui/painting/qcolor.cpp33
-rw-r--r--src/gui/painting/qcolor.h16
-rw-r--r--src/gui/painting/qcompositionfunctions.cpp792
-rw-r--r--src/gui/painting/qcoregraphics.mm2
-rw-r--r--src/gui/painting/qcosmeticstroker.cpp2
-rw-r--r--src/gui/painting/qdrawhelper.cpp707
-rw-r--r--src/gui/painting/qdrawhelper_avx2.cpp19
-rw-r--r--src/gui/painting/qdrawhelper_p.h4
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp4
-rw-r--r--src/gui/painting/qemulationpaintengine.cpp84
-rw-r--r--src/gui/painting/qgrayraster.c809
-rw-r--r--src/gui/painting/qpagedpaintdevice.cpp12
-rw-r--r--src/gui/painting/qpagedpaintdevice.h2
-rw-r--r--src/gui/painting/qpaintengine.cpp8
-rw-r--r--src/gui/painting/qpaintengine_p.h25
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp10
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h2
-rw-r--r--src/gui/painting/qpainter.cpp8
-rw-r--r--src/gui/painting/qpdf.cpp319
-rw-r--r--src/gui/painting/qpdf.qrc7
-rw-r--r--src/gui/painting/qpdf_p.h11
-rw-r--r--src/gui/painting/qpdfa_metadata.xml16
-rw-r--r--src/gui/painting/qpdfwriter.cpp31
-rw-r--r--src/gui/painting/qpdfwriter.h3
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp45
-rw-r--r--src/gui/painting/qplatformbackingstore.h5
-rw-r--r--src/gui/painting/qpolygon.cpp43
-rw-r--r--src/gui/painting/qpolygon.h4
-rw-r--r--src/gui/text/qdistancefield.cpp12
-rw-r--r--src/gui/text/qfont.cpp5
-rw-r--r--src/gui/text/qfont.h8
-rw-r--r--src/gui/text/qfontengine.cpp4
-rw-r--r--src/gui/text/qfontengine_p.h6
-rw-r--r--src/gui/text/qfontmetrics.cpp2
-rw-r--r--src/gui/text/qfontsubset.cpp8
-rw-r--r--src/gui/text/qstatictext.h2
-rw-r--r--src/gui/text/qtextdocument.cpp2
-rw-r--r--src/gui/text/qtextdocument_p.cpp2
-rw-r--r--src/gui/text/qtextengine.cpp87
-rw-r--r--src/gui/text/qtextengine_p.h17
-rw-r--r--src/gui/text/qtextformat.cpp34
-rw-r--r--src/gui/text/qtexthtmlparser.cpp14
-rw-r--r--src/gui/text/qtexthtmlparser_p.h1
-rw-r--r--src/gui/text/qtextlayout.cpp58
-rw-r--r--src/gui/text/qtextoption.cpp33
-rw-r--r--src/gui/text/qtextoption.h14
-rw-r--r--src/gui/util/qshaderformat.cpp130
-rw-r--r--src/gui/util/qshaderformat_p.h109
-rw-r--r--src/gui/util/qshadergenerator.cpp351
-rw-r--r--src/gui/util/qshadergenerator_p.h75
-rw-r--r--src/gui/util/qshadergraph.cpp262
-rw-r--r--src/gui/util/qshadergraph_p.h123
-rw-r--r--src/gui/util/qshadergraphloader.cpp251
-rw-r--r--src/gui/util/qshadergraphloader_p.h99
-rw-r--r--src/gui/util/qshaderlanguage.cpp56
-rw-r--r--src/gui/util/qshaderlanguage_p.h163
-rw-r--r--src/gui/util/qshadernode.cpp172
-rw-r--r--src/gui/util/qshadernode_p.h128
-rw-r--r--src/gui/util/qshadernodeport.cpp55
-rw-r--r--src/gui/util/qshadernodeport_p.h88
-rw-r--r--src/gui/util/qshadernodesloader.cpp274
-rw-r--r--src/gui/util/qshadernodesloader_p.h95
-rw-r--r--src/gui/util/qvalidator.cpp12
-rw-r--r--src/gui/util/util.pri20
-rw-r--r--src/gui/vulkan/KHRONOS_LICENSE.txt20
-rw-r--r--src/gui/vulkan/qplatformvulkaninstance.cpp88
-rw-r--r--src/gui/vulkan/qplatformvulkaninstance.h91
-rw-r--r--src/gui/vulkan/qt_attribution.json17
-rw-r--r--src/gui/vulkan/qvulkanfunctions.cpp177
-rw-r--r--src/gui/vulkan/qvulkaninstance.cpp894
-rw-r--r--src/gui/vulkan/qvulkaninstance.h198
-rw-r--r--src/gui/vulkan/qvulkanwindow.cpp2720
-rw-r--r--src/gui/vulkan/qvulkanwindow.h161
-rw-r--r--src/gui/vulkan/qvulkanwindow_p.h188
-rw-r--r--src/gui/vulkan/vk.xml5269
-rw-r--r--src/gui/vulkan/vulkan.pri55
-rw-r--r--src/network/access/access.pri6
-rw-r--r--src/network/access/http2/http2frames.cpp6
-rw-r--r--src/network/access/http2/http2frames_p.h2
-rw-r--r--src/network/access/http2/http2protocol.cpp75
-rw-r--r--src/network/access/http2/http2protocol_p.h6
-rw-r--r--src/network/access/qhsts.cpp61
-rw-r--r--src/network/access/qhsts_p.h7
-rw-r--r--src/network/access/qhstsstore.cpp202
-rw-r--r--src/network/access/qhstsstore_p.h93
-rw-r--r--src/network/access/qhttp2protocolhandler.cpp38
-rw-r--r--src/network/access/qhttp2protocolhandler_p.h4
-rw-r--r--src/network/access/qhttpmultipart.cpp21
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp43
-rw-r--r--src/network/access/qhttpnetworkconnection_p.h2
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp100
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h5
-rw-r--r--src/network/access/qhttpnetworkheader_p.h2
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp16
-rw-r--r--src/network/access/qhttpthreaddelegate_p.h4
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp22
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp46
-rw-r--r--src/network/access/qnetworkaccessmanager.h3
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h2
-rw-r--r--src/network/access/qnetworkreply.cpp6
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp17
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h5
-rw-r--r--src/network/bearer/qnetworkconfiguration.cpp2
-rw-r--r--src/network/configure.json14
-rw-r--r--src/network/kernel/kernel.pri2
-rw-r--r--src/network/kernel/qhostaddress.cpp35
-rw-r--r--src/network/kernel/qhostinfo.cpp21
-rw-r--r--src/network/kernel/qhostinfo.h9
-rw-r--r--src/network/kernel/qnetworkinterface_win.cpp58
-rw-r--r--src/network/kernel/qnetworkproxy.cpp48
-rw-r--r--src/network/kernel/qnetworkproxy.h9
-rw-r--r--src/network/socket/qabstractsocket.cpp13
-rw-r--r--src/network/socket/qlocalserver.cpp40
-rw-r--r--src/network/socket/qlocalserver.h2
-rw-r--r--src/network/socket/qlocalsocket.cpp14
-rw-r--r--src/network/socket/qlocalsocket_win.cpp4
-rw-r--r--src/network/socket/qnativesocketengine.cpp3
-rw-r--r--src/network/socket/qnativesocketengine_p.h2
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp60
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp12
-rw-r--r--src/network/socket/qtcpserver_p.h3
-rw-r--r--src/network/ssl/qsslcertificate_openssl.cpp57
-rw-r--r--src/network/ssl/qsslcertificate_qt.cpp17
-rw-r--r--src/network/ssl/qsslcontext_openssl.cpp309
-rw-r--r--src/network/ssl/qsslcontext_openssl11.cpp277
-rw-r--r--src/network/ssl/qsslcontext_opensslpre11.cpp354
-rw-r--r--src/network/ssl/qssldiffiehellmanparameters_openssl.cpp38
-rw-r--r--src/network/ssl/qsslellipticcurve.h1
-rw-r--r--src/network/ssl/qsslellipticcurve_openssl.cpp8
-rw-r--r--src/network/ssl/qsslkey_openssl.cpp79
-rw-r--r--src/network/ssl/qsslsocket.cpp13
-rw-r--r--src/network/ssl/qsslsocket_mac.cpp24
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp392
-rw-r--r--src/network/ssl/qsslsocket_openssl11.cpp285
-rw-r--r--src/network/ssl/qsslsocket_openssl11_symbols_p.h132
-rw-r--r--src/network/ssl/qsslsocket_openssl_p.h8
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp499
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h122
-rw-r--r--src/network/ssl/qsslsocket_opensslpre11.cpp424
-rw-r--r--src/network/ssl/qsslsocket_opensslpre11_symbols_p.h230
-rw-r--r--src/network/ssl/qsslsocket_p.h1
-rw-r--r--src/network/ssl/ssl.pri18
-rw-r--r--src/platformheaders/cocoafunctions/qcocoawindowfunctions.h6
-rw-r--r--src/platformsupport/cglconvenience/cglconvenience.mm131
-rw-r--r--src/platformsupport/cglconvenience/cglconvenience.pro17
-rw-r--r--src/platformsupport/clipboard/clipboard.pro1
-rw-r--r--src/platformsupport/clipboard/qmacmime.mm85
-rw-r--r--src/platformsupport/edid/edid.pro13
-rw-r--r--src/platformsupport/edid/qedidparser.cpp177
-rw-r--r--src/platformsupport/edid/qedidparser_p.h (renamed from src/platformsupport/cglconvenience/cglconvenience_p.h)39
-rw-r--r--src/platformsupport/edid/qedidvendortable_p.h2296
-rw-r--r--src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp56
-rw-r--r--src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h3
-rw-r--r--src/platformsupport/fbconvenience/qfbwindow.cpp2
-rw-r--r--src/platformsupport/fbconvenience/qfbwindow_p.h4
-rw-r--r--src/platformsupport/fontdatabases/mac/coretext.pri16
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h8
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp16
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h2
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience.cpp48
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience_p.h15
-rw-r--r--src/platformsupport/graphics/qrasterbackingstore.cpp28
-rw-r--r--src/platformsupport/graphics/qrasterbackingstore_p.h1
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp2
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h2
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp6
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h2
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp18
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h8
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp34
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h7
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp6
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h3
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp7
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h2
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp4
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h2
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp7
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h2
-rw-r--r--src/platformsupport/input/libinput/qlibinputhandler.cpp22
-rw-r--r--src/platformsupport/input/libinput/qlibinputhandler_p.h8
-rw-r--r--src/platformsupport/input/libinput/qlibinputkeyboard_p.h3
-rw-r--r--src/platformsupport/input/libinput/qlibinputpointer.cpp23
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice.cpp24
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice_p.h3
-rw-r--r--src/platformsupport/linuxaccessibility/atspiadaptor.cpp130
-rw-r--r--src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp4
-rw-r--r--src/platformsupport/platformsupport.pro6
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu.cpp20
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h16
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp2
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes.cpp8
-rw-r--r--src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp357
-rw-r--r--src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h106
-rw-r--r--src/platformsupport/vkconvenience/vkconvenience.pro16
-rw-r--r--src/plugins/bearer/linux_common/qofonoservice_linux.cpp2
-rw-r--r--src/plugins/generic/tuiotouch/qoscbundle.cpp6
-rw-r--r--src/plugins/generic/tuiotouch/qoscmessage.cpp2
-rw-r--r--src/plugins/generic/tuiotouch/qtuiohandler.cpp41
-rw-r--r--src/plugins/imageformats/gif/main.h4
-rw-r--r--src/plugins/imageformats/gif/qgifhandler.cpp4
-rw-r--r--src/plugins/imageformats/gif/qgifhandler_p.h22
-rw-r--r--src/plugins/imageformats/ico/ico.pro1
-rw-r--r--src/plugins/imageformats/ico/main.h4
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp128
-rw-r--r--src/plugins/imageformats/ico/qicohandler.h18
-rw-r--r--src/plugins/imageformats/jpeg/main.h4
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler_p.h14
-rw-r--r--src/plugins/platforms/android/android.pro9
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp4
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp17
-rw-r--r--src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp6
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp37
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.h7
-rw-r--r--src/plugins/platforms/android/qandroidplatformmenu.cpp11
-rw-r--r--src/plugins/platforms/android/qandroidplatformmenu.h3
-rw-r--r--src/plugins/platforms/android/qandroidplatformmenuitem.cpp11
-rw-r--r--src/plugins/platforms/android/qandroidplatformmenuitem.h3
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp22
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.h4
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkaninstance.cpp66
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkaninstance.h63
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp210
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkanwindow.h91
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp5
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.h4
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro6
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm239
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm18
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm63
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h129
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoakeymapper.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoakeymapper.mm19
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoamimetypes.mm92
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.mm104
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h135
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm1510
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h18
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm335
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.h74
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.mm299
-rw-r--r--src/plugins/platforms/direct2d/direct2d.pro2
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfswindow.cpp17
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp5
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp82
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h5
-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.cpp4
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp57
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h11
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp71
-rw-r--r--src/plugins/platforms/haiku/qhaikuwindow.cpp23
-rw-r--r--src/plugins/platforms/haiku/qhaikuwindow.h4
-rw-r--r--src/plugins/platforms/ios/qiosclipboard.mm14
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.mm2
-rw-r--r--src/plugins/platforms/ios/qiosmenu.h8
-rw-r--r--src/plugins/platforms/ios/qiosmenu.mm22
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm7
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm4
-rw-r--r--src/plugins/platforms/ios/qioswindow.h2
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm28
-rw-r--r--src/plugins/platforms/ios/quiview.mm31
-rw-r--r--src/plugins/platforms/ios/quiview_accessibility.mm2
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.cpp12
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.h2
-rw-r--r--src/plugins/platforms/offscreen/qoffscreencommon.h1
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.cpp12
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.h4
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenwindow.cpp23
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenwindow.h2
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp27
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h4
-rw-r--r--src/plugins/platforms/vnc/qvncintegration.cpp3
-rw-r--r--src/plugins/platforms/windows/accessible/accessible.pri15
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.cpp190
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.h47
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp10
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp138
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h36
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h8
-rw-r--r--src/plugins/platforms/windows/qwindowscombase.h112
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp101
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h8
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp30
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h7
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp36
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp73
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h11
-rw-r--r--src/plugins/platforms/windows/qwindowsdropdataobject.cpp98
-rw-r--r--src/plugins/platforms/windows/qwindowsdropdataobject.h63
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp72
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h7
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp30
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h8
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.cpp962
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.h243
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp62
-rw-r--r--src/plugins/platforms/windows/qwindowsole.h17
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.cpp443
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.h103
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp70
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h10
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.cpp136
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.h76
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp322
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h38
-rw-r--r--src/plugins/platforms/windows/windows.pri15
-rw-r--r--src/plugins/platforms/windows/windows.pro2
-rw-r--r--src/plugins/platforms/winrt/qwinrtdrag.cpp6
-rw-r--r--src/plugins/platforms/winrt/qwinrtdrag.h1
-rw-r--r--src/plugins/platforms/winrt/qwinrtfileengine.cpp3
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.cpp21
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.h2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h17
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp1
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp30
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h1
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp13
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp18
-rw-r--r--src/plugins/platforms/xcb/nativepainting/nativepainting.pri22
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp203
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qbackingstore_x11_p.h70
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qcolormap_x11.cpp644
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qcolormap_x11_p.h75
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp2837
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h118
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp2108
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h160
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qt_x11_p.h193
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qtessellator.cpp1494
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qtessellator_p.h83
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp315
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.h96
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp102
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp86
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp662
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h177
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp1012
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp131
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp32
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp63
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h7
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp98
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp81
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h15
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp603
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h71
-rw-r--r--src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp38
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkaninstance.cpp156
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkaninstance.h79
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkanwindow.cpp88
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkanwindow.h65
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp665
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h10
-rw-r--r--src/plugins/platforms/xcb/qxcbwmsupport.cpp21
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.cpp43
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro16
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3menu.cpp22
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3menu.h8
-rw-r--r--src/plugins/plugins.pro1
-rw-r--r--src/plugins/sqldrivers/db2/qsql_db2.cpp14
-rw-r--r--src/plugins/sqldrivers/ibase/qsql_ibase.cpp9
-rw-r--r--src/plugins/sqldrivers/mysql/qsql_mysql.cpp3
-rw-r--r--src/plugins/sqldrivers/odbc/qsql_odbc.cpp7
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql.cpp12
-rw-r--r--src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp110
-rw-r--r--src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp2
-rw-r--r--src/plugins/sqldrivers/tds/qsql_tds.cpp4
-rw-r--r--src/plugins/styles/android/android.pro16
-rw-r--r--src/plugins/styles/android/androidstyle.json3
-rw-r--r--src/plugins/styles/android/main.cpp64
-rw-r--r--src/plugins/styles/android/qandroidstyle.cpp (renamed from src/widgets/styles/qandroidstyle.cpp)4
-rw-r--r--src/plugins/styles/android/qandroidstyle_p.h (renamed from src/widgets/styles/qandroidstyle_p.h)6
-rw-r--r--src/plugins/styles/mac/mac.pro19
-rw-r--r--src/plugins/styles/mac/macstyle.json3
-rw-r--r--src/plugins/styles/mac/main.mm65
-rw-r--r--src/plugins/styles/mac/qmacstyle.qdoc (renamed from src/widgets/styles/qmacstyle.qdoc)2
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm (renamed from src/widgets/styles/qmacstyle_mac.mm)2867
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p.h (renamed from src/widgets/styles/qmacstyle_mac_p.h)11
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p_p.h (renamed from src/widgets/styles/qmacstyle_mac_p_p.h)69
-rw-r--r--src/plugins/styles/styles.pro8
-rw-r--r--src/plugins/styles/windowsvista/main.cpp64
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle.cpp (renamed from src/widgets/styles/qwindowsvistastyle.cpp)4
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle_p.h (renamed from src/widgets/styles/qwindowsvistastyle_p.h)6
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h (renamed from src/widgets/styles/qwindowsvistastyle_p_p.h)6
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle.cpp (renamed from src/widgets/styles/qwindowsxpstyle.cpp)12
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle_p.h (renamed from src/widgets/styles/qwindowsxpstyle_p.h)7
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h (renamed from src/widgets/styles/qwindowsxpstyle_p_p.h)6
-rw-r--r--src/plugins/styles/windowsvista/windowsvista.pro22
-rw-r--r--src/plugins/styles/windowsvista/windowsvistastyle.json3
-rw-r--r--src/printsupport/kernel/qcups.cpp2
-rw-r--r--src/printsupport/kernel/qprintengine_pdf.cpp4
-rw-r--r--src/printsupport/kernel/qprintengine_pdf_p.h2
-rw-r--r--src/printsupport/kernel/qprinter.cpp33
-rw-r--r--src/printsupport/kernel/qprinter.h3
-rw-r--r--src/printsupport/kernel/qprinter_p.h4
-rw-r--r--src/sql/doc/snippets/code/doc_src_sql-driver.cpp5
-rw-r--r--src/sql/doc/src/sql-driver.qdoc16
-rw-r--r--src/sql/kernel/qsqldatabase.cpp1
-rw-r--r--src/sql/kernel/qsqlerror.cpp34
-rw-r--r--src/sql/kernel/qsqlerror.h7
-rw-r--r--src/sql/kernel/qsqlfield.cpp42
-rw-r--r--src/sql/kernel/qsqlfield.h5
-rw-r--r--src/sql/kernel/qsqlrecord.cpp17
-rw-r--r--src/sql/models/qsqlquerymodel.cpp24
-rw-r--r--src/sql/models/qsqlquerymodel.h24
-rw-r--r--src/sql/models/qsqltablemodel.cpp14
-rw-r--r--src/sql/models/qsqltablemodel_p.h2
-rw-r--r--src/src.pro8
-rw-r--r--src/testlib/qbenchmarkmetric.cpp190
-rw-r--r--src/testlib/qtest.h29
-rw-r--r--src/testlib/qtest_gui.h29
-rw-r--r--src/testlib/qtestblacklist.cpp14
-rw-r--r--src/testlib/qtestcase.cpp106
-rw-r--r--src/testlib/qtestcase.h22
-rw-r--r--src/testlib/qtestcase.qdoc34
-rw-r--r--src/testlib/qtestkeyboard.h20
-rw-r--r--src/testlib/qtestutil_macos.mm27
-rw-r--r--src/testlib/qtestutil_macos_p.h11
-rw-r--r--src/tools/bootstrap/bootstrap.pro6
-rw-r--r--src/tools/moc/generator.cpp33
-rw-r--r--src/tools/moc/generator.h1
-rw-r--r--src/tools/moc/main.cpp4
-rw-r--r--src/tools/moc/moc.cpp10
-rw-r--r--src/tools/moc/moc.h3
-rw-r--r--src/tools/moc/moc.pro1
-rw-r--r--src/tools/qdbuscpp2xml/qdbuscpp2xml.pro1
-rw-r--r--src/tools/qdbusxml2cpp/qdbusxml2cpp.pro1
-rw-r--r--src/tools/qlalr/qlalr.pro1
-rw-r--r--src/tools/qvkgen/qvkgen.cpp530
-rw-r--r--src/tools/qvkgen/qvkgen.pro6
-rw-r--r--src/tools/rcc/rcc.pro1
-rw-r--r--src/tools/uic/cpp/cpp.pri12
-rw-r--r--src/tools/uic/cpp/cppextractimages.cpp140
-rw-r--r--src/tools/uic/cpp/cppextractimages.h64
-rw-r--r--src/tools/uic/cpp/cppwritedeclaration.cpp63
-rw-r--r--src/tools/uic/cpp/cppwritedeclaration.h3
-rw-r--r--src/tools/uic/cpp/cppwriteicondata.cpp172
-rw-r--r--src/tools/uic/cpp/cppwriteicondata.h68
-rw-r--r--src/tools/uic/cpp/cppwriteicondeclaration.cpp67
-rw-r--r--src/tools/uic/cpp/cppwriteicondeclaration.h63
-rw-r--r--src/tools/uic/cpp/cppwriteiconinitialization.cpp102
-rw-r--r--src/tools/uic/cpp/cppwriteiconinitialization.h68
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.cpp22
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.h5
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.cpp237
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.h16
-rw-r--r--src/tools/uic/customwidgetsinfo.cpp12
-rw-r--r--src/tools/uic/customwidgetsinfo.h2
-rw-r--r--src/tools/uic/databaseinfo.cpp4
-rw-r--r--src/tools/uic/main.cpp5
-rw-r--r--src/tools/uic/option.h4
-rw-r--r--src/tools/uic/treewalker.cpp29
-rw-r--r--src/tools/uic/treewalker.h7
-rw-r--r--src/tools/uic/ui4.cpp5165
-rw-r--r--src/tools/uic/ui4.h2292
-rw-r--r--src/tools/uic/uic.cpp7
-rw-r--r--src/tools/uic/uic.h7
-rw-r--r--src/tools/uic/uic.pro1
-rw-r--r--src/tools/uic/utils.h13
-rw-r--r--src/widgets/configure.json10
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp5
-rw-r--r--src/widgets/dialogs/qdialog.cpp11
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp16
-rw-r--r--src/widgets/dialogs/qinputdialog.cpp61
-rw-r--r--src/widgets/dialogs/qinputdialog.h8
-rw-r--r--src/widgets/dialogs/qmessagebox.cpp3
-rw-r--r--src/widgets/dialogs/qprogressdialog.cpp2
-rw-r--r--src/widgets/dialogs/qwizard.cpp32
-rw-r--r--src/widgets/doc/images/stylesheet-coffee-xp.pngbin14200 -> 0 bytes
-rw-r--r--src/widgets/doc/images/windowsxp-tabwidget.pngbin5220 -> 0 bytes
-rw-r--r--src/widgets/doc/images/windowsxp-treeview.pngbin5795 -> 0 bytes
-rw-r--r--src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc4
-rw-r--r--src/widgets/doc/snippets/macmainwindow.mm2
-rw-r--r--src/widgets/doc/src/qtwidgets-index.qdoc4
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/gallery.qdoc4
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc39
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/widgets.qdoc2
-rw-r--r--src/widgets/graphicsview/qgraphicsview.cpp3
-rw-r--r--src/widgets/graphicsview/qgraphicswidget_p.cpp3
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp22
-rw-r--r--src/widgets/itemviews/qabstractitemview.h1
-rw-r--r--src/widgets/itemviews/qcolumnview.cpp6
-rw-r--r--src/widgets/itemviews/qdirmodel.cpp17
-rw-r--r--src/widgets/itemviews/qheaderview.cpp16
-rw-r--r--src/widgets/itemviews/qitemdelegate.cpp2
-rw-r--r--src/widgets/itemviews/qlistview.cpp3
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp18
-rw-r--r--src/widgets/itemviews/qlistwidget.h11
-rw-r--r--src/widgets/itemviews/qtablewidget.cpp18
-rw-r--r--src/widgets/itemviews/qtablewidget.h10
-rw-r--r--src/widgets/itemviews/qtreeview.cpp2
-rw-r--r--src/widgets/itemviews/qtreewidget.cpp19
-rw-r--r--src/widgets/itemviews/qtreewidget.h10
-rw-r--r--src/widgets/kernel/qaction.cpp45
-rw-r--r--src/widgets/kernel/qaction.h3
-rw-r--r--src/widgets/kernel/qaction_p.h3
-rw-r--r--src/widgets/kernel/qapplication.cpp12
-rw-r--r--src/widgets/kernel/qapplication_p.h2
-rw-r--r--src/widgets/kernel/qboxlayout.cpp28
-rw-r--r--src/widgets/kernel/qdesktopwidget.cpp87
-rw-r--r--src/widgets/kernel/qdesktopwidget.qdoc2
-rw-r--r--src/widgets/kernel/qdesktopwidget_p.h23
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp10
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp134
-rw-r--r--src/widgets/kernel/qopenglwidget.h3
-rw-r--r--src/widgets/kernel/qtooltip.cpp13
-rw-r--r--src/widgets/kernel/qwhatsthis.cpp9
-rw-r--r--src/widgets/kernel/qwidget.cpp115
-rw-r--r--src/widgets/kernel/qwidget_p.h21
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp26
-rw-r--r--src/widgets/kernel/qwidgetbackingstore_p.h6
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp113
-rw-r--r--src/widgets/kernel/qwidgetwindow_p.h3
-rw-r--r--src/widgets/kernel/qwindowcontainer.cpp13
-rw-r--r--src/widgets/styles/images/fusion_arrow.pngbin295 -> 0 bytes
-rw-r--r--src/widgets/styles/qcommonstyle.cpp8
-rw-r--r--src/widgets/styles/qcommonstyle_p.h2
-rw-r--r--src/widgets/styles/qfusionstyle.cpp262
-rw-r--r--src/widgets/styles/qfusionstyle_p.h2
-rw-r--r--src/widgets/styles/qstyle.cpp18
-rw-r--r--src/widgets/styles/qstyle.h2
-rw-r--r--src/widgets/styles/qstyle.qrc1
-rw-r--r--src/widgets/styles/qstyleanimation_p.h13
-rw-r--r--src/widgets/styles/qstylefactory.cpp61
-rw-r--r--src/widgets/styles/qstylehelper.cpp29
-rw-r--r--src/widgets/styles/qstylehelper_p.h23
-rw-r--r--src/widgets/styles/qstyleoption.cpp12
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp6
-rw-r--r--src/widgets/styles/qstylesheetstyle_default.cpp4
-rw-r--r--src/widgets/styles/qwindowsstyle_p.h2
-rw-r--r--src/widgets/styles/qwindowsstyle_p_p.h2
-rw-r--r--src/widgets/styles/styles.pri23
-rw-r--r--src/widgets/util/qcompleter.cpp50
-rw-r--r--src/widgets/util/qcompleter_p.h4
-rw-r--r--src/widgets/util/qsystemtrayicon.cpp29
-rw-r--r--src/widgets/util/qsystemtrayicon_win.cpp591
-rw-r--r--src/widgets/util/util.pri4
-rw-r--r--src/widgets/widgets/qcombobox.cpp41
-rw-r--r--src/widgets/widgets/qcombobox_p.h3
-rw-r--r--src/widgets/widgets/qdatetimeedit.cpp8
-rw-r--r--src/widgets/widgets/qdialogbuttonbox.cpp2
-rw-r--r--src/widgets/widgets/qdialogbuttonbox.h6
-rw-r--r--src/widgets/widgets/qdockarealayout.cpp137
-rw-r--r--src/widgets/widgets/qdockarealayout_p.h5
-rw-r--r--src/widgets/widgets/qdockwidget.cpp14
-rw-r--r--src/widgets/widgets/qeffects.cpp4
-rw-r--r--src/widgets/widgets/qfontcombobox.cpp3
-rw-r--r--src/widgets/widgets/qlineedit.cpp50
-rw-r--r--src/widgets/widgets/qlineedit.h2
-rw-r--r--src/widgets/widgets/qmainwindow.cpp257
-rw-r--r--src/widgets/widgets/qmainwindowlayout.cpp700
-rw-r--r--src/widgets/widgets/qmainwindowlayout_p.h313
-rw-r--r--src/widgets/widgets/qmdiarea.cpp6
-rw-r--r--src/widgets/widgets/qmdisubwindow.cpp58
-rw-r--r--src/widgets/widgets/qmenu.cpp35
-rw-r--r--src/widgets/widgets/qmenu.h8
-rw-r--r--src/widgets/widgets/qmenu_p.h2
-rw-r--r--src/widgets/widgets/qmenubar.cpp7
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp30
-rw-r--r--src/widgets/widgets/qplaintextedit.h12
-rw-r--r--src/widgets/widgets/qprogressbar.cpp2
-rw-r--r--src/widgets/widgets/qpushbutton.cpp7
-rw-r--r--src/widgets/widgets/qsizegrip.cpp3
-rw-r--r--src/widgets/widgets/qsplashscreen.cpp5
-rw-r--r--src/widgets/widgets/qtabbar_p.h4
-rw-r--r--src/widgets/widgets/qtabwidget.cpp5
-rw-r--r--src/widgets/widgets/qtextedit.cpp29
-rw-r--r--src/widgets/widgets/qtextedit.h12
-rw-r--r--src/widgets/widgets/qtoolbar.cpp1
-rw-r--r--src/widgets/widgets/qtoolbar.h4
-rw-r--r--src/widgets/widgets/qtoolbutton.cpp3
-rw-r--r--src/widgets/widgets/qwidgetanimator.cpp4
-rw-r--r--src/widgets/widgets/qwidgetresizehandler.cpp11
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp5
974 files changed, 84180 insertions, 45404 deletions
diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
index 3b7b11c8ee..e5746bf3eb 100644
--- a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
+++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
@@ -168,21 +168,7 @@ contains(SHAPERS, coretext) {
# 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
- }
- }
+ CONFIG += watchos_coretext
}
contains(SHAPERS, fallback)|isEmpty(SHAPERS) {
diff --git a/src/3rdparty/iaccessible2/generated/amd64/ia2_api_all.h b/src/3rdparty/iaccessible2/generated/amd64/ia2_api_all.h
index 4f7b7d07d7..1008728034 100644
--- a/src/3rdparty/iaccessible2/generated/amd64/ia2_api_all.h
+++ b/src/3rdparty/iaccessible2/generated/amd64/ia2_api_all.h
@@ -16,8 +16,9 @@
*/
/* @@MIDL_FILE_HEADING( ) */
-#pragma warning( disable: 4049 ) /* more than 64k source lines */
-
+#ifdef _MSC_VER
+# pragma warning( disable: 4049 ) /* more than 64k source lines */
+#endif
/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
diff --git a/src/3rdparty/iaccessible2/generated/amd64/ia2_api_all_i.c b/src/3rdparty/iaccessible2/generated/amd64/ia2_api_all_i.c
index e04a5dcb69..4687e9942d 100644
--- a/src/3rdparty/iaccessible2/generated/amd64/ia2_api_all_i.c
+++ b/src/3rdparty/iaccessible2/generated/amd64/ia2_api_all_i.c
@@ -18,8 +18,9 @@
*/
/* @@MIDL_FILE_HEADING( ) */
-#pragma warning( disable: 4049 ) /* more than 64k source lines */
-
+#ifdef _MSC_VER
+# pragma warning( disable: 4049 ) /* more than 64k source lines */
+#endif
#ifdef __cplusplus
extern "C"{
@@ -65,7 +66,7 @@ typedef IID CLSID;
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
-#endif !_MIDL_USE_GUIDDEF_
+#endif // !_MIDL_USE_GUIDDEF_
MIDL_DEFINE_GUID(IID, IID_IAccessibleRelation,0x7CDF86EE,0xC3DA,0x496a,0xBD,0xA4,0x28,0x1B,0x33,0x6E,0x1F,0xDC);
diff --git a/src/3rdparty/iaccessible2/generated/x86/ia2_api_all.h b/src/3rdparty/iaccessible2/generated/x86/ia2_api_all.h
index eb3b57b8bd..9e4be75bb9 100644
--- a/src/3rdparty/iaccessible2/generated/x86/ia2_api_all.h
+++ b/src/3rdparty/iaccessible2/generated/x86/ia2_api_all.h
@@ -16,7 +16,9 @@
*/
/* @@MIDL_FILE_HEADING( ) */
-#pragma warning( disable: 4049 ) /* more than 64k source lines */
+#ifdef _MSC_VER
+# pragma warning( disable: 4049 ) /* more than 64k source lines */
+#endif
/* verify that the <rpcndr.h> version is high enough to compile this file*/
diff --git a/src/3rdparty/iaccessible2/generated/x86/ia2_api_all_i.c b/src/3rdparty/iaccessible2/generated/x86/ia2_api_all_i.c
index c50b3e9a4f..61bb5ee5f7 100644
--- a/src/3rdparty/iaccessible2/generated/x86/ia2_api_all_i.c
+++ b/src/3rdparty/iaccessible2/generated/x86/ia2_api_all_i.c
@@ -18,7 +18,9 @@
*/
/* @@MIDL_FILE_HEADING( ) */
-#pragma warning( disable: 4049 ) /* more than 64k source lines */
+#ifdef _MSC_VER
+# pragma warning( disable: 4049 ) /* more than 64k source lines */
+#endif
#ifdef __cplusplus
@@ -65,7 +67,7 @@ typedef IID CLSID;
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
-#endif !_MIDL_USE_GUIDDEF_
+#endif // !_MIDL_USE_GUIDDEF_
MIDL_DEFINE_GUID(IID, IID_IAccessibleRelation,0x7CDF86EE,0xC3DA,0x496a,0xBD,0xA4,0x28,0x1B,0x33,0x6E,0x1F,0xDC);
diff --git a/src/3rdparty/icc/LICENSE.txt b/src/3rdparty/icc/LICENSE.txt
new file mode 100644
index 0000000000..e25b1d39f1
--- /dev/null
+++ b/src/3rdparty/icc/LICENSE.txt
@@ -0,0 +1,10 @@
+For the file sRGB2014.icc:
+
+Copyright International Color Consortium, 2015
+
+This profile is made available by the International Color Consortium, and may be copied,
+distributed, embedded, made, used, and sold without restriction. Altered versions of this
+profile shall have the original identification and copyright information removed and
+shall not be misrepresented as the original profile.
+
+(original source location: http://www.color.org/srgbprofiles.xalter)
diff --git a/src/3rdparty/icc/qt_attribution.json b/src/3rdparty/icc/qt_attribution.json
new file mode 100644
index 0000000000..7a1c813522
--- /dev/null
+++ b/src/3rdparty/icc/qt_attribution.json
@@ -0,0 +1,15 @@
+[
+ {
+ "Id": "icc-sRGB-color-profile",
+ "Name": "sRGB color profile icc file",
+ "QDocModule": "qtgui",
+ "QtUsage": "Used in Qt Gui (Embedded into PDF/A-1b files generated by QPrinter/QPdfWriter).",
+ "Files": "sRGB2014.icc",
+
+ "Description": "An ICC color profile for PDF/A-1b compatible PDF files.",
+ "LicenseId": "ICC License",
+ "License": "International Color Consortium License",
+ "LicenseFile": "LICENSE.txt",
+ "Copyright": "Copyright International Color Consortium, 2015"
+ }
+]
diff --git a/src/3rdparty/icc/sRGB2014.icc b/src/3rdparty/icc/sRGB2014.icc
new file mode 100644
index 0000000000..49afbfef10
--- /dev/null
+++ b/src/3rdparty/icc/sRGB2014.icc
Binary files differ
diff --git a/src/3rdparty/pcre2/AUTHORS b/src/3rdparty/pcre2/AUTHORS
index d9a0e15690..e056ad6868 100644
--- a/src/3rdparty/pcre2/AUTHORS
+++ b/src/3rdparty/pcre2/AUTHORS
@@ -8,7 +8,7 @@ Email domain: cam.ac.uk
University of Cambridge Computing Service,
Cambridge, England.
-Copyright (c) 1997-2016 University of Cambridge
+Copyright (c) 1997-2017 University of Cambridge
All rights reserved
@@ -19,7 +19,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
-Copyright(c) 2010-2016 Zoltan Herczeg
+Copyright(c) 2010-2017 Zoltan Herczeg
All rights reserved.
@@ -30,7 +30,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
-Copyright(c) 2009-2016 Zoltan Herczeg
+Copyright(c) 2009-2017 Zoltan Herczeg
All rights reserved.
####
diff --git a/src/3rdparty/pcre2/LICENCE b/src/3rdparty/pcre2/LICENCE
index 6600a65907..2b34d3f62b 100644
--- a/src/3rdparty/pcre2/LICENCE
+++ b/src/3rdparty/pcre2/LICENCE
@@ -5,9 +5,10 @@ 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 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.
+specified below, with one exemption for certain binary redistributions. 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 just-in-time compiler that can be used to
@@ -25,7 +26,7 @@ Email domain: cam.ac.uk
University of Cambridge Computing Service,
Cambridge, England.
-Copyright (c) 1997-2016 University of Cambridge
+Copyright (c) 1997-2017 University of Cambridge
All rights reserved.
@@ -36,7 +37,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
-Copyright(c) 2010-2016 Zoltan Herczeg
+Copyright(c) 2010-2017 Zoltan Herczeg
All rights reserved.
@@ -47,7 +48,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
-Copyright(c) 2009-2016 Zoltan Herczeg
+Copyright(c) 2009-2017 Zoltan Herczeg
All rights reserved.
@@ -57,11 +58,11 @@ THE "BSD" LICENCE
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice,
+ * Redistributions of source code must retain the above copyright notices,
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
+ notices, 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 any
@@ -80,4 +81,14 @@ 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.
+
+EXEMPTION FOR BINARY LIBRARY-LIKE PACKAGES
+------------------------------------------
+
+The second condition in the BSD licence (covering binary redistributions) does
+not apply all the way down a chain of software. If binary package A includes
+PCRE2, it must respect the condition, but if package B is software that
+includes package A, the condition is not imposed on package B unless it uses
+PCRE2 independently.
+
End
diff --git a/src/3rdparty/pcre2/qt_attribution.json b/src/3rdparty/pcre2/qt_attribution.json
index bcf7650993..33c1a58878 100644
--- a/src/3rdparty/pcre2/qt_attribution.json
+++ b/src/3rdparty/pcre2/qt_attribution.json
@@ -6,12 +6,12 @@
"Description": "The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl 5.",
"Homepage": "http://www.pcre.org/",
- "Version": "10.22",
+ "Version": "10.30",
"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": "Copyright (c) 1997-2017 University of Cambridge
+Copyright (c) 2009-2017 Zoltan Herczeg
Copyright (c) 2007-2012 Google Inc.
Copyright (c) 2013-2013 Tilera Corporation (jiwang@tilera.com)"
}
diff --git a/src/3rdparty/pcre2/src/config.h b/src/3rdparty/pcre2/src/config.h
index fbebfe6be0..eeade9d9ce 100644
--- a/src/3rdparty/pcre2/src/config.h
+++ b/src/3rdparty/pcre2/src/config.h
@@ -7,8 +7,9 @@
#define HAVE_STRING_H 1
#define LINK_SIZE 2
+#define HEAP_LIMIT 20000000
#define MATCH_LIMIT 10000000
-#define MATCH_LIMIT_RECURSION MATCH_LIMIT
+#define MATCH_LIMIT_DEPTH MATCH_LIMIT
#define MAX_NAME_COUNT 10000
#define MAX_NAME_SIZE 32
#define NEWLINE_DEFAULT 2
diff --git a/src/3rdparty/pcre2/src/pcre2.h b/src/3rdparty/pcre2/src/pcre2.h
index 20d221b803..5a4533909d 100644
--- a/src/3rdparty/pcre2/src/pcre2.h
+++ b/src/3rdparty/pcre2/src/pcre2.h
@@ -5,7 +5,7 @@
/* This is the public header file for the PCRE library, second API, to be
#included by applications that call PCRE2 functions.
- Copyright (c) 2016 University of Cambridge
+ Copyright (c) 2016-2017 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -36,15 +36,15 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
-#ifndef _PCRE2_H
-#define _PCRE2_H
+#ifndef PCRE2_H_IDEMPOTENT_GUARD
+#define PCRE2_H_IDEMPOTENT_GUARD
/* The current PCRE version information. */
#define PCRE2_MAJOR 10
-#define PCRE2_MINOR 22
+#define PCRE2_MINOR 30
#define PCRE2_PRERELEASE
-#define PCRE2_DATE 2016-07-29
+#define PCRE2_DATE 2017-08-14
/* 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
@@ -67,6 +67,20 @@ don't change existing definitions of PCRE2_EXP_DECL. */
# endif
#endif
+/* When compiling with the MSVC compiler, it is sometimes necessary to include
+a "calling convention" before exported function names. (This is secondhand
+information; I know nothing about MSVC myself). For example, something like
+
+ void __cdecl function(....)
+
+might be needed. In order so make this easy, all the exported functions have
+PCRE2_CALL_CONVENTION just before their names. It is rarely needed; if not
+set, we ensure here that it has no effect. */
+
+#ifndef PCRE2_CALL_CONVENTION
+#define PCRE2_CALL_CONVENTION
+#endif
+
/* Have to include limits.h, stdlib.h and stdint.h to ensure that size_t and
uint8_t, UCHAR_MAX, etc are defined. */
@@ -87,6 +101,7 @@ others can be added next to them */
#define PCRE2_ANCHORED 0x80000000u
#define PCRE2_NO_UTF_CHECK 0x40000000u
+#define PCRE2_ENDANCHORED 0x20000000u
/* The following option bits can be passed only to pcre2_compile(). However,
they may affect compilation, JIT compilation, and/or interpretive execution.
@@ -122,6 +137,15 @@ D is inspected during pcre2_dfa_match() execution
#define PCRE2_ALT_CIRCUMFLEX 0x00200000u /* J M D */
#define PCRE2_ALT_VERBNAMES 0x00400000u /* C */
#define PCRE2_USE_OFFSET_LIMIT 0x00800000u /* J M D */
+#define PCRE2_EXTENDED_MORE 0x01000000u /* C */
+#define PCRE2_LITERAL 0x02000000u /* C */
+
+/* An additional compile options word is available in the compile context. */
+
+#define PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES 0x00000001u /* C */
+#define PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL 0x00000002u /* C */
+#define PCRE2_EXTRA_MATCH_WORD 0x00000004u /* C */
+#define PCRE2_EXTRA_MATCH_LINE 0x00000008u /* C */
/* These are for pcre2_jit_compile(). */
@@ -160,6 +184,16 @@ ignored for pcre2_jit_match(). */
#define PCRE2_NO_JIT 0x00002000u
+/* Options for pcre2_pattern_convert(). */
+
+#define PCRE2_CONVERT_UTF 0x00000001u
+#define PCRE2_CONVERT_NO_UTF_CHECK 0x00000002u
+#define PCRE2_CONVERT_POSIX_BASIC 0x00000004u
+#define PCRE2_CONVERT_POSIX_EXTENDED 0x00000008u
+#define PCRE2_CONVERT_GLOB 0x00000010u
+#define PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR 0x00000030u
+#define PCRE2_CONVERT_GLOB_NO_STARSTAR 0x00000050u
+
/* 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. */
@@ -169,6 +203,7 @@ greater than zero. */
#define PCRE2_NEWLINE_CRLF 3
#define PCRE2_NEWLINE_ANY 4
#define PCRE2_NEWLINE_ANYCRLF 5
+#define PCRE2_NEWLINE_NUL 6
#define PCRE2_BSR_UNICODE 1
#define PCRE2_BSR_ANYCRLF 2
@@ -242,7 +277,8 @@ numbers must not be changed. */
#define PCRE2_ERROR_NOUNIQUESUBSTRING (-50)
#define PCRE2_ERROR_NULL (-51)
#define PCRE2_ERROR_RECURSELOOP (-52)
-#define PCRE2_ERROR_RECURSIONLIMIT (-53)
+#define PCRE2_ERROR_DEPTHLIMIT (-53)
+#define PCRE2_ERROR_RECURSIONLIMIT (-53) /* Obsolete synonym */
#define PCRE2_ERROR_UNAVAILABLE (-54)
#define PCRE2_ERROR_UNSET (-55)
#define PCRE2_ERROR_BADOFFSETLIMIT (-56)
@@ -252,6 +288,9 @@ numbers must not be changed. */
#define PCRE2_ERROR_BADSUBSPATTERN (-60)
#define PCRE2_ERROR_TOOMANYREPLACE (-61)
#define PCRE2_ERROR_BADSERIALIZEDDATA (-62)
+#define PCRE2_ERROR_HEAPLIMIT (-63)
+#define PCRE2_ERROR_CONVERT_SYNTAX (-64)
+
/* Request types for pcre2_pattern_info() */
@@ -276,9 +315,12 @@ numbers must not be changed. */
#define PCRE2_INFO_NAMEENTRYSIZE 18
#define PCRE2_INFO_NAMETABLE 19
#define PCRE2_INFO_NEWLINE 20
-#define PCRE2_INFO_RECURSIONLIMIT 21
+#define PCRE2_INFO_DEPTHLIMIT 21
+#define PCRE2_INFO_RECURSIONLIMIT 21 /* Obsolete synonym */
#define PCRE2_INFO_SIZE 22
#define PCRE2_INFO_HASBACKSLASHC 23
+#define PCRE2_INFO_FRAMESIZE 24
+#define PCRE2_INFO_HEAPLIMIT 25
/* Request types for pcre2_config(). */
@@ -289,11 +331,13 @@ numbers must not be changed. */
#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_DEPTHLIMIT 7
+#define PCRE2_CONFIG_RECURSIONLIMIT 7 /* Obsolete synonym */
+#define PCRE2_CONFIG_STACKRECURSE 8 /* Obsolete */
#define PCRE2_CONFIG_UNICODE 9
#define PCRE2_CONFIG_UNICODE_VERSION 10
#define PCRE2_CONFIG_VERSION 11
+#define PCRE2_CONFIG_HEAPLIMIT 12
/* Types for code units in patterns and subject strings. */
@@ -328,6 +372,9 @@ 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_convert_context; \
+typedef struct pcre2_real_convert_context pcre2_convert_context; \
+\
struct pcre2_real_code; \
typedef struct pcre2_real_code pcre2_code; \
\
@@ -386,170 +433,220 @@ 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 *);
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION 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 *);
+PCRE2_EXP_DECL pcre2_general_context PCRE2_CALL_CONVENTION \
+ *pcre2_general_context_copy(pcre2_general_context *); \
+PCRE2_EXP_DECL pcre2_general_context PCRE2_CALL_CONVENTION \
+ *pcre2_general_context_create(void *(*)(PCRE2_SIZE, void *), \
+ void (*)(void *, void *), void *); \
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ 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 *);
+PCRE2_EXP_DECL pcre2_compile_context PCRE2_CALL_CONVENTION \
+ *pcre2_compile_context_copy(pcre2_compile_context *); \
+PCRE2_EXP_DECL pcre2_compile_context PCRE2_CALL_CONVENTION \
+ *pcre2_compile_context_create(pcre2_general_context *);\
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_compile_context_free(pcre2_compile_context *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_bsr(pcre2_compile_context *, uint32_t); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_character_tables(pcre2_compile_context *, const unsigned char *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_compile_extra_options(pcre2_compile_context *, uint32_t); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_max_pattern_length(pcre2_compile_context *, PCRE2_SIZE); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_newline(pcre2_compile_context *, uint32_t); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_parens_nest_limit(pcre2_compile_context *, uint32_t); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ 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 *);
+PCRE2_EXP_DECL pcre2_match_context PCRE2_CALL_CONVENTION \
+ *pcre2_match_context_copy(pcre2_match_context *); \
+PCRE2_EXP_DECL pcre2_match_context PCRE2_CALL_CONVENTION \
+ *pcre2_match_context_create(pcre2_general_context *); \
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_match_context_free(pcre2_match_context *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_callout(pcre2_match_context *, \
+ int (*)(pcre2_callout_block *, void *), void *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_depth_limit(pcre2_match_context *, uint32_t); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_heap_limit(pcre2_match_context *, uint32_t); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_match_limit(pcre2_match_context *, uint32_t); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_offset_limit(pcre2_match_context *, PCRE2_SIZE); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_recursion_limit(pcre2_match_context *, uint32_t); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_recursion_memory_management(pcre2_match_context *, \
+ void *(*)(PCRE2_SIZE, void *), void (*)(void *, void *), void *);
+
+#define PCRE2_CONVERT_CONTEXT_FUNCTIONS \
+PCRE2_EXP_DECL pcre2_convert_context PCRE2_CALL_CONVENTION \
+ *pcre2_convert_context_copy(pcre2_convert_context *); \
+PCRE2_EXP_DECL pcre2_convert_context PCRE2_CALL_CONVENTION \
+ *pcre2_convert_context_create(pcre2_general_context *); \
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_convert_context_free(pcre2_convert_context *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_glob_escape(pcre2_convert_context *, uint32_t); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_set_glob_separator(pcre2_convert_context *, uint32_t);
/* 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 *);
+PCRE2_EXP_DECL pcre2_code PCRE2_CALL_CONVENTION \
+ *pcre2_compile(PCRE2_SPTR, PCRE2_SIZE, uint32_t, int *, PCRE2_SIZE *, \
+ pcre2_compile_context *); \
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_code_free(pcre2_code *); \
+PCRE2_EXP_DECL pcre2_code PCRE2_CALL_CONVENTION \
+ *pcre2_code_copy(const pcre2_code *); \
+PCRE2_EXP_DECL pcre2_code PCRE2_CALL_CONVENTION \
+ *pcre2_code_copy_with_tables(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 *);
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_pattern_info(const pcre2_code *, uint32_t, void *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ 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 *);
+PCRE2_EXP_DECL pcre2_match_data PCRE2_CALL_CONVENTION \
+ *pcre2_match_data_create(uint32_t, pcre2_general_context *); \
+PCRE2_EXP_DECL pcre2_match_data PCRE2_CALL_CONVENTION \
+ *pcre2_match_data_create_from_pattern(const pcre2_code *, \
+ pcre2_general_context *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ 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_CALL_CONVENTION \
+ pcre2_match(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, \
+ uint32_t, pcre2_match_data *, pcre2_match_context *); \
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_match_data_free(pcre2_match_data *); \
+PCRE2_EXP_DECL PCRE2_SPTR PCRE2_CALL_CONVENTION \
+ pcre2_get_mark(pcre2_match_data *); \
+PCRE2_EXP_DECL uint32_t PCRE2_CALL_CONVENTION \
+ pcre2_get_ovector_count(pcre2_match_data *); \
+PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \
+ *pcre2_get_ovector_pointer(pcre2_match_data *); \
+PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \
+ 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 **);
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_substring_copy_byname(pcre2_match_data *, PCRE2_SPTR, PCRE2_UCHAR *, \
+ PCRE2_SIZE *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_substring_copy_bynumber(pcre2_match_data *, uint32_t, PCRE2_UCHAR *, \
+ PCRE2_SIZE *); \
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_substring_free(PCRE2_UCHAR *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_substring_get_byname(pcre2_match_data *, PCRE2_SPTR, PCRE2_UCHAR **, \
+ PCRE2_SIZE *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_substring_get_bynumber(pcre2_match_data *, uint32_t, PCRE2_UCHAR **, \
+ PCRE2_SIZE *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_substring_length_byname(pcre2_match_data *, PCRE2_SPTR, PCRE2_SIZE *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_substring_length_bynumber(pcre2_match_data *, uint32_t, PCRE2_SIZE *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_substring_nametable_scan(const pcre2_code *, PCRE2_SPTR, PCRE2_SPTR *, \
+ PCRE2_SPTR *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_substring_number_from_name(const pcre2_code *, PCRE2_SPTR); \
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_substring_list_free(PCRE2_SPTR *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ 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 *);
+PCRE2_EXP_DECL int32_t PCRE2_CALL_CONVENTION \
+ pcre2_serialize_encode(const pcre2_code **, int32_t, uint8_t **, \
+ PCRE2_SIZE *, pcre2_general_context *); \
+PCRE2_EXP_DECL int32_t PCRE2_CALL_CONVENTION \
+ pcre2_serialize_decode(pcre2_code **, int32_t, const uint8_t *, \
+ pcre2_general_context *); \
+PCRE2_EXP_DECL int32_t PCRE2_CALL_CONVENTION \
+ pcre2_serialize_get_number_of_codes(const uint8_t *); \
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ 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 *);
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ 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 converting pattern source strings. */
+
+#define PCRE2_CONVERT_FUNCTIONS \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_pattern_convert(PCRE2_SPTR, PCRE2_SIZE, uint32_t, PCRE2_UCHAR **, \
+ PCRE2_SIZE *, pcre2_convert_context *); \
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_converted_pattern_free(PCRE2_UCHAR *);
/* 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 *);
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_jit_compile(pcre2_code *, uint32_t); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ 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_CALL_CONVENTION \
+ pcre2_jit_free_unused_memory(pcre2_general_context *); \
+PCRE2_EXP_DECL pcre2_jit_stack PCRE2_CALL_CONVENTION \
+ *pcre2_jit_stack_create(PCRE2_SIZE, PCRE2_SIZE, pcre2_general_context *); \
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_jit_stack_assign(pcre2_match_context *, pcre2_jit_callback, void *); \
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ 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 *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_get_error_message(int, PCRE2_UCHAR *, PCRE2_SIZE); \
+PCRE2_EXP_DECL const uint8_t PCRE2_CALL_CONVENTION \
+ *pcre2_maketables(pcre2_general_context *); \
/* Define macros that generate width-specific names from generic versions. The
@@ -576,6 +673,7 @@ pcre2_compile are called by application code. */
#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_convert_context PCRE2_SUFFIX(pcre2_real_convert_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_)
@@ -587,6 +685,7 @@ pcre2_compile are called by application code. */
#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_convert_context PCRE2_SUFFIX(pcre2_convert_context_)
#define pcre2_match_context PCRE2_SUFFIX(pcre2_match_context_)
#define pcre2_match_data PCRE2_SUFFIX(pcre2_match_data_)
@@ -595,12 +694,17 @@ pcre2_compile are called by application code. */
#define pcre2_callout_enumerate PCRE2_SUFFIX(pcre2_callout_enumerate_)
#define pcre2_code_copy PCRE2_SUFFIX(pcre2_code_copy_)
+#define pcre2_code_copy_with_tables PCRE2_SUFFIX(pcre2_code_copy_with_tables_)
#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_convert_context_copy PCRE2_SUFFIX(pcre2_convert_context_copy_)
+#define pcre2_convert_context_create PCRE2_SUFFIX(pcre2_convert_context_create_)
+#define pcre2_convert_context_free PCRE2_SUFFIX(pcre2_convert_context_free_)
+#define pcre2_converted_pattern_free PCRE2_SUFFIX(pcre2_converted_pattern_free_)
#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_)
@@ -624,6 +728,7 @@ pcre2_compile are called by application code. */
#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_convert PCRE2_SUFFIX(pcre2_pattern_convert_)
#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_)
@@ -632,14 +737,17 @@ pcre2_compile are called by application code. */
#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_extra_options PCRE2_SUFFIX(pcre2_set_compile_extra_options_)
#define pcre2_set_compile_recursion_guard PCRE2_SUFFIX(pcre2_set_compile_recursion_guard_)
+#define pcre2_set_depth_limit PCRE2_SUFFIX(pcre2_set_depth_limit_)
+#define pcre2_set_glob_escape PCRE2_SUFFIX(pcre2_set_glob_escape_)
+#define pcre2_set_glob_separator PCRE2_SUFFIX(pcre2_set_glob_separator_)
+#define pcre2_set_heap_limit PCRE2_SUFFIX(pcre2_set_heap_limit_)
#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_)
@@ -653,6 +761,11 @@ pcre2_compile are called by application code. */
#define pcre2_substring_nametable_scan PCRE2_SUFFIX(pcre2_substring_nametable_scan_)
#define pcre2_substring_number_from_name PCRE2_SUFFIX(pcre2_substring_number_from_name_)
+/* Keep this old function name for backwards compatibility */
+#define pcre2_set_recursion_limit PCRE2_SUFFIX(pcre2_set_recursion_limit_)
+
+/* Keep this obsolete function for backwards compatibility: it is now a noop. */
+#define pcre2_set_recursion_memory_management PCRE2_SUFFIX(pcre2_set_recursion_memory_management_)
/* Now generate all three sets of width-specific structures and function
prototypes. */
@@ -663,6 +776,8 @@ PCRE2_STRUCTURE_LIST \
PCRE2_GENERAL_INFO_FUNCTIONS \
PCRE2_GENERAL_CONTEXT_FUNCTIONS \
PCRE2_COMPILE_CONTEXT_FUNCTIONS \
+PCRE2_CONVERT_CONTEXT_FUNCTIONS \
+PCRE2_CONVERT_FUNCTIONS \
PCRE2_MATCH_CONTEXT_FUNCTIONS \
PCRE2_COMPILE_FUNCTIONS \
PCRE2_PATTERN_INFO_FUNCTIONS \
@@ -692,6 +807,7 @@ PCRE2_TYPES_STRUCTURES_AND_FUNCTIONS
#undef PCRE2_GENERAL_INFO_FUNCTIONS
#undef PCRE2_GENERAL_CONTEXT_FUNCTIONS
#undef PCRE2_COMPILE_CONTEXT_FUNCTIONS
+#undef PCRE2_CONVERT_CONTEXT_FUNCTIONS
#undef PCRE2_MATCH_CONTEXT_FUNCTIONS
#undef PCRE2_COMPILE_FUNCTIONS
#undef PCRE2_PATTERN_INFO_FUNCTIONS
@@ -729,4 +845,6 @@ PCRE2_SUFFIX a no-op. Otherwise, generate an error. */
} /* extern "C" */
#endif
-#endif /* End of pcre2.h */
+#endif /* PCRE2_H_IDEMPOTENT_GUARD */
+
+/* End of pcre2.h */
diff --git a/src/3rdparty/pcre2/src/pcre2_auto_possess.c b/src/3rdparty/pcre2/src/pcre2_auto_possess.c
index 8d0fa896ec..ad3543f627 100644
--- a/src/3rdparty/pcre2/src/pcre2_auto_possess.c
+++ b/src/3rdparty/pcre2/src/pcre2_auto_possess.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016 University of Cambridge
+ New API code Copyright (c) 2016-2017 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -588,7 +588,7 @@ for(;;)
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. */
@@ -600,12 +600,14 @@ for(;;)
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];
+ /* Check each branch. We have to recurse a level for all but the last
+ branch. */
+
while (*next_code == OP_ALT)
{
if (!compare_opcodes(code, utf, cb, base_list, base_end, rec_limit))
@@ -621,8 +623,8 @@ for(;;)
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;
+ if (*next_code != OP_BRA && *next_code != OP_CBRA &&
+ *next_code != OP_ONCE) return FALSE;
do next_code += GET(next_code, 1); while (*next_code == OP_ALT);
@@ -1046,8 +1048,10 @@ but some compilers complain about an unreachable statement. */
/* 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.
+non-existent 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. The rec_limit catches
+overly complicated or large patterns. In these cases, the check just stops,
+leaving the remainder of the pattern unpossessified.
Arguments:
code points to start of the byte code
@@ -1061,17 +1065,17 @@ Returns: 0 for success
int
PRIV(auto_possessify)(PCRE2_UCHAR *code, BOOL utf, const compile_block *cb)
{
-register PCRE2_UCHAR c;
+PCRE2_UCHAR c;
PCRE2_SPTR end;
PCRE2_UCHAR *repeat_opcode;
uint32_t list[8];
-int rec_limit;
+int rec_limit = 1000; /* Was 10,000 but clang+ASAN uses a lot of stack. */
for (;;)
{
c = *code;
- if (c > OP_TABLE_LENGTH) return -1; /* Something gone wrong */
+ if (c >= OP_TABLE_LENGTH) return -1; /* Something gone wrong */
if (c >= OP_STAR && c <= OP_TYPEPOSUPTO)
{
@@ -1080,7 +1084,6 @@ for (;;)
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)
@@ -1137,7 +1140,6 @@ for (;;)
list[1] = (c & 1) == 0;
- rec_limit = 1000;
if (compare_opcodes(end, utf, cb, list, end, &rec_limit))
{
switch (c)
diff --git a/src/3rdparty/pcre2/src/pcre2_compile.c b/src/3rdparty/pcre2/src/pcre2_compile.c
index bb9736cd51..44ee2502c8 100644
--- a/src/3rdparty/pcre2/src/pcre2_compile.c
+++ b/src/3rdparty/pcre2/src/pcre2_compile.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016 University of Cambridge
+ New API code Copyright (c) 2016-2017 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -58,9 +58,14 @@ POSSIBILITY OF SUCH DAMAGE.
#define PRINTABLE(c) ((c) >= 32 && (c) < 127)
#endif
#include "pcre2_printint.c"
-#define CALL_PRINTINT
+#define DEBUG_CALL_PRINTINT
#endif
+/* Other debugging code can be enabled by these defines. */
+
+// #define DEBUG_SHOW_CAPTURES
+// #define DEBUG_SHOW_PARSED
+
/* There are a few things that vary with different code unit sizes. Handle them
by defining macros in order to minimize #if usage. */
@@ -79,16 +84,56 @@ by defining macros in order to minimize #if usage. */
#endif
#endif
+/* Macros to store and retrieve a PCRE2_SIZE value in the parsed pattern, which
+consists of uint32_t elements. Assume that if uint32_t can't hold it, two of
+them will be able to (i.e. assume a 64-bit world). */
+
+#if PCRE2_SIZE_MAX <= UINT32_MAX
+#define PUTOFFSET(s,p) *p++ = s
+#define GETOFFSET(s,p) s = *p++
+#define GETPLUSOFFSET(s,p) s = *(++p)
+#define READPLUSOFFSET(s,p) s = p[1]
+#define SKIPOFFSET(p) p++
+#define SIZEOFFSET 1
+#else
+#define PUTOFFSET(s,p) \
+ { *p++ = (uint32_t)(s >> 32); *p++ = (uint32_t)(s & 0xffffffff); }
+#define GETOFFSET(s,p) \
+ { s = ((PCRE2_SIZE)p[0] << 32) | (PCRE2_SIZE)p[1]; p += 2; }
+#define GETPLUSOFFSET(s,p) \
+ { s = ((PCRE2_SIZE)p[1] << 32) | (PCRE2_SIZE)p[2]; p += 2; }
+#define READPLUSOFFSET(s,p) \
+ { s = ((PCRE2_SIZE)p[1] << 32) | (PCRE2_SIZE)p[2]; }
+#define SKIPOFFSET(p) p += 2
+#define SIZEOFFSET 2
+#endif
+
+/* Macros for manipulating elements of the parsed pattern vector. */
+
+#define META_CODE(x) (x & 0xffff0000u)
+#define META_DATA(x) (x & 0x0000ffffu)
+#define META_DIFF(x,y) ((x-y)>>16)
+
/* Function definitions to allow mutual recursion */
+#ifdef SUPPORT_UNICODE
static unsigned int
- add_list_to_class(uint8_t *, PCRE2_UCHAR **, uint32_t, compile_block *,
- const uint32_t *, unsigned int);
+ add_list_to_class_internal(uint8_t *, PCRE2_UCHAR **, uint32_t,
+ compile_block *, const uint32_t *, unsigned int);
+#endif
+
+static int
+ compile_regex(uint32_t, PCRE2_UCHAR **, uint32_t **, int *, uint32_t,
+ uint32_t *, int32_t *, uint32_t *, int32_t *, branch_chain *,
+ compile_block *, PCRE2_SIZE *);
+
+static int
+ get_branchlength(uint32_t **, int *, int *, parsed_recurse_check *,
+ compile_block *);
static BOOL
- 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 *);
+ set_lookbehind_lengths(uint32_t **, int *, int *, parsed_recurse_check *,
+ compile_block *);
@@ -96,9 +141,15 @@ static BOOL
* Code parameters and static tables *
*************************************************/
-/* 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.
+#define MAX_GROUP_NUMBER 65535u
+#define MAX_REPEAT_COUNT 65535u
+#define REPEAT_UNLIMITED (MAX_REPEAT_COUNT+1)
+
+/* COMPILE_WORK_SIZE specifies the size of stack workspace, which is used in
+different ways in the different pattern scans. The parsing and group-
+identifying pre-scan uses it to handle nesting, and needs it to be 16-bit
+aligned for this. Having defined the size in code units, we set up
+C16_WORK_SIZE as the number of elements in the 16-bit vector.
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
@@ -107,16 +158,18 @@ 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.
-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. */
+In the real compile phase, this workspace is not currently used. */
-#define COMPILE_WORK_SIZE (2048*LINK_SIZE) /* Size in code units */
+#define COMPILE_WORK_SIZE (3000*LINK_SIZE) /* Size in code units */
-#define C32_WORK_SIZE \
- ((COMPILE_WORK_SIZE * sizeof(PCRE2_UCHAR))/sizeof(uint32_t))
+#define C16_WORK_SIZE \
+ ((COMPILE_WORK_SIZE * sizeof(PCRE2_UCHAR))/sizeof(uint16_t))
+
+/* A uint32_t vector is used for caching information about the size of
+capturing groups, to improve performance. A default is created on the stack of
+this size. */
+
+#define GROUPINFO_DEFAULT_SIZE 256
/* 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. */
@@ -130,25 +183,176 @@ 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. */
+/* The pre-compiling pass over the pattern creates a parsed pattern in a vector
+of uint32_t. For short patterns this lives on the stack, with this size. Heap
+memory is used for longer patterns. */
-#define COPIED_PATTERN_SIZE 1024
+#define PARSED_PATTERN_DEFAULT_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. */
+than INT_MAX to allow for adding in group terminating code units, so that we
+don't have to check them every time. */
#define OFLOW_MAX (INT_MAX - 20)
+/* Code values for parsed patterns, which are stored in a vector of 32-bit
+unsigned ints. Values less than META_END are literal data values. The coding
+for identifying the item is in the top 16-bits, leaving 16 bits for the
+additional data that some of them need. The META_CODE, META_DATA, and META_DIFF
+macros are used to manipulate parsed pattern elements.
+
+NOTE: When these definitions are changed, the table of extra lengths for each
+code (meta_extra_lengths, just below) must be updated to remain in step. */
+
+#define META_END 0x80000000u /* End of pattern */
+
+#define META_ALT 0x80010000u /* alternation */
+#define META_ATOMIC 0x80020000u /* atomic group */
+#define META_BACKREF 0x80030000u /* Back ref */
+#define META_BACKREF_BYNAME 0x80040000u /* \k'name' */
+#define META_BIGVALUE 0x80050000u /* Next is a literal > META_END */
+#define META_CALLOUT_NUMBER 0x80060000u /* (?C with numerical argument */
+#define META_CALLOUT_STRING 0x80070000u /* (?C with string argument */
+#define META_CAPTURE 0x80080000u /* Capturing parenthesis */
+#define META_CIRCUMFLEX 0x80090000u /* ^ metacharacter */
+#define META_CLASS 0x800a0000u /* start non-empty class */
+#define META_CLASS_EMPTY 0x800b0000u /* empty class */
+#define META_CLASS_EMPTY_NOT 0x800c0000u /* negative empty class */
+#define META_CLASS_END 0x800d0000u /* end of non-empty class */
+#define META_CLASS_NOT 0x800e0000u /* start non-empty negative class */
+#define META_COND_ASSERT 0x800f0000u /* (?(?assertion)... */
+#define META_COND_DEFINE 0x80100000u /* (?(DEFINE)... */
+#define META_COND_NAME 0x80110000u /* (?(<name>)... */
+#define META_COND_NUMBER 0x80120000u /* (?(digits)... */
+#define META_COND_RNAME 0x80130000u /* (?(R&name)... */
+#define META_COND_RNUMBER 0x80140000u /* (?(Rdigits)... */
+#define META_COND_VERSION 0x80150000u /* (?(VERSION<op>x.y)... */
+#define META_DOLLAR 0x80160000u /* $ metacharacter */
+#define META_DOT 0x80170000u /* . metacharacter */
+#define META_ESCAPE 0x80180000u /* \d and friends */
+#define META_KET 0x80190000u /* closing parenthesis */
+#define META_NOCAPTURE 0x801a0000u /* no capture parens */
+#define META_OPTIONS 0x801b0000u /* (?i) and friends */
+#define META_POSIX 0x801c0000u /* POSIX class item */
+#define META_POSIX_NEG 0x801d0000u /* negative POSIX class item */
+#define META_RANGE_ESCAPED 0x801e0000u /* range with at least one escape */
+#define META_RANGE_LITERAL 0x801f0000u /* range defined literally */
+#define META_RECURSE 0x80200000u /* Recursion */
+#define META_RECURSE_BYNAME 0x80210000u /* (?&name) */
+
+/* These must be kept together to make it easy to check that an assertion
+is present where expected in a conditional group. */
+
+#define META_LOOKAHEAD 0x80220000u /* (?= */
+#define META_LOOKAHEADNOT 0x80230000u /* (?! */
+#define META_LOOKBEHIND 0x80240000u /* (?<= */
+#define META_LOOKBEHINDNOT 0x80250000u /* (?<! */
+
+/* These must be kept in this order, with consecutive values, and the _ARG
+versions of PRUNE, SKIP, and THEN immediately after their non-argument
+versions. */
+
+#define META_MARK 0x80260000u /* (*MARK) */
+#define META_ACCEPT 0x80270000u /* (*ACCEPT) */
+#define META_COMMIT 0x80280000u /* (*COMMIT) */
+#define META_FAIL 0x80290000u /* (*FAIL) */
+#define META_PRUNE 0x802a0000u /* These pairs must */
+#define META_PRUNE_ARG 0x802b0000u /* be */
+#define META_SKIP 0x802c0000u /* kept */
+#define META_SKIP_ARG 0x802d0000u /* in */
+#define META_THEN 0x802e0000u /* this */
+#define META_THEN_ARG 0x802f0000u /* order */
+
+/* These must be kept in groups of adjacent 3 values, and all together. */
+
+#define META_ASTERISK 0x80300000u /* * */
+#define META_ASTERISK_PLUS 0x80310000u /* *+ */
+#define META_ASTERISK_QUERY 0x80320000u /* *? */
+#define META_PLUS 0x80330000u /* + */
+#define META_PLUS_PLUS 0x80340000u /* ++ */
+#define META_PLUS_QUERY 0x80350000u /* +? */
+#define META_QUERY 0x80360000u /* ? */
+#define META_QUERY_PLUS 0x80370000u /* ?+ */
+#define META_QUERY_QUERY 0x80380000u /* ?? */
+#define META_MINMAX 0x80390000u /* {n,m} repeat */
+#define META_MINMAX_PLUS 0x803a0000u /* {n,m}+ repeat */
+#define META_MINMAX_QUERY 0x803b0000u /* {n,m}? repeat */
+
+#define META_FIRST_QUANTIFIER META_ASTERISK
+#define META_LAST_QUANTIFIER META_MINMAX_QUERY
+
+/* Table of extra lengths for each of the meta codes. Must be kept in step with
+the definitions above. For some items these values are a basic length to which
+a variable amount has to be added. */
+
+static unsigned char meta_extra_lengths[] = {
+ 0, /* META_END */
+ 0, /* META_ALT */
+ 0, /* META_ATOMIC */
+ 0, /* META_BACKREF - more if group is >= 10 */
+ 1+SIZEOFFSET, /* META_BACKREF_BYNAME */
+ 1, /* META_BIGVALUE */
+ 3, /* META_CALLOUT_NUMBER */
+ 3+SIZEOFFSET, /* META_CALLOUT_STRING */
+ 0, /* META_CAPTURE */
+ 0, /* META_CIRCUMFLEX */
+ 0, /* META_CLASS */
+ 0, /* META_CLASS_EMPTY */
+ 0, /* META_CLASS_EMPTY_NOT */
+ 0, /* META_CLASS_END */
+ 0, /* META_CLASS_NOT */
+ 0, /* META_COND_ASSERT */
+ SIZEOFFSET, /* META_COND_DEFINE */
+ 1+SIZEOFFSET, /* META_COND_NAME */
+ 1+SIZEOFFSET, /* META_COND_NUMBER */
+ 1+SIZEOFFSET, /* META_COND_RNAME */
+ 1+SIZEOFFSET, /* META_COND_RNUMBER */
+ 3, /* META_COND_VERSION */
+ 0, /* META_DOLLAR */
+ 0, /* META_DOT */
+ 0, /* META_ESCAPE - more for ESC_P, ESC_p, ESC_g, ESC_k */
+ 0, /* META_KET */
+ 0, /* META_NOCAPTURE */
+ 1, /* META_OPTIONS */
+ 1, /* META_POSIX */
+ 1, /* META_POSIX_NEG */
+ 0, /* META_RANGE_ESCAPED */
+ 0, /* META_RANGE_LITERAL */
+ SIZEOFFSET, /* META_RECURSE */
+ 1+SIZEOFFSET, /* META_RECURSE_BYNAME */
+ 0, /* META_LOOKAHEAD */
+ 0, /* META_LOOKAHEADNOT */
+ SIZEOFFSET, /* META_LOOKBEHIND */
+ SIZEOFFSET, /* META_LOOKBEHINDNOT */
+ 1, /* META_MARK - plus the string length */
+ 0, /* META_ACCEPT */
+ 0, /* META_COMMIT */
+ 0, /* META_FAIL */
+ 0, /* META_PRUNE */
+ 1, /* META_PRUNE_ARG - plus the string length */
+ 0, /* META_SKIP */
+ 1, /* META_SKIP_ARG - plus the string length */
+ 0, /* META_THEN */
+ 1, /* META_THEN_ARG - plus the string length */
+ 0, /* META_ASTERISK */
+ 0, /* META_ASTERISK_PLUS */
+ 0, /* META_ASTERISK_QUERY */
+ 0, /* META_PLUS */
+ 0, /* META_PLUS_PLUS */
+ 0, /* META_PLUS_QUERY */
+ 0, /* META_QUERY */
+ 0, /* META_QUERY_PLUS */
+ 0, /* META_QUERY_QUERY */
+ 2, /* META_MINMAX */
+ 2, /* META_MINMAX_PLUS */
+ 2 /* META_MINMAX_QUERY */
+};
+
+/* Types for skipping parts of a parsed pattern. */
+
+enum { PSKIP_ALT, PSKIP_CLASS, PSKIP_KET };
+
/* 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:
@@ -170,17 +374,10 @@ compiler is clever with identical subexpressions. */
/* 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_SET_FIXED_LENGTH 0x80000000u
+#define GI_NOT_FIXED_LENGTH 0x40000000u
#define GI_FIXED_LENGTH_MASK 0x0000ffffu
-/* 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
-
/* 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). */
@@ -191,8 +388,8 @@ comparison). */
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
+least in some simple cases I timed), and in some applications one wants PCRE2
+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
@@ -380,9 +577,9 @@ string is built from string macros so that it works in UTF-8 mode on EBCDIC
platforms. */
typedef struct verbitem {
- int len; /* Length of verb name */
- int op; /* Op when no arg, or -1 if arg mandatory */
- int op_arg; /* Op when arg present, or -1 if not allowed */
+ unsigned int len; /* Length of verb name */
+ uint32_t meta; /* Base META_ code */
+ int has_arg; /* Argument requirement */
} verbitem;
static const char verbnames[] =
@@ -397,32 +594,30 @@ static const char verbnames[] =
STRING_THEN;
static const verbitem verbs[] = {
- { 0, -1, OP_MARK },
- { 4, -1, OP_MARK },
- { 6, OP_ACCEPT, -1 },
- { 6, OP_COMMIT, -1 },
- { 1, OP_FAIL, -1 },
- { 4, OP_FAIL, -1 },
- { 5, OP_PRUNE, OP_PRUNE_ARG },
- { 4, OP_SKIP, OP_SKIP_ARG },
- { 4, OP_THEN, OP_THEN_ARG }
+ { 0, META_MARK, +1 }, /* > 0 => must have an argument */
+ { 4, META_MARK, +1 },
+ { 6, META_ACCEPT, -1 }, /* < 0 => must not have an argument */
+ { 6, META_COMMIT, -1 },
+ { 1, META_FAIL, -1 },
+ { 4, META_FAIL, -1 },
+ { 5, META_PRUNE, 0 }, /* Argument is optional; bump META code if found */
+ { 4, META_SKIP, 0 },
+ { 4, META_THEN, 0 }
};
static const int verbcount = sizeof(verbs)/sizeof(verbitem);
+/* Verb opcodes, indexed by their META code offset from META_MARK. */
-/* Substitutes for [[:<:]] and [[:>:]], which mean start and end of word in
-another regex library. */
-
-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 uint32_t verbops[] = {
+ OP_MARK, OP_ACCEPT, OP_COMMIT, OP_FAIL, OP_PRUNE, OP_PRUNE_ARG, OP_SKIP,
+ OP_SKIP_ARG, OP_THEN, OP_THEN_ARG };
-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' };
+/* Offsets from OP_STAR for case-independent and negative repeat opcodes. */
+static uint32_t chartypeoffset[] = {
+ OP_STAR - OP_STAR, OP_STARI - OP_STAR,
+ OP_NOTSTAR - OP_STAR, OP_NOTSTARI - OP_STAR };
/* Tables of names of POSIX character classes and their lengths. The names are
now all in a single string, to reduce the number of relocations when a shared
@@ -444,7 +639,6 @@ static const uint8_t posix_name_lengths[] = {
#define PC_PRINT 9
#define PC_PUNCT 10
-
/* Table of class bit maps for each POSIX class. Each class is formed from a
base map, with an optional addition or removal of another map. Then, for some
classes, there is some additional tweaking: for [:blank:] the vertical space
@@ -472,130 +666,53 @@ static const int posix_class_maps[] = {
cbit_xdigit,-1, 0 /* xdigit */
};
-/* Table of substitutes for \d etc when PCRE2_UCP is set. They are replaced by
-Unicode property escapes. */
-
#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 PCRE2_UCHAR string_pNd[] = {
- CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
- CHAR_N, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' };
-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 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 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 PCRE2_UCHAR string_pXwd[] = {
- CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
- CHAR_X, CHAR_w, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' };
-
-static PCRE2_SPTR substitutes[] = {
- string_PNd, /* \D */
- string_pNd, /* \d */
- string_PXsp, /* \S */ /* Xsp is Perl space, but from 8.34, Perl */
- string_pXsp, /* \s */ /* space and POSIX space are the same. */
- string_PXwd, /* \W */
- string_pXwd /* \w */
-};
-/* The POSIX class substitutes must be in the order of the POSIX class names,
-defined above, and there are both positive and negative cases. NULL means no
-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 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 PCRE2_UCHAR string_pLl[] = {
- CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET,
- CHAR_L, CHAR_l, CHAR_RIGHT_CURLY_BRACKET, '\0' };
-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 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 PCRE2_UCHAR string_h[] = {
- CHAR_BACKSLASH, CHAR_h, '\0' };
-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 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 PCRE2_UCHAR string_PLl[] = {
- CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET,
- CHAR_L, CHAR_l, CHAR_RIGHT_CURLY_BRACKET, '\0' };
-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 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 PCRE2_UCHAR string_H[] = {
- CHAR_BACKSLASH, CHAR_H, '\0' };
-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 PCRE2_SPTR posix_substitutes[] = {
- string_pL, /* alpha */
- string_pLl, /* lower */
- string_pLu, /* upper */
- string_pXan, /* alnum */
- NULL, /* ascii */
- string_h, /* blank */
- string_pCc, /* cntrl */
- string_pNd, /* digit */
- NULL, /* graph */
- NULL, /* print */
- NULL, /* punct */
- string_pXps, /* space */ /* Xps is POSIX space, but from 8.34 */
- string_pXwd, /* word */ /* Perl and POSIX space are the same */
- NULL, /* xdigit */
- /* Negated cases */
- string_PL, /* ^alpha */
- string_PLl, /* ^lower */
- string_PLu, /* ^upper */
- string_PXan, /* ^alnum */
- NULL, /* ^ascii */
- string_H, /* ^blank */
- string_PCc, /* ^cntrl */
- string_PNd, /* ^digit */
- NULL, /* ^graph */
- NULL, /* ^print */
- NULL, /* ^punct */
- string_PXps, /* ^space */ /* Xps is POSIX space, but from 8.34 */
- string_PXwd, /* ^word */ /* Perl and POSIX space are the same */
- NULL /* ^xdigit */
+/* The POSIX class Unicode property substitutes that are used in UCP mode must
+be in the order of the POSIX class names, defined above. */
+
+static int posix_substitutes[] = {
+ PT_GC, ucp_L, /* alpha */
+ PT_PC, ucp_Ll, /* lower */
+ PT_PC, ucp_Lu, /* upper */
+ PT_ALNUM, 0, /* alnum */
+ -1, 0, /* ascii, treat as non-UCP */
+ -1, 1, /* blank, treat as \h */
+ PT_PC, ucp_Cc, /* cntrl */
+ PT_PC, ucp_Nd, /* digit */
+ PT_PXGRAPH, 0, /* graph */
+ PT_PXPRINT, 0, /* print */
+ PT_PXPUNCT, 0, /* punct */
+ PT_PXSPACE, 0, /* space */ /* Xps is POSIX space, but from 8.34 */
+ PT_WORD, 0, /* word */ /* Perl and POSIX space are the same */
+ -1, 0 /* xdigit, treat as non-UCP */
};
-#define POSIX_SUBSIZE (sizeof(posix_substitutes) / sizeof(PCRE2_UCHAR *))
+#define POSIX_SUBSIZE (sizeof(posix_substitutes) / (2*sizeof(uint32_t)))
#endif /* SUPPORT_UNICODE */
-/* Masks for checking option settings. */
+/* Masks for checking option settings. When PCRE2_LITERAL is set, only a subset
+are allowed. */
+
+#define PUBLIC_LITERAL_COMPILE_OPTIONS \
+ (PCRE2_ANCHORED|PCRE2_AUTO_CALLOUT|PCRE2_CASELESS|PCRE2_ENDANCHORED| \
+ PCRE2_FIRSTLINE|PCRE2_LITERAL|PCRE2_NO_START_OPTIMIZE| \
+ PCRE2_NO_UTF_CHECK|PCRE2_USE_OFFSET_LIMIT|PCRE2_UTF)
#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)
+ (PUBLIC_LITERAL_COMPILE_OPTIONS| \
+ PCRE2_ALLOW_EMPTY_CLASS|PCRE2_ALT_BSUX|PCRE2_ALT_CIRCUMFLEX| \
+ PCRE2_ALT_VERBNAMES|PCRE2_DOLLAR_ENDONLY|PCRE2_DOTALL|PCRE2_DUPNAMES| \
+ PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|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_UCP|PCRE2_UNGREEDY)
+
+#define PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS \
+ (PCRE2_EXTRA_MATCH_LINE|PCRE2_EXTRA_MATCH_WORD)
+
+#define PUBLIC_COMPILE_EXTRA_OPTIONS \
+ (PUBLIC_LITERAL_COMPILE_EXTRA_OPTIONS| \
+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES|PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL)
/* 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
@@ -611,21 +728,8 @@ enum { ERR0 = COMPILE_ERROR_BASE,
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[] =
- {
- 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 */
- };
+ ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88, ERR89, ERR90,
+ ERR91, ERR92};
/* 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
@@ -636,8 +740,9 @@ 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_LIMH, /* Read integer value for heap limit */
PSO_LIMM, /* Read integer value for match limit */
- PSO_LIMR }; /* Read integer value for recursion limit */
+ PSO_LIMD }; /* Read integer value for depth limit */
typedef struct pso {
const uint8_t *name;
@@ -658,12 +763,15 @@ static pso pso_list[] = {
{ (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_HEAP_EQ, 11, PSO_LIMH, 0 },
{ (uint8_t *)STRING_LIMIT_MATCH_EQ, 12, PSO_LIMM, 0 },
- { (uint8_t *)STRING_LIMIT_RECURSION_EQ, 16, PSO_LIMR, 0 },
+ { (uint8_t *)STRING_LIMIT_DEPTH_EQ, 12, PSO_LIMD, 0 },
+ { (uint8_t *)STRING_LIMIT_RECURSION_EQ, 16, PSO_LIMD, 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_NUL_RIGHTPAR, 4, PSO_NL, PCRE2_NEWLINE_NUL },
{ (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 }
@@ -728,1056 +836,535 @@ static const uint8_t opcode_possessify[] = {
};
-
+#ifdef DEBUG_SHOW_PARSED
/*************************************************
-* Copy compiled code *
+* Show the parsed pattern for debugging *
*************************************************/
-/* Compiled JIT code cannot be copied, so the new compiled block has no
-associated JIT data. */
+/* For debugging the pre-scan, this code, which outputs the parsed data vector,
+can be enabled. */
-PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION
-pcre2_code_copy(const pcre2_code *code)
+static void show_parsed(compile_block *cb)
{
-PCRE2_SIZE* ref_count;
-pcre2_code *newcode;
+uint32_t *pptr = cb->parsed_pattern;
-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;
-
-/* If the code is one that has been deserialized, increment the reference count
-in the decoded tables. */
-
-if ((code->flags & PCRE2_DEREF_TABLES) != 0)
+for (;;)
{
- ref_count = (PCRE2_SIZE *)(code->tables + tables_length);
- (*ref_count)++;
- }
-
-return newcode;
-}
+ int max, min;
+ PCRE2_SIZE offset;
+ uint32_t i;
+ uint32_t length;
+ uint32_t meta_arg = META_DATA(*pptr);
+ fprintf(stderr, "+++ %02d %.8x ", (int)(pptr - cb->parsed_pattern), *pptr);
-
-/*************************************************
-* Free compiled code *
-*************************************************/
-
-PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
-pcre2_code_free(pcre2_code *code)
-{
-PCRE2_SIZE* ref_count;
-
-if (code != NULL)
- {
- if (code->executable_jit != NULL)
- PRIV(jit_free)(code->executable_jit, &code->memctl);
-
- if ((code->flags & PCRE2_DEREF_TABLES) != 0)
+ if (*pptr < META_END)
{
- /* 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. */
-
- ref_count = (PCRE2_SIZE *)(code->tables + tables_length);
- if (*ref_count > 0)
- {
- (*ref_count)--;
- if (*ref_count == 0)
- code->memctl.free((void *)code->tables, code->memctl.memory_data);
- }
+ if (*pptr > 32 && *pptr < 128) fprintf(stderr, "%c", *pptr);
+ pptr++;
}
- code->memctl.free(code, code->memctl.memory_data);
- }
-}
-
-
-
-/*************************************************
-* Insert an automatic callout point *
-*************************************************/
-
-/* This function is called when the PCRE2_AUTO_CALLOUT option is set, to insert
-callout points before each pattern item.
-
-Arguments:
- code current code pointer
- ptr current pattern pointer
- cb general compile-time data
-
-Returns: new code pointer
-*/
-
-static PCRE2_UCHAR *
-auto_callout(PCRE2_UCHAR *code, PCRE2_SPTR ptr, compile_block *cb)
-{
-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];
-}
-
-
-
-/*************************************************
-* 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
- cb general compile-time data
-
-Returns: nothing
-*/
-
-static void
-complete_callout(PCRE2_UCHAR *previous_callout, PCRE2_SPTR ptr,
- compile_block *cb)
-{
-size_t length = (size_t)(ptr - cb->start_pattern - GET(previous_callout, 1));
-PUT(previous_callout, 1 + LINK_SIZE, length);
-}
-
-
-
-/*************************************************
-* 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 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 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 mode
- atend TRUE if called when the pattern is complete
- cb the "compile data" structure
- recurses chain of recurse_check to catch mutual recursion
- 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(PCRE2_UCHAR *code, BOOL utf, BOOL atend, compile_block *cb,
- recurse_check *recurses, int *countptr)
-{
-uint32_t length = 0xffffffffu; /* Unset */
-uint32_t group = 0;
-uint32_t groupinfo = 0;
-recurse_check this_recurse;
-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)
+ else switch (META_CODE(*pptr++))
{
- 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;
+ default:
+ fprintf(stderr, "**** OOPS - unknown META value - giving up ****\n");
+ return;
-/* 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. */
+ case META_END:
+ fprintf(stderr, "META_END\n");
+ return;
-for (;;)
- {
- int d;
- PCRE2_UCHAR *ce, *cs;
- register PCRE2_UCHAR op = *cc;
+ case META_CAPTURE:
+ fprintf(stderr, "META_CAPTURE %d", meta_arg);
+ break;
- if (branchlength > LOOKBEHIND_MAX) return FFL_TOOLONG;
+ case META_RECURSE:
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "META_RECURSE %d %zd", meta_arg, offset);
+ break;
- switch (op)
- {
- /* We only need to continue for OP_CBRA (normal capturing bracket) and
- OP_BRA (normal non-capturing bracket) because the other variants of these
- opcodes are all concerned with unlimited repeated groups, which of course
- are not of fixed length. */
-
- case OP_CBRA:
- case OP_BRA:
- case OP_ONCE:
- case OP_ONCE_NC:
- case OP_COND:
- d = find_fixedlength(cc, utf, atend, cb, recurses, countptr);
- if (d < 0) return d;
- branchlength += (uint32_t)d;
- do cc += GET(cc, 1); while (*cc == OP_ALT);
- cc += 1 + LINK_SIZE;
+ case META_BACKREF:
+ if (meta_arg < 10)
+ offset = cb->small_ref_offset[meta_arg];
+ else
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "META_BACKREF %d %zd", meta_arg, offset);
break;
- /* Reached end of a branch; if it's a ket it is the end of a nested call.
- If it's ALT it is an alternation in a nested call. An ACCEPT is effectively
- an ALT. If it is END it's the end of the outer call. All can be handled by
- the same code. Note that we must not include the OP_KETRxxx opcodes here,
- because they all imply an unlimited repeat. */
-
- case OP_ALT:
- case OP_KET:
- case OP_END:
- case OP_ACCEPT:
- case OP_ASSERT_ACCEPT:
- if (length == 0xffffffffu) length = branchlength;
- else if (length != branchlength) goto ISNOTFIXED;
- if (*cc != OP_ALT)
+ case META_ESCAPE:
+ if (meta_arg == ESC_P || meta_arg == ESC_p)
+ {
+ uint32_t ptype = *pptr >> 16;
+ uint32_t pvalue = *pptr++ & 0xffff;
+ fprintf(stderr, "META \\%c %d %d", (meta_arg == ESC_P)? 'P':'p',
+ ptype, pvalue);
+ }
+ else
{
- if (group > 0)
+ uint32_t cc;
+ /* There's just one escape we might have here that isn't negated in the
+ escapes table. */
+ if (meta_arg == ESC_g) cc = CHAR_g;
+ else for (cc = ESCAPES_FIRST; cc <= ESCAPES_LAST; cc++)
{
- groupinfo |= (uint32_t)(GI_SET_FIXED_LENGTH | length);
- cb->groupinfo[group] = groupinfo;
+ if (meta_arg == (uint32_t)(-escapes[cc - ESCAPES_FIRST])) break;
}
- return (int)length;
+ if (cc > ESCAPES_LAST) cc = CHAR_QUESTION_MARK;
+ fprintf(stderr, "META \\%c", cc);
}
- 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 FFL_LATER. */
-
- case OP_RECURSE:
- 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) 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) goto ISNOTFIXED; /* Mutual recursion */
- }
- this_recurse.prev = recurses;
- this_recurse.group = cs;
- d = find_fixedlength(cs, utf, atend, cb, &this_recurse, countptr);
- if (d < 0) return d;
- branchlength += (uint32_t)d;
- cc += 1 + LINK_SIZE;
+ case META_MINMAX:
+ min = *pptr++;
+ max = *pptr++;
+ if (max != REPEAT_UNLIMITED)
+ fprintf(stderr, "META {%d,%d}", min, max);
+ else
+ fprintf(stderr, "META {%d,}", min);
break;
- /* 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:
- case OP_ASSERTBACK:
- case OP_ASSERTBACK_NOT:
- do cc += GET(cc, 1); while (*cc == OP_ALT);
- cc += 1 + LINK_SIZE;
+ case META_MINMAX_QUERY:
+ min = *pptr++;
+ max = *pptr++;
+ if (max != REPEAT_UNLIMITED)
+ fprintf(stderr, "META {%d,%d}?", min, max);
+ else
+ fprintf(stderr, "META {%d,}?", min);
break;
- /* Skip over things that don't match chars */
-
- case OP_MARK:
- case OP_PRUNE_ARG:
- case OP_SKIP_ARG:
- case OP_THEN_ARG:
- cc += cc[1] + PRIV(OP_lengths)[*cc];
+ case META_MINMAX_PLUS:
+ min = *pptr++;
+ max = *pptr++;
+ if (max != REPEAT_UNLIMITED)
+ fprintf(stderr, "META {%d,%d}+", min, max);
+ else
+ fprintf(stderr, "META {%d,}+", min);
break;
- case OP_CALLOUT:
- case OP_CIRC:
- case OP_CIRCM:
- case OP_CLOSE:
- case OP_COMMIT:
- case OP_CREF:
- case OP_FALSE:
- case OP_TRUE:
- case OP_DNCREF:
- case OP_DNRREF:
- case OP_DOLL:
- case OP_DOLLM:
- case OP_EOD:
- case OP_EODN:
- case OP_FAIL:
- case OP_NOT_WORD_BOUNDARY:
- case OP_PRUNE:
- case OP_REVERSE:
- case OP_RREF:
- case OP_SET_SOM:
- case OP_SKIP:
- case OP_SOD:
- case OP_SOM:
- case OP_THEN:
- case OP_WORD_BOUNDARY:
- cc += PRIV(OP_lengths)[*cc];
+ case META_BIGVALUE: fprintf(stderr, "META_BIGVALUE %.8x", *pptr++); break;
+ case META_CIRCUMFLEX: fprintf(stderr, "META_CIRCUMFLEX"); break;
+ case META_COND_ASSERT: fprintf(stderr, "META_COND_ASSERT"); break;
+ case META_DOLLAR: fprintf(stderr, "META_DOLLAR"); break;
+ case META_DOT: fprintf(stderr, "META_DOT"); break;
+ case META_ASTERISK: fprintf(stderr, "META *"); break;
+ case META_ASTERISK_QUERY: fprintf(stderr, "META *?"); break;
+ case META_ASTERISK_PLUS: fprintf(stderr, "META *+"); break;
+ case META_PLUS: fprintf(stderr, "META +"); break;
+ case META_PLUS_QUERY: fprintf(stderr, "META +?"); break;
+ case META_PLUS_PLUS: fprintf(stderr, "META ++"); break;
+ case META_QUERY: fprintf(stderr, "META ?"); break;
+ case META_QUERY_QUERY: fprintf(stderr, "META ??"); break;
+ case META_QUERY_PLUS: fprintf(stderr, "META ?+"); break;
+
+ case META_ATOMIC: fprintf(stderr, "META (?>"); break;
+ case META_NOCAPTURE: fprintf(stderr, "META (?:"); break;
+ case META_LOOKAHEAD: fprintf(stderr, "META (?="); break;
+ case META_LOOKAHEADNOT: fprintf(stderr, "META (?!"); break;
+ case META_KET: fprintf(stderr, "META )"); break;
+ case META_ALT: fprintf(stderr, "META | %d", meta_arg); break;
+
+ case META_CLASS: fprintf(stderr, "META ["); break;
+ case META_CLASS_NOT: fprintf(stderr, "META [^"); break;
+ case META_CLASS_END: fprintf(stderr, "META ]"); break;
+ case META_CLASS_EMPTY: fprintf(stderr, "META []"); break;
+ case META_CLASS_EMPTY_NOT: fprintf(stderr, "META [^]"); break;
+
+ case META_RANGE_LITERAL: fprintf(stderr, "META - (literal)"); break;
+ case META_RANGE_ESCAPED: fprintf(stderr, "META - (escaped)"); break;
+
+ case META_POSIX: fprintf(stderr, "META_POSIX %d", *pptr++); break;
+ case META_POSIX_NEG: fprintf(stderr, "META_POSIX_NEG %d", *pptr++); break;
+
+ case META_ACCEPT: fprintf(stderr, "META (*ACCEPT)"); break;
+ case META_COMMIT: fprintf(stderr, "META (*COMMIT)"); break;
+ case META_FAIL: fprintf(stderr, "META (*FAIL)"); break;
+ case META_PRUNE: fprintf(stderr, "META (*PRUNE)"); break;
+ case META_SKIP: fprintf(stderr, "META (*SKIP)"); break;
+ case META_THEN: fprintf(stderr, "META (*THEN)"); break;
+
+ case META_OPTIONS: fprintf(stderr, "META_OPTIONS 0x%02x", *pptr++); break;
+
+ case META_LOOKBEHIND:
+ fprintf(stderr, "META (?<= %d offset=", meta_arg);
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "%zd", offset);
break;
- case OP_CALLOUT_STR:
- cc += GET(cc, 1 + 2*LINK_SIZE);
+ case META_LOOKBEHINDNOT:
+ fprintf(stderr, "META (?<! %d offset=", meta_arg);
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "%zd", offset);
break;
- /* Handle literal characters */
+ case META_CALLOUT_NUMBER:
+ fprintf(stderr, "META (?C%d) next=%d/%d", pptr[2], pptr[0],
+ pptr[1]);
+ pptr += 3;
+ break;
- case OP_CHAR:
- case OP_CHARI:
- case OP_NOT:
- case OP_NOTI:
- branchlength++;
- cc += 2;
-#ifdef SUPPORT_UNICODE
- if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
-#endif
+ case META_CALLOUT_STRING:
+ {
+ uint32_t patoffset = *pptr++; /* Offset of next pattern item */
+ uint32_t patlength = *pptr++; /* Length of next pattern item */
+ fprintf(stderr, "META (?Cstring) length=%d offset=", *pptr++);
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "%zd next=%d/%d", offset, patoffset, patlength);
+ }
break;
- /* Handle exact repetitions. The count is already in characters, but we
- need to skip over a multibyte character in UTF8 mode. */
+ case META_RECURSE_BYNAME:
+ fprintf(stderr, "META (?(&name) length=%d offset=", *pptr++);
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "%zd", offset);
+ break;
- case OP_EXACT:
- case OP_EXACTI:
- case OP_NOTEXACT:
- case OP_NOTEXACTI:
- branchlength += GET2(cc,1);
- cc += 2 + IMM2_SIZE;
-#ifdef SUPPORT_UNICODE
- if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
-#endif
+ case META_BACKREF_BYNAME:
+ fprintf(stderr, "META_BACKREF_BYNAME length=%d offset=", *pptr++);
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "%zd", offset);
break;
- case OP_TYPEEXACT:
- branchlength += GET2(cc,1);
- if (cc[1 + IMM2_SIZE] == OP_PROP || cc[1 + IMM2_SIZE] == OP_NOTPROP)
- cc += 2;
- cc += 1 + IMM2_SIZE + 1;
+ case META_COND_NUMBER:
+ fprintf(stderr, "META_COND_NUMBER %d offset=", pptr[SIZEOFFSET]);
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "%zd", offset);
+ pptr++;
break;
- /* Handle single-char matchers */
+ case META_COND_DEFINE:
+ fprintf(stderr, "META (?(DEFINE) offset=");
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "%zd", offset);
+ break;
- case OP_PROP:
- case OP_NOTPROP:
- cc += 2;
- /* Fall through */
+ case META_COND_VERSION:
+ fprintf(stderr, "META (?(VERSION%s", (*pptr++ == 0)? "=" : ">=");
+ fprintf(stderr, "%d.", *pptr++);
+ fprintf(stderr, "%d)", *pptr++);
+ break;
- case OP_HSPACE:
- case OP_VSPACE:
- case OP_NOT_HSPACE:
- case OP_NOT_VSPACE:
- case OP_NOT_DIGIT:
- case OP_DIGIT:
- case OP_NOT_WHITESPACE:
- case OP_WHITESPACE:
- case OP_NOT_WORDCHAR:
- case OP_WORDCHAR:
- case OP_ANY:
- case OP_ALLANY:
- branchlength++;
- cc++;
+ case META_COND_NAME:
+ fprintf(stderr, "META (?(<name>) length=%d offset=", *pptr++);
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "%zd", offset);
break;
- /* 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 META_COND_RNAME:
+ fprintf(stderr, "META (?(R&name) length=%d offset=", *pptr++);
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "%zd", offset);
+ break;
- case OP_ANYBYTE:
- return FFL_BACKSLASHC;
+ /* This is kept as a name, because it might be. */
- /* Check a class for variable quantification */
+ case META_COND_RNUMBER:
+ fprintf(stderr, "META (?(Rnumber) length=%d offset=", *pptr++);
+ GETOFFSET(offset, pptr);
+ fprintf(stderr, "%zd", offset);
+ break;
- case OP_CLASS:
- case OP_NCLASS:
-#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. */
- if (op == OP_XCLASS)
- cc += GET(cc, 1);
- else
- cc += PRIV(OP_lengths)[OP_CLASS];
-#else
- cc += PRIV(OP_lengths)[OP_CLASS];
-#endif
+ case META_MARK:
+ fprintf(stderr, "META (*MARK:");
+ goto SHOWARG;
- switch (*cc)
- {
- 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:
- goto ISNOTFIXED;
+ case META_PRUNE_ARG:
+ fprintf(stderr, "META (*PRUNE:");
+ goto SHOWARG;
- case OP_CRRANGE:
- case OP_CRMINRANGE:
- case OP_CRPOSRANGE:
- if (GET2(cc,1) != GET2(cc,1+IMM2_SIZE)) goto ISNOTFIXED;
- branchlength += GET2(cc,1);
- cc += 1 + 2 * IMM2_SIZE;
- break;
+ case META_SKIP_ARG:
+ fprintf(stderr, "META (*SKIP:");
+ goto SHOWARG;
- default:
- branchlength++;
+ case META_THEN_ARG:
+ fprintf(stderr, "META (*THEN:");
+ SHOWARG:
+ length = *pptr++;
+ for (i = 0; i < length; i++)
+ {
+ uint32_t cc = *pptr++;
+ if (cc > 32 && cc < 128) fprintf(stderr, "%c", cc);
+ else fprintf(stderr, "\\x{%x}", cc);
}
+ fprintf(stderr, ") length=%u", length);
break;
-
- /* Anything else is variable length */
-
- case OP_ANYNL:
- case OP_BRAMINZERO:
- case OP_BRAPOS:
- case OP_BRAPOSZERO:
- case OP_BRAZERO:
- case OP_CBRAPOS:
- case OP_EXTUNI:
- case OP_KETRMAX:
- case OP_KETRMIN:
- case OP_KETRPOS:
- case OP_MINPLUS:
- case OP_MINPLUSI:
- case OP_MINQUERY:
- case OP_MINQUERYI:
- case OP_MINSTAR:
- case OP_MINSTARI:
- case OP_MINUPTO:
- case OP_MINUPTOI:
- case OP_NOTMINPLUS:
- case OP_NOTMINPLUSI:
- case OP_NOTMINQUERY:
- case OP_NOTMINQUERYI:
- case OP_NOTMINSTAR:
- case OP_NOTMINSTARI:
- case OP_NOTMINUPTO:
- case OP_NOTMINUPTOI:
- case OP_NOTPLUS:
- case OP_NOTPLUSI:
- case OP_NOTPOSPLUS:
- case OP_NOTPOSPLUSI:
- case OP_NOTPOSQUERY:
- case OP_NOTPOSQUERYI:
- case OP_NOTPOSSTAR:
- case OP_NOTPOSSTARI:
- case OP_NOTPOSUPTO:
- case OP_NOTPOSUPTOI:
- case OP_NOTQUERY:
- case OP_NOTQUERYI:
- case OP_NOTSTAR:
- case OP_NOTSTARI:
- case OP_NOTUPTO:
- case OP_NOTUPTOI:
- case OP_PLUS:
- case OP_PLUSI:
- case OP_POSPLUS:
- case OP_POSPLUSI:
- case OP_POSQUERY:
- case OP_POSQUERYI:
- case OP_POSSTAR:
- case OP_POSSTARI:
- case OP_POSUPTO:
- case OP_POSUPTOI:
- case OP_QUERY:
- case OP_QUERYI:
- case OP_REF:
- case OP_REFI:
- case OP_DNREF:
- case OP_DNREFI:
- case OP_SBRA:
- case OP_SBRAPOS:
- case OP_SCBRA:
- case OP_SCBRAPOS:
- case OP_SCOND:
- case OP_SKIPZERO:
- case OP_STAR:
- case OP_STARI:
- case OP_TYPEMINPLUS:
- case OP_TYPEMINQUERY:
- case OP_TYPEMINSTAR:
- case OP_TYPEMINUPTO:
- case OP_TYPEPLUS:
- case OP_TYPEPOSPLUS:
- case OP_TYPEPOSQUERY:
- case OP_TYPEPOSSTAR:
- case OP_TYPEPOSUPTO:
- case OP_TYPEQUERY:
- case OP_TYPESTAR:
- case OP_TYPEUPTO:
- case OP_UPTO:
- case OP_UPTOI:
- goto ISNOTFIXED;
-
- /* Catch unrecognized opcodes so that when new ones are added they
- are not forgotten, as has happened in the past. */
-
- default:
- return FFL_UNKNOWNOP;
}
+ fprintf(stderr, "\n");
}
-/* Control never gets here except by goto. */
-
-ISNOTFIXED:
-if (group > 0)
- {
- groupinfo |= GI_NOT_FIXED_LENGTH;
- cb->groupinfo[group] = groupinfo;
- }
-return FFL_NOTFIXED;
+return;
}
+#endif /* DEBUG_SHOW_PARSED */
/*************************************************
-* Find first significant op code *
+* Copy compiled code *
*************************************************/
-/* This is called by several functions that scan a compiled expression looking
-for a fixed first character, or an anchoring op code etc. It skips over things
-that do not influence this. For some calls, it makes sense to skip negative
-forward and all backward assertions, and also the \b assertion; for others it
-does not.
-
-Arguments:
- code pointer to the start of the group
- skipassert TRUE if certain assertions are to be skipped
-
-Returns: pointer to the first significant opcode
-*/
+/* Compiled JIT code cannot be copied, so the new compiled block has no
+associated JIT data. */
-static const PCRE2_UCHAR*
-first_significant_code(PCRE2_SPTR code, BOOL skipassert)
+PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION
+pcre2_code_copy(const pcre2_code *code)
{
-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 */
+PCRE2_SIZE* ref_count;
+pcre2_code *newcode;
- 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;
+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;
- case OP_CALLOUT_STR:
- code += GET(code, 1 + 2*LINK_SIZE);
- break;
+/* If the code is one that has been deserialized, increment the reference count
+in the decoded tables. */
- default:
- return code;
- }
+if ((code->flags & PCRE2_DEREF_TABLES) != 0)
+ {
+ ref_count = (PCRE2_SIZE *)(code->tables + tables_length);
+ (*ref_count)++;
}
-/* Control never reaches here */
+
+return newcode;
}
/*************************************************
-* Scan compiled branch for non-emptiness *
+* Copy compiled code and character tables *
*************************************************/
-/* This function scans through a branch of a compiled pattern to see whether it
-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 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: 0 if what is matched cannot be empty
- 1 if what is matched could be empty
- -1 if the pattern is too complicated
-*/
-
-#define CBE_NOTEMPTY 0
-#define CBE_EMPTY 1
-#define CBE_TOOCOMPLICATED (-1)
-
+/* Compiled JIT code cannot be copied, so the new compiled block has no
+associated JIT data. This version of code_copy also makes a separate copy of
+the character tables. */
-static int
-could_be_empty_branch(PCRE2_SPTR code, PCRE2_SPTR endcode, BOOL utf,
- compile_block *cb, BOOL atend, recurse_check *recurses, int *countptr)
+PCRE2_EXP_DEFN pcre2_code * PCRE2_CALL_CONVENTION
+pcre2_code_copy_with_tables(const pcre2_code *code)
{
-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;
+PCRE2_SIZE* ref_count;
+pcre2_code *newcode;
+uint8_t *newtables;
-/* 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 == 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;
-if ((cb->external_flags & PCRE2_DUPCAPUSED) == 0 &&
- (*code == OP_CBRA || *code == OP_CBRAPOS))
+newtables = code->memctl.malloc(tables_length + sizeof(PCRE2_SIZE),
+ code->memctl.memory_data);
+if (newtables == NULL)
{
- 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;
+ code->memctl.free((void *)newcode, code->memctl.memory_data);
+ return NULL;
}
+memcpy(newtables, code->tables, tables_length);
+ref_count = (PCRE2_SIZE *)(newtables + tables_length);
+*ref_count = 1;
-/* 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. */
+newcode->tables = newtables;
+newcode->flags |= PCRE2_DEREF_TABLES;
+return newcode;
+}
-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))
- {
- PCRE2_SPTR ccode;
+/*************************************************
+* Free compiled code *
+*************************************************/
- c = *code;
+PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
+pcre2_code_free(pcre2_code *code)
+{
+PCRE2_SIZE* ref_count;
- /* Skip over forward assertions; the other assertions are skipped by
- first_significant_code() with a TRUE final argument. */
+if (code != NULL)
+ {
+ if (code->executable_jit != NULL)
+ PRIV(jit_free)(code->executable_jit, &code->memctl);
- if (c == OP_ASSERT)
+ if ((code->flags & PCRE2_DEREF_TABLES) != 0)
{
- do code += GET(code, 1); while (*code == OP_ALT);
- c = *code;
- continue;
+ /* 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. */
+
+ ref_count = (PCRE2_SIZE *)(code->tables + tables_length);
+ if (*ref_count > 0)
+ {
+ (*ref_count)--;
+ if (*ref_count == 0)
+ code->memctl.free((void *)code->tables, code->memctl.memory_data);
+ }
}
- /* 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. */
+ code->memctl.free(code, code->memctl.memory_data);
+ }
+}
- if (c == OP_RECURSE)
- {
- PCRE2_SPTR scode, endgroup;
- BOOL empty_branch;
- if (!atend) goto ISTRUE;
- scode = cb->start_code + GET(code, 1);
- endgroup = scode;
- /* 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. */
+/*************************************************
+* Read a number, possibly signed *
+*************************************************/
- do endgroup += GET(endgroup, 1); while (*endgroup == OP_ALT);
- if (code >= scode && code <= endgroup) continue; /* Simple recursion */
- else
- {
- recurse_check *r = recurses;
- for (r = recurses; r != NULL; r = r->prev)
- if (r->group == scode) break;
- if (r != NULL) continue; /* Mutual recursion */
- }
+/* This function is used to read numbers in the pattern. The initial pointer
+must be the sign or first digit of the number. When relative values (introduced
+by + or -) are allowed, they are relative group numbers, and the result must be
+greater than zero.
- /* Scan the referenced group, remembering it on the stack chain to detect
- mutual recursions. */
+Arguments:
+ ptrptr points to the character pointer variable
+ ptrend points to the end of the input string
+ allow_sign if < 0, sign not allowed; if >= 0, sign is relative to this
+ max_value the largest number allowed
+ max_error the error to give for an over-large number
+ intptr where to put the result
+ errcodeptr where to put an error code
+
+Returns: TRUE - a number was read
+ FALSE - errorcode == 0 => no number was found
+ errorcode != 0 => an error occurred
+*/
- empty_branch = FALSE;
- this_recurse.prev = recurses;
- this_recurse.group = scode;
+static BOOL
+read_number(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, int32_t allow_sign,
+ uint32_t max_value, uint32_t max_error, int *intptr, int *errorcodeptr)
+{
+int sign = 0;
+uint32_t n = 0;
+PCRE2_SPTR ptr = *ptrptr;
+BOOL yield = FALSE;
- do
- {
- 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;
- }
- scode += GET(scode, 1);
- }
- while (*scode == OP_ALT);
+*errorcodeptr = 0;
- if (!empty_branch) goto ISFALSE; /* All branches are non-empty */
- continue;
+if (allow_sign >= 0 && ptr < ptrend)
+ {
+ if (*ptr == CHAR_PLUS)
+ {
+ sign = +1;
+ max_value -= allow_sign;
+ ptr++;
}
-
- /* Groups with zero repeats can of course be empty; skip them. */
-
- if (c == OP_BRAZERO || c == OP_BRAMINZERO || c == OP_SKIPZERO ||
- c == OP_BRAPOSZERO)
+ else if (*ptr == CHAR_MINUS)
{
- code += PRIV(OP_lengths)[c];
- do code += GET(code, 1); while (*code == OP_ALT);
- c = *code;
- continue;
+ sign = -1;
+ ptr++;
}
+ }
- /* A nested group that is already marked as "could be empty" can just be
- skipped. */
-
- if (c == OP_SBRA || c == OP_SBRAPOS ||
- c == OP_SCBRA || c == OP_SCBRAPOS)
+if (ptr >= ptrend || !IS_DIGIT(*ptr)) return FALSE;
+while (ptr < ptrend && IS_DIGIT(*ptr))
+ {
+ n = n * 10 + *ptr++ - CHAR_0;
+ if (n > max_value)
{
- do code += GET(code, 1); while (*code == OP_ALT);
- c = *code;
- continue;
+ *errorcodeptr = max_error;
+ goto EXIT;
}
+ }
- /* For other groups, scan the branches. */
-
- if (c == OP_BRA || c == OP_BRAPOS ||
- c == OP_CBRA || c == OP_CBRAPOS ||
- c == OP_ONCE || c == OP_ONCE_NC ||
- c == OP_COND || c == OP_SCOND)
+if (allow_sign >= 0 && sign != 0)
+ {
+ if (n == 0)
{
- BOOL empty_branch;
- 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.
- Otherwise, scan the individual branches of the group. */
-
- if (c == OP_COND && code[GET(code, 1)] != OP_ALT)
- code += GET(code, 1);
- else
- {
- empty_branch = FALSE;
- do
- {
- if (!empty_branch)
- {
- 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) goto ISFALSE; /* All branches are non-empty */
- }
-
- c = *code;
- continue;
+ *errorcodeptr = ERR26; /* +0 and -0 are not allowed */
+ goto EXIT;
}
- /* Handle the other opcodes */
-
- switch (c)
+ if (sign > 0) n += allow_sign;
+ else if ((int)n > allow_sign)
{
- /* Check for quantifiers after a class. XCLASS is used for classes that
- cannot be represented just by a bit map. This includes negated single
- high-valued characters. The length in PRIV(OP_lengths)[] is zero; the
- actual length is stored in the compiled code, so we must update "code"
- here. */
-
-#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
- case OP_XCLASS:
- ccode = code += GET(code, 1);
- goto CHECK_CLASS_REPEAT;
-#endif
-
- case OP_CLASS:
- case OP_NCLASS:
- ccode = code + PRIV(OP_lengths)[OP_CLASS];
-
-#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
- CHECK_CLASS_REPEAT:
-#endif
-
- switch (*ccode)
- {
- case OP_CRSTAR: /* These could be empty; continue */
- case OP_CRMINSTAR:
- case OP_CRQUERY:
- case OP_CRMINQUERY:
- case OP_CRPOSSTAR:
- case OP_CRPOSQUERY:
- break;
+ *errorcodeptr = ERR15; /* Non-existent subpattern */
+ goto EXIT;
+ }
+ else n = allow_sign + 1 - n;
+ }
- default: /* Non-repeat => class must match */
- case OP_CRPLUS: /* These repeats aren't empty */
- case OP_CRMINPLUS:
- case OP_CRPOSPLUS:
- goto ISFALSE;
+yield = TRUE;
- case OP_CRRANGE:
- case OP_CRMINRANGE:
- case OP_CRPOSRANGE:
- if (GET2(ccode, 1) > 0) goto ISFALSE; /* Minimum > 0 */
- break;
- }
- break;
+EXIT:
+*intptr = n;
+*ptrptr = ptr;
+return yield;
+}
- /* Opcodes that must match a character */
-
- case OP_ANY:
- case OP_ALLANY:
- case OP_ANYBYTE:
-
- case OP_PROP:
- case OP_NOTPROP:
- case OP_ANYNL:
-
- case OP_NOT_HSPACE:
- case OP_HSPACE:
- case OP_NOT_VSPACE:
- case OP_VSPACE:
- case OP_EXTUNI:
-
- case OP_NOT_DIGIT:
- case OP_DIGIT:
- case OP_NOT_WHITESPACE:
- case OP_WHITESPACE:
- case OP_NOT_WORDCHAR:
- case OP_WORDCHAR:
-
- case OP_CHAR:
- case OP_CHARI:
- case OP_NOT:
- case OP_NOTI:
-
- case OP_PLUS:
- case OP_PLUSI:
- case OP_MINPLUS:
- case OP_MINPLUSI:
-
- case OP_NOTPLUS:
- case OP_NOTPLUSI:
- case OP_NOTMINPLUS:
- case OP_NOTMINPLUSI:
-
- case OP_POSPLUS:
- case OP_POSPLUSI:
- case OP_NOTPOSPLUS:
- case OP_NOTPOSPLUSI:
-
- case OP_EXACT:
- case OP_EXACTI:
- case OP_NOTEXACT:
- case OP_NOTEXACTI:
-
- case OP_TYPEPLUS:
- case OP_TYPEMINPLUS:
- case OP_TYPEPOSPLUS:
- case OP_TYPEEXACT:
- 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. */
-
- case OP_TYPESTAR:
- case OP_TYPEMINSTAR:
- case OP_TYPEPOSSTAR:
- case OP_TYPEQUERY:
- case OP_TYPEMINQUERY:
- case OP_TYPEPOSQUERY:
- if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
- break;
- /* Same for these */
- case OP_TYPEUPTO:
- case OP_TYPEMINUPTO:
- case OP_TYPEPOSUPTO:
- if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
- code += 2;
- break;
+/*************************************************
+* Read repeat counts *
+*************************************************/
- /* End of branch */
+/* Read an item of the form {n,m} and return the values if non-NULL pointers
+are supplied. Repeat counts must be less than 65536 (MAX_REPEAT_COUNT); a
+larger value is used for "unlimited". We have to use signed arguments for
+read_number() because it is capable of returning a signed value.
- case OP_KET:
- case OP_KETRMAX:
- case OP_KETRMIN:
- case OP_KETRPOS:
- case OP_ALT:
- goto ISTRUE;
+Arguments:
+ ptrptr points to pointer to character after'{'
+ ptrend pointer to end of input
+ minp if not NULL, pointer to int for min
+ maxp if not NULL, pointer to int for max (-1 if no max)
+ returned as -1 if no max
+ errorcodeptr points to error code variable
- /* 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. */
+Returns: FALSE if not a repeat quantifier, errorcode set zero
+ FALSE on error, with errorcode set non-zero
+ TRUE on success, with pointer updated to point after '}'
+*/
-#ifdef MAYBE_UTF_MULTI
- case OP_STAR:
- case OP_STARI:
- case OP_NOTSTAR:
- case OP_NOTSTARI:
-
- case OP_MINSTAR:
- case OP_MINSTARI:
- case OP_NOTMINSTAR:
- case OP_NOTMINSTARI:
-
- case OP_POSSTAR:
- case OP_POSSTARI:
- case OP_NOTPOSSTAR:
- case OP_NOTPOSSTARI:
-
- case OP_QUERY:
- case OP_QUERYI:
- case OP_NOTQUERY:
- case OP_NOTQUERYI:
-
- case OP_MINQUERY:
- case OP_MINQUERYI:
- case OP_NOTMINQUERY:
- case OP_NOTMINQUERYI:
-
- case OP_POSQUERY:
- case OP_POSQUERYI:
- case OP_NOTPOSQUERY:
- case OP_NOTPOSQUERYI:
- if (utf && HAS_EXTRALEN(code[1])) code += GET_EXTRALEN(code[1]);
- break;
+static BOOL
+read_repeat_counts(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t *minp,
+ uint32_t *maxp, int *errorcodeptr)
+{
+PCRE2_SPTR p = *ptrptr;
+BOOL yield = FALSE;
+int32_t min = 0;
+int32_t max = REPEAT_UNLIMITED; /* This value is larger than MAX_REPEAT_COUNT */
- 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:
- if (utf && HAS_EXTRALEN(code[1 + IMM2_SIZE])) code += GET_EXTRALEN(code[1 + IMM2_SIZE]);
- break;
-#endif /* MAYBE_UTF_MULTI */
+/* NB read_number() initializes the error code to zero. The only error is for a
+number that is too big. */
- /* MARK, and PRUNE/SKIP/THEN with an argument must skip over the argument
- string. */
+if (!read_number(&p, ptrend, -1, MAX_REPEAT_COUNT, ERR5, &min, errorcodeptr))
+ goto EXIT;
- case OP_MARK:
- case OP_PRUNE_ARG:
- case OP_SKIP_ARG:
- case OP_THEN_ARG:
- code += code[1];
- break;
+if (p >= ptrend) goto EXIT;
- /* None of the remaining opcodes are required to match a character. */
+if (*p == CHAR_RIGHT_CURLY_BRACKET)
+ {
+ p++;
+ max = min;
+ }
- default:
- break;
+else
+ {
+ if (*p++ != CHAR_COMMA || p >= ptrend) goto EXIT;
+ if (*p != CHAR_RIGHT_CURLY_BRACKET)
+ {
+ if (!read_number(&p, ptrend, -1, MAX_REPEAT_COUNT, ERR5, &max,
+ errorcodeptr) || p >= ptrend || *p != CHAR_RIGHT_CURLY_BRACKET)
+ goto EXIT;
+ if (max < min)
+ {
+ *errorcodeptr = ERR4;
+ goto EXIT;
+ }
}
+ p++;
}
-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;
-}
-
-
-
-/*************************************************
-* Check for counted repeat *
-*************************************************/
+yield = TRUE;
+if (minp != NULL) *minp = (uint32_t)min;
+if (maxp != NULL) *maxp = (uint32_t)max;
-/* 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.
+/* Update the pattern pointer on success, or after an error, but not when
+the result is "not a repeat quantifier". */
-Argument: pointer to the first char after '{'
-Returns: TRUE or FALSE
-*/
-
-static BOOL
-is_counted_repeat(PCRE2_SPTR p)
-{
-if (!IS_DIGIT(*p)) return FALSE;
-p++;
-while (IS_DIGIT(*p)) p++;
-if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE;
+EXIT:
+if (yield || *errorcodeptr != 0) *ptrptr = p;
+return yield;
-if (*p++ != CHAR_COMMA) return FALSE;
-if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE;
-if (!IS_DIGIT(*p)) return FALSE;
-p++;
-while (IS_DIGIT(*p)) p++;
-return (*p == CHAR_RIGHT_CURLY_BRACKET);
}
@@ -1789,21 +1376,14 @@ return (*p == CHAR_RIGHT_CURLY_BRACKET);
/* 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.
+entry, ptr is pointing at the character after \. On exit, it points after 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.
+in replacement strings. In this case, the cb argument is NULL, and in the case
+of escapes that have further processing, only sequences that define a data
+character are recognised. The isclass argument is not relevant; the options
+argument is the final value of the compiled pattern's options.
Arguments:
ptrptr points to the input position pointer
@@ -1816,7 +1396,7 @@ Arguments:
Returns: zero => a data character
positive => a special escape sequence
- negative => a back reference
+ negative => a numerical back reference
on error, errorcodeptr is set non-zero
*/
@@ -1825,16 +1405,11 @@ PRIV(check_escape)(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t *chptr,
int *errorcodeptr, uint32_t options, BOOL isclass, compile_block *cb)
{
BOOL utf = (options & PCRE2_UTF) != 0;
-PCRE2_SPTR ptr = *ptrptr + 1;
-register uint32_t c, cc;
+PCRE2_SPTR ptr = *ptrptr;
+uint32_t c, cc;
int escape = 0;
int i;
-/* Find the end of a nested insert. */
-
-if (cb != NULL && cb->nestptr[0] != NULL)
- ptrend = ptr + PRIV(strlen)(ptr);
-
/* If backslash is at the end of the string, it's an error. */
if (ptr >= ptrend)
@@ -1844,7 +1419,7 @@ if (ptr >= ptrend)
}
GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */
-ptr--; /* Set pointer back to the last code unit */
+*errorcodeptr = 0; /* Be optimistic */
/* 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
@@ -1858,7 +1433,7 @@ else if ((i = escapes[c - ESCAPES_FIRST]) != 0)
if (i > 0) c = (uint32_t)i; else /* Positive is a data character */
{
escape = -i; /* Else return a special escape */
- if (escape == ESC_P || escape == ESC_p || escape == ESC_X)
+ if (cb != NULL && (escape == ESC_P || escape == ESC_p || escape == ESC_X))
cb->external_flags |= PCRE2_HASBKPORX; /* Note \P, \p, or \X */
}
}
@@ -1870,8 +1445,8 @@ when BSUX is set). */
else
{
PCRE2_SPTR oldptr;
- BOOL braced, negated, overflow;
- unsigned int s;
+ BOOL overflow;
+ int s;
/* Filter calls from pcre2_substitute(). */
@@ -1900,26 +1475,31 @@ else
if ((options & PCRE2_ALT_BSUX) == 0) *errorcodeptr = ERR37; else
{
uint32_t xc;
- if ((cc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */
+ if (ptrend - ptr < 4) break; /* Less than 4 chars */
+ if ((cc = XDIGIT(ptr[0])) == 0xff) break; /* Not a hex digit */
+ if ((xc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */
+ cc = (cc << 4) | xc;
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 >= 0xd800 && c <= 0xdfff &&
+ (cb->cx->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)
+ *errorcodeptr = ERR73;
}
else if (c > MAX_NON_UTF_CHAR) *errorcodeptr = ERR77;
}
break;
- case CHAR_U:
/* \U is unrecognized unless PCRE2_ALT_BSUX is set, in which case it is an
upper case letter. */
+
+ case CHAR_U:
if ((options & PCRE2_ALT_BSUX) == 0) *errorcodeptr = ERR37;
break;
@@ -1933,87 +1513,71 @@ else
(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.
+ was \k{name}.
(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). */
+ (possibly recursive) subroutine calls, _not_ backreferences. We return
+ the ESC_g code.
+
+ Summary: Return a negative number for a numerical back reference, ESC_k for
+ a named back reference, and ESC_g for a named or numbered subroutine call.
+ */
case CHAR_g:
if (isclass) break;
- if (ptr[1] == CHAR_LESS_THAN_SIGN || ptr[1] == CHAR_APOSTROPHE)
+
+ if (ptr >= ptrend)
+ {
+ *errorcodeptr = ERR57;
+ break;
+ }
+
+ if (*ptr == CHAR_LESS_THAN_SIGN || *ptr == CHAR_APOSTROPHE)
{
escape = ESC_g;
break;
}
- /* Handle the Perl-compatible cases */
+ /* If there is a brace delimiter, try to read a numerical reference. If
+ there isn't one, assume we have a name and treat it as \k. */
- if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
+ if (*ptr == CHAR_LEFT_CURLY_BRACKET)
{
- 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)
+ PCRE2_SPTR p = ptr + 1;
+ if (!read_number(&p, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &s,
+ errorcodeptr))
{
- escape = ESC_k;
+ if (*errorcodeptr == 0) escape = ESC_k; /* No number found */
break;
}
- braced = TRUE;
- ptr++;
+ if (p >= ptrend || *p != CHAR_RIGHT_CURLY_BRACKET)
+ {
+ *errorcodeptr = ERR57;
+ break;
+ }
+ ptr = p + 1;
}
- else braced = FALSE;
- if (ptr[1] == CHAR_MINUS)
- {
- negated = TRUE;
- ptr++;
- }
- else negated = FALSE;
+ /* Read an undelimited number */
- /* The integer range is limited by the machine's int representation. */
- s = 0;
- overflow = FALSE;
- while (IS_DIGIT(ptr[1]))
+ else
{
- if (s > INT_MAX / 10 - 1) /* Integer overflow */
+ if (!read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &s,
+ errorcodeptr))
{
- overflow = TRUE;
+ if (*errorcodeptr == 0) *errorcodeptr = ERR57; /* No number found */
break;
}
- s = s * 10 + (unsigned int)(*(++ptr) - CHAR_0);
- }
- if (overflow) /* Integer overflow */
- {
- while (IS_DIGIT(ptr[1])) ptr++;
- *errorcodeptr = ERR61;
- break;
}
- if (braced && *(++ptr) != CHAR_RIGHT_CURLY_BRACKET)
+ if (s <= 0)
{
- *errorcodeptr = ERR57;
+ *errorcodeptr = ERR15;
break;
}
- if (s == 0)
- {
- *errorcodeptr = ERR58;
- break;
- }
-
- if (negated)
- {
- if (s > cb->bracount)
- {
- *errorcodeptr = ERR15;
- break;
- }
- s = cb->bracount - (s - 1);
- }
-
- escape = -(int)s;
+ escape = -s;
break;
/* The handling of escape sequences consisting of a string of digits
@@ -2036,31 +1600,18 @@ else
if (!isclass)
{
oldptr = ptr;
- /* The integer range is limited by the machine's int representation. */
- s = c - CHAR_0;
- overflow = FALSE;
- while (IS_DIGIT(ptr[1]))
- {
- if (s > INT_MAX / 10 - 1) /* Integer overflow */
- {
- overflow = TRUE;
- break;
- }
- s = s * 10 + (unsigned int)(*(++ptr) - CHAR_0);
- }
- if (overflow) /* Integer overflow */
- {
- while (IS_DIGIT(ptr[1])) ptr++;
- *errorcodeptr = ERR61;
+ ptr--; /* Back to the digit */
+ if (!read_number(&ptr, ptrend, -1, INT_MAX/10 - 1, ERR61, &s,
+ errorcodeptr))
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. */
- if (s < 10 || *oldptr >= CHAR_8 || s <= cb->bracount)
+ if (s < 10 || oldptr[-1] >= CHAR_8 || s <= (int)cb->bracount)
{
- escape = -(int)s; /* Indicates a back reference */
+ if (s > (int)MAX_GROUP_NUMBER) *errorcodeptr = ERR61;
+ else escape = -s; /* Indicates a back reference */
break;
}
ptr = oldptr; /* Put the pointer back and fall through */
@@ -2068,13 +1619,12 @@ else
/* 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. */
+ generate a binary zero 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;
+ if (c >= CHAR_8) break;
- /* Fall through with a digit less than 8 */
+ /* Fall through */
/* \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
@@ -2084,8 +1634,8 @@ else
case CHAR_0:
c -= CHAR_0;
- while(i++ < 2 && ptr[1] >= CHAR_0 && ptr[1] <= CHAR_7)
- c = c * 8 + *(++ptr) - CHAR_0;
+ while(i++ < 2 && ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7)
+ c = c * 8 + *ptr++ - CHAR_0;
#if PCRE2_CODE_UNIT_WIDTH == 8
if (!utf && c > 0xff) *errorcodeptr = ERR51;
#endif
@@ -2095,13 +1645,18 @@ else
specifying character codes in octal. The only supported form is \o{ddd}. */
case CHAR_o:
- if (ptr[1] != CHAR_LEFT_CURLY_BRACKET) *errorcodeptr = ERR55; else
- if (ptr[2] == CHAR_RIGHT_CURLY_BRACKET) *errorcodeptr = ERR78; else
+ if (ptr >= ptrend || *ptr++ != CHAR_LEFT_CURLY_BRACKET)
+ {
+ ptr--;
+ *errorcodeptr = ERR55;
+ }
+ else if (ptr >= ptrend || *ptr == CHAR_RIGHT_CURLY_BRACKET)
+ *errorcodeptr = ERR78;
+ else
{
- ptr += 2;
c = 0;
overflow = FALSE;
- while (*ptr >= CHAR_0 && *ptr <= CHAR_7)
+ while (ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7)
{
cc = *ptr++;
if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */
@@ -2119,14 +1674,23 @@ else
}
if (overflow)
{
- while (*ptr >= CHAR_0 && *ptr <= CHAR_7) ptr++;
+ while (ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7) ptr++;
*errorcodeptr = ERR34;
}
- else if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
+ else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET)
+ {
+ if (utf && c >= 0xd800 && c <= 0xdfff && (cb == NULL ||
+ (cb->cx->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0))
+ {
+ ptr--;
+ *errorcodeptr = ERR73;
+ }
+ }
+ else
{
- if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
+ ptr--;
+ *errorcodeptr = ERR64;
}
- else *errorcodeptr = ERR64;
}
break;
@@ -2137,8 +1701,9 @@ else
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 */
+ if (ptrend - ptr < 2) break; /* Less than 2 characters */
+ if ((cc = XDIGIT(ptr[0])) == 0xff) break; /* Not a hex digit */
+ if ((xc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */
c = (cc << 4) | xc;
ptr += 2;
} /* End PCRE2_ALT_BSUX handling */
@@ -2152,10 +1717,9 @@ else
else
{
- if (ptr[1] == CHAR_LEFT_CURLY_BRACKET)
+ if (ptr < ptrend && *ptr == CHAR_LEFT_CURLY_BRACKET)
{
- ptr += 2;
- if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
+ if (++ptr >= ptrend || *ptr == CHAR_RIGHT_CURLY_BRACKET)
{
*errorcodeptr = ERR78;
break;
@@ -2163,7 +1727,7 @@ else
c = 0;
overflow = FALSE;
- while ((cc = XDIGIT(*ptr)) != 0xff)
+ while (ptr < ptrend && (cc = XDIGIT(*ptr)) != 0xff)
{
ptr++;
if (c == 0 && cc == 0) continue; /* Leading zeroes */
@@ -2180,12 +1744,17 @@ else
if (overflow)
{
- while (XDIGIT(*ptr) != 0xff) ptr++;
+ while (ptr < ptrend && XDIGIT(*ptr) != 0xff) ptr++;
*errorcodeptr = ERR34;
}
- else if (*ptr == CHAR_RIGHT_CURLY_BRACKET)
+ else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET)
{
- if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73;
+ if (utf && c >= 0xd800 && c <= 0xdfff && (cb == NULL ||
+ (cb->cx->extra_options & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0))
+ {
+ ptr--;
+ *errorcodeptr = ERR73;
+ }
}
/* If the sequence of hex digits does not end with '}', give an error.
@@ -2193,18 +1762,22 @@ else
\x handling, but nowadays Perl gives an error, which seems much more
sensible, so we do too. */
- else *errorcodeptr = ERR67;
+ else
+ {
+ ptr--;
+ *errorcodeptr = ERR67;
+ }
} /* End of \x{} processing */
- /* Read a single-byte hex-defined char (up to two hex digits after \x) */
+ /* Read a up to two hex digits after \x */
else
{
c = 0;
- if ((cc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */
+ if (ptr >= ptrend || (cc = XDIGIT(*ptr)) == 0xff) break; /* Not a hex digit */
ptr++;
c = cc;
- if ((cc = XDIGIT(ptr[1])) == 0xff) break; /* Not a hex digit */
+ if (ptr >= ptrend || (cc = XDIGIT(*ptr)) == 0xff) break; /* Not a hex digit */
ptr++;
c = (c << 4) | cc;
} /* End of \xdd handling */
@@ -2230,14 +1803,13 @@ else
#else
case CHAR_c:
#endif
-
- c = *(++ptr);
- if (c >= CHAR_a && c <= CHAR_z) c = UPPER_CASE(c);
- if (c == CHAR_NULL && ptr >= ptrend)
+ if (ptr >= ptrend)
{
*errorcodeptr = ERR2;
break;
}
+ c = *ptr;
+ if (c >= CHAR_a && c <= CHAR_z) c = UPPER_CASE(c);
/* Handle \c in an ASCII/Unicode environment. */
@@ -2267,6 +1839,7 @@ else
}
#endif /* EBCDIC */
+ ptr++;
break;
/* Any other alphanumeric following \ is an error. Perl gives an error only
@@ -2274,7 +1847,8 @@ else
default:
*errorcodeptr = ERR3;
- break;
+ *ptrptr = ptr - 1; /* Point to the character at fault */
+ return 0;
}
}
@@ -2282,16 +1856,16 @@ else
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);
+if (escape == ESC_N && ptr < ptrend && *ptr == CHAR_LEFT_CURLY_BRACKET &&
+ ptrend - ptr > 2)
+ {
+ PCRE2_SPTR p = ptr + 1;
+ if (!read_repeat_counts(&p, ptrend, NULL, NULL, errorcodeptr) &&
+ *errorcodeptr == 0)
+ *errorcodeptr = ERR37;
+ }
-/* Set the pointer to the final character before returning. */
+/* Set the pointer to the next character before returning. */
*ptrptr = ptr;
*chptr = c;
@@ -2307,8 +1881,8 @@ return escape;
/* 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.
+contents of ptrptr are pointing after the P or p. On exit, it is left pointing
+after the final code unit of the escape sequence.
Arguments:
ptrptr the pattern position pointer
@@ -2322,31 +1896,34 @@ Returns: TRUE if the type value was found, or FALSE for an invalid type
*/
static BOOL
-get_ucp(PCRE2_SPTR *ptrptr, BOOL *negptr, unsigned int *ptypeptr,
- unsigned int *pdataptr, int *errorcodeptr, compile_block *cb)
+get_ucp(PCRE2_SPTR *ptrptr, BOOL *negptr, uint16_t *ptypeptr,
+ uint16_t *pdataptr, int *errorcodeptr, compile_block *cb)
{
-register PCRE2_UCHAR c;
-size_t i, bot, top;
+PCRE2_UCHAR c;
+PCRE2_SIZE i, bot, top;
PCRE2_SPTR ptr = *ptrptr;
PCRE2_UCHAR name[32];
+if (ptr >= cb->end_pattern) goto ERROR_RETURN;
+c = *ptr++;
*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)
{
- if (ptr[1] == CHAR_CIRCUMFLEX_ACCENT)
+ if (ptr >= cb->end_pattern) goto ERROR_RETURN;
+ if (*ptr == 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 (ptr >= cb->end_pattern) goto ERROR_RETURN;
+ c = *ptr++;
+ if (c == CHAR_NUL) goto ERROR_RETURN;
if (c == CHAR_RIGHT_CURLY_BRACKET) break;
name[i] = c;
}
@@ -2397,217 +1974,6 @@ return FALSE;
/*************************************************
-* Read repeat counts *
-*************************************************/
-
-/* Read an item of the form {n,m} and return the values. This is called only
-after is_counted_repeat() has confirmed that a repeat-count quantifier exists,
-so the syntax is guaranteed to be correct, but we need to check the values.
-
-Arguments:
- p pointer to first char after '{'
- minp pointer to int for min
- maxp pointer to int for max
- returned as -1 if no max
- errorcodeptr points to error code variable
-
-Returns: pointer to '}' on success;
- current ptr on error, with errorcodeptr set non-zero
-*/
-
-static 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;
- }
- }
- if (max < min)
- {
- *errorcodeptr = ERR4;
- return p;
- }
- }
- }
-
-*minp = min;
-*maxp = max;
-return p;
-}
-
-
-
-/*************************************************
-* Scan compiled regex for recursion reference *
-*************************************************/
-
-/* This function scans through a compiled pattern until it finds an instance of
-OP_RECURSE.
-
-Arguments:
- code points to start of expression
- utf TRUE in UTF mode
-
-Returns: pointer to the opcode for OP_RECURSE, or NULL if not found
-*/
-
-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;
-
- /* 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);
-
- /* Otherwise, we can get the item's length from the table, except that for
- repeated character types, we have to test for \p and \P, which have an extra
- two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we
- must add in its length. */
-
- else
- {
- switch(c)
- {
- case OP_TYPESTAR:
- case OP_TYPEMINSTAR:
- case OP_TYPEPLUS:
- case OP_TYPEMINPLUS:
- case OP_TYPEQUERY:
- case OP_TYPEMINQUERY:
- case OP_TYPEPOSSTAR:
- case OP_TYPEPOSPLUS:
- case OP_TYPEPOSQUERY:
- if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2;
- break;
-
- case OP_TYPEPOSUPTO:
- case OP_TYPEUPTO:
- case OP_TYPEMINUPTO:
- case OP_TYPEEXACT:
- if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
- code += 2;
- break;
-
- case OP_MARK:
- case OP_PRUNE_ARG:
- case OP_SKIP_ARG:
- 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-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 /* MAYBE_UTF_MULTI */
- }
- }
-}
-
-
-
-/*************************************************
* Check for POSIX class syntax *
*************************************************/
@@ -2645,25 +2011,28 @@ seem right at all. PCRE does not allow closing square brackets in POSIX class
names.
Arguments:
- ptr pointer to the initial [
+ ptr pointer to the character after the initial [ (colon, dot, equals)
+ ptrend pointer to the end of the pattern
endptr where to return a pointer to the terminating ':', '.', or '='
Returns: TRUE or FALSE
*/
static BOOL
-check_posix_syntax(PCRE2_SPTR ptr, PCRE2_SPTR *endptr)
+check_posix_syntax(PCRE2_SPTR ptr, PCRE2_SPTR ptrend, PCRE2_SPTR *endptr)
{
PCRE2_UCHAR terminator; /* Don't combine these lines; the Solaris cc */
-terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */
+terminator = *ptr++; /* compiler warns about "non-constant" initializer. */
-for (++ptr; *ptr != CHAR_NULL; ptr++)
+for (; ptrend - ptr >= 2; ptr++)
{
if (*ptr == 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;
+
else if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
{
*endptr = ptr;
@@ -2694,7 +2063,7 @@ static int
check_posix_name(PCRE2_SPTR ptr, int len)
{
const char *pn = posix_names;
-register int yield = 0;
+int yield = 0;
while (posix_name_lengths[yield] != 0)
{
if (len == posix_name_lengths[yield] &&
@@ -2707,765 +2076,1424 @@ return -1;
-#ifdef SUPPORT_UNICODE
/*************************************************
-* Get othercase range *
+* Read a subpattern or VERB name *
*************************************************/
-/* 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.
+/* This function is called from parse_regex() below whenever it needs to read
+the name of a subpattern or a (*VERB). The initial pointer must be to the
+character before the name. If that character is '*' we are reading a verb name.
+The pointer is updated to point after the name, for a VERB, or after tha name's
+terminator for a subpattern name. Returning both the offset and the name
+pointer is redundant information, but some callers use one and some the other,
+so it is simplest just to return both.
Arguments:
- cptr points to starting character value; updated
- d end value
- ocptr where to put start of othercase range
- odptr where to put end of othercase range
-
-Yield: -1 when no more
- 0 when a range is returned
- >0 the CASESET offset for char with multiple other cases
- in this case, ocptr contains the original
+ ptrptr points to the character pointer variable
+ ptrend points to the end of the input string
+ terminator the terminator of a subpattern name must be this
+ offsetptr where to put the offset from the start of the pattern
+ nameptr where to put a pointer to the name in the input
+ namelenptr where to put the length of the name
+ errcodeptr where to put an error code
+ cb pointer to the compile data block
+
+Returns: TRUE if a name was read
+ FALSE otherwise, with error code set
*/
-static int
-get_othercase_range(uint32_t *cptr, uint32_t d, uint32_t *ocptr,
- uint32_t *odptr)
+static BOOL
+read_name(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend, uint32_t terminator,
+ PCRE2_SIZE *offsetptr, PCRE2_SPTR *nameptr, uint32_t *namelenptr,
+ int *errorcodeptr, compile_block *cb)
{
-uint32_t c, othercase, next;
-unsigned int co;
+PCRE2_SPTR ptr = *ptrptr;
+BOOL is_verb = (*ptr == CHAR_ASTERISK);
+uint32_t namelen = 0;
+uint32_t ctype = is_verb? ctype_letter : ctype_word;
-/* Find the first character that has an other case. If it has multiple other
-cases, return its case offset value. */
+if (++ptr >= ptrend)
+ {
+ *errorcodeptr = is_verb? ERR60: /* Verb not recognized or malformed */
+ ERR62; /* Subpattern name expected */
+ goto FAILED;
+ }
-for (c = *cptr; c <= d; c++)
+*nameptr = ptr;
+*offsetptr = (PCRE2_SIZE)(ptr - cb->start_pattern);
+
+if (IS_DIGIT(*ptr))
{
- if ((co = UCD_CASESET(c)) != 0)
+ *errorcodeptr = ERR44; /* Group name must not start with digit */
+ goto FAILED;
+ }
+
+while (ptr < ptrend && MAX_255(*ptr) && (cb->ctypes[*ptr] & ctype) != 0)
+ {
+ ptr++;
+ namelen++;
+ if (namelen > MAX_NAME_SIZE)
{
- *ocptr = c++; /* Character that has the set */
- *cptr = c; /* Rest of input range */
- return (int)co;
+ *errorcodeptr = ERR48;
+ goto FAILED;
}
- if ((othercase = UCD_OTHERCASE(c)) != c) break;
}
-if (c > d) return -1; /* Reached end of range */
-
-/* Found a character that has a single other case. Search for the end of the
-range, which is either the end of the input range, or a character that has zero
-or more than one other cases. */
+/* Subpattern names must not be empty, and their terminator is checked here.
+(What follows a verb name is checked separately.) */
-*ocptr = othercase;
-next = othercase + 1;
-
-for (++c; c <= d; c++)
+if (!is_verb)
{
- if ((co = UCD_CASESET(c)) != 0 || UCD_OTHERCASE(c) != next) break;
- next++;
+ if (namelen == 0)
+ {
+ *errorcodeptr = ERR62; /* Subpattern name expected */
+ goto FAILED;
+ }
+ if (ptr >= ptrend || *ptr != (PCRE2_UCHAR)terminator)
+ {
+ *errorcodeptr = ERR42;
+ goto FAILED;
+ }
+ ptr++;
}
-*odptr = next - 1; /* End of othercase range */
-*cptr = c; /* Rest of input range */
-return 0;
+*namelenptr = namelen;
+*ptrptr = ptr;
+return TRUE;
+
+FAILED:
+*ptrptr = ptr;
+return FALSE;
}
-#endif /* SUPPORT_UNICODE */
/*************************************************
-* Add a character or range to a class *
+* Manage callouts at start of cycle *
*************************************************/
-/* This function packages up the logic of adding a character or range of
-characters to a class. The character values in the arguments will be within the
-valid values for the current mode (8-bit, 16-bit, UTF, etc). This function is
-mutually recursive with the function immediately below.
+/* At the start of a new item in parse_regex() we are able to record the
+details of the previous item in a prior callout, and also to set up an
+automatic callout if enabled. Avoid having two adjacent automatic callouts,
+which would otherwise happen for items such as \Q that contribute nothing to
+the parsed pattern.
Arguments:
- classbits the bit map for characters < 256
- uchardptr points to the pointer for extra data
- options the options word
- cb compile data
- start start of range character
- end end of range character
+ ptr current pattern pointer
+ pcalloutptr points to a pointer to previous callout, or NULL
+ auto_callout TRUE if auto_callouts are enabled
+ parsed_pattern the parsed pattern pointer
+ cb compile block
-Returns: the number of < 256 characters added
- the pointer to extra data is updated
+Returns: possibly updated parsed_pattern pointer.
*/
-static unsigned int
-add_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, uint32_t options,
- compile_block *cb, uint32_t start, uint32_t end)
+static uint32_t *
+manage_callouts(PCRE2_SPTR ptr, uint32_t **pcalloutptr, BOOL auto_callout,
+ uint32_t *parsed_pattern, compile_block *cb)
{
-uint32_t c;
-uint32_t classbits_end = (end <= 0xff ? end : 0xff);
-unsigned int n8 = 0;
+uint32_t *previous_callout = *pcalloutptr;
-/* 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 (previous_callout != NULL) previous_callout[2] = ptr - cb->start_pattern -
+ (PCRE2_SIZE)previous_callout[1];
-if ((options & PCRE2_CASELESS) != 0)
+if (!auto_callout) previous_callout = NULL; else
{
-#ifdef SUPPORT_UNICODE
- if ((options & PCRE2_UTF) != 0)
+ if (previous_callout == NULL ||
+ previous_callout != parsed_pattern - 4 ||
+ previous_callout[3] != 255)
{
- int rc;
- uint32_t oc, od;
-
- options &= ~PCRE2_CASELESS; /* Remove for recursive calls */
- c = start;
+ previous_callout = parsed_pattern; /* Set up new automatic callout */
+ parsed_pattern += 4;
+ previous_callout[0] = META_CALLOUT_NUMBER;
+ previous_callout[2] = 0;
+ previous_callout[3] = 255;
+ }
+ previous_callout[1] = (uint32_t)(ptr - cb->start_pattern);
+ }
- while ((rc = get_othercase_range(&c, end, &oc, &od)) >= 0)
- {
- /* Handle a single character that has more than one other case. */
+*pcalloutptr = previous_callout;
+return parsed_pattern;
+}
- 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. */
- else if (oc >= start && od <= end) continue;
+/*************************************************
+* Parse regex and identify named groups *
+*************************************************/
- /* Extend the original range if there is overlap, noting that if oc < c, we
- can't have od > end because a subrange is always shorter than the basic
- range. Otherwise, use a recursive call to add the additional range. */
+/* This function is called first of all. It scans the pattern and does two
+things: (1) It identifies capturing groups and makes a table of named capturing
+groups so that information about them is fully available to both the compiling
+scans. (2) It writes a parsed version of the pattern with comments omitted and
+escapes processed into the parsed_pattern vector.
- else if (oc < start && od >= start - 1) start = oc; /* Extend downwards */
- else if (od > end && oc <= end + 1)
- {
- end = od; /* Extend upwards */
- if (end > classbits_end) classbits_end = (end <= 0xff ? end : 0xff);
- }
- else n8 += add_to_class(classbits, uchardptr, options, cb, oc, od);
- }
- }
- else
-#endif /* SUPPORT_UNICODE */
-
- /* Not UTF mode */
+Arguments:
+ ptr points to the start of the pattern
+ options compiling dynamic options (may change during the scan)
+ has_lookbehind points to a boolean, set TRUE if a lookbehind is found
+ cb pointer to the compile data block
- for (c = start; c <= classbits_end; c++)
- {
- SETBIT(classbits, cb->fcc[c]);
- n8++;
- }
- }
+Returns: zero on success or a non-zero error code, with the
+ error offset placed in the cb field
+*/
-/* Now handle the original range. Adjust the final value according to the bit
-length - this means that the same lists of (e.g.) horizontal spaces can be used
-in all cases. */
+/* A structure and some flags for dealing with nested groups. */
-if ((options & PCRE2_UTF) == 0 && end > MAX_NON_UTF_CHAR)
- end = MAX_NON_UTF_CHAR;
+typedef struct nest_save {
+ uint16_t nest_depth;
+ uint16_t reset_group;
+ uint16_t max_group;
+ uint16_t flags;
+ uint32_t options;
+} nest_save;
-/* Use the bitmap for characters < 256. Otherwise use extra data.*/
+#define NSF_RESET 0x0001u
+#define NSF_CONDASSERT 0x0002u
-for (c = start; c <= classbits_end; c++)
- {
- /* Regardless of start, c will always be <= 255. */
- SETBIT(classbits, c);
- n8++;
- }
+/* Of the options that are changeable within the pattern, these are tracked
+during parsing. The rest are used from META_OPTIONS items when compiling. */
-#ifdef SUPPORT_WIDE_CHARS
-if (start <= 0xff) start = 0xff + 1;
+#define PARSE_TRACKED_OPTIONS \
+ (PCRE2_DUPNAMES|PCRE2_EXTENDED|PCRE2_EXTENDED_MORE|PCRE2_NO_AUTO_CAPTURE)
-if (end >= start)
- {
- PCRE2_UCHAR *uchardata = *uchardptr;
+/* States used for analyzing ranges in character classes. The two OK values
+must be last. */
-#ifdef SUPPORT_UNICODE
- if ((options & PCRE2_UTF) != 0)
- {
- if (start < end)
- {
- *uchardata++ = XCL_RANGE;
- uchardata += PRIV(ord2utf)(start, uchardata);
- uchardata += PRIV(ord2utf)(end, uchardata);
- }
- else if (start == end)
- {
- *uchardata++ = XCL_SINGLE;
- uchardata += PRIV(ord2utf)(start, uchardata);
- }
- }
- else
-#endif /* SUPPORT_UNICODE */
+enum { RANGE_NO, RANGE_STARTED, RANGE_OK_ESCAPED, RANGE_OK_LITERAL };
- /* Without UTF support, character values are constrained by the bit length,
- and can only be > 256 for 16-bit and 32-bit libraries. */
+/* Only in 32-bit mode can there be literals > META_END. A macros encapsulates
+the storing of literal values in the parsed pattern. */
-#if PCRE2_CODE_UNIT_WIDTH == 8
- {}
-#else
- if (start < end)
- {
- *uchardata++ = XCL_RANGE;
- *uchardata++ = start;
- *uchardata++ = end;
- }
- else if (start == end)
- {
- *uchardata++ = XCL_SINGLE;
- *uchardata++ = start;
- }
-#endif
- *uchardptr = uchardata; /* Updata extra data pointer */
+#if PCRE2_CODE_UNIT_WIDTH == 32
+#define PARSED_LITERAL(c, p) \
+ { \
+ if (c >= META_END) *p++ = META_BIGVALUE; \
+ *p++ = c; \
+ okquantifier = TRUE; \
}
#else
- (void)uchardptr; /* Avoid compiler warning */
-#endif /* SUPPORT_WIDE_CHARS */
-
-return n8; /* Number of 8-bit characters */
-}
-
+#define PARSED_LITERAL(c, p) *p++ = c; okquantifier = TRUE;
+#endif
+/* Here's the actual function. */
-/*************************************************
-* Add a list of characters to a class *
-*************************************************/
+static int parse_regex(PCRE2_SPTR ptr, uint32_t options, BOOL *has_lookbehind,
+ compile_block *cb)
+{
+uint32_t c;
+uint32_t delimiter;
+uint32_t namelen;
+uint32_t class_range_state;
+uint32_t *verblengthptr = NULL; /* Value avoids compiler warning */
+uint32_t *previous_callout = NULL;
+uint32_t *parsed_pattern = cb->parsed_pattern;
+uint32_t *parsed_pattern_end = cb->parsed_pattern_end;
+uint32_t meta_quantifier = 0;
+uint16_t nest_depth = 0;
+int after_manual_callout = 0;
+int expect_cond_assert = 0;
+int errorcode = 0;
+int escape;
+int i;
+BOOL inescq = FALSE;
+BOOL inverbname = FALSE;
+BOOL utf = (options & PCRE2_UTF) != 0;
+BOOL auto_callout = (options & PCRE2_AUTO_CALLOUT) != 0;
+BOOL isdupname;
+BOOL negate_class;
+BOOL okquantifier = FALSE;
+PCRE2_SPTR thisptr;
+PCRE2_SPTR name;
+PCRE2_SPTR ptrend = cb->end_pattern;
+PCRE2_SPTR verbnamestart = NULL; /* Value avoids compiler warning */
+named_group *ng;
+nest_save *top_nest, *end_nests;
-/* This function is used for adding a list of case-equivalent characters to a
-class, and also for adding a list of horizontal or vertical whitespace. If the
-list is in order (which it should be), ranges of characters are detected and
-handled appropriately. This function is mutually recursive with the function
-above.
+/* Insert leading items for word and line matching (features provided for the
+benefit of pcre2grep). */
-Arguments:
- classbits the bit map for characters < 256
- uchardptr points to the pointer for extra data
- options the options word
- 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
- already know about
+if ((cb->cx->extra_options & PCRE2_EXTRA_MATCH_LINE) != 0)
+ {
+ *parsed_pattern++ = META_CIRCUMFLEX;
+ *parsed_pattern++ = META_NOCAPTURE;
+ }
+else if ((cb->cx->extra_options & PCRE2_EXTRA_MATCH_WORD) != 0)
+ {
+ *parsed_pattern++ = META_ESCAPE + ESC_b;
+ *parsed_pattern++ = META_NOCAPTURE;
+ }
-Returns: the number of < 256 characters added
- the pointer to extra data is updated
-*/
+/* If the pattern is actually a literal string, process it separately to avoid
+cluttering up the main loop. */
-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)
-{
-unsigned int n8 = 0;
-while (p[0] < NOTACHAR)
+if ((options & PCRE2_LITERAL) != 0)
{
- unsigned int n = 0;
- if (p[0] != except)
+ while (ptr < ptrend)
{
- while(p[n+1] == p[0] + n + 1) n++;
- n8 += add_to_class(classbits, uchardptr, options, cb, p[0], p[n]);
+ if (parsed_pattern >= parsed_pattern_end)
+ {
+ errorcode = ERR63; /* Internal error (parsed pattern overflow) */
+ goto FAILED;
+ }
+ thisptr = ptr;
+ GETCHARINCTEST(c, ptr);
+ if (auto_callout)
+ parsed_pattern = manage_callouts(thisptr, &previous_callout,
+ auto_callout, parsed_pattern, cb);
+ PARSED_LITERAL(c, parsed_pattern);
}
- p += n + 1;
+ goto PARSED_END;
}
-return n8;
-}
+/* Process a real regex which may contain meta-characters. */
+top_nest = NULL;
+end_nests = (nest_save *)(cb->start_workspace + cb->workspace_size);
-/*************************************************
-* Add characters not in a list to a class *
-*************************************************/
-
-/* This function is used for adding the complement of a list of horizontal or
-vertical whitespace to a class. The list must be in order.
-
-Arguments:
- classbits the bit map for characters < 256
- uchardptr points to the pointer for extra data
- options the options word
- 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
-*/
+/* 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. */
-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 & PCRE2_UTF) != 0;
-unsigned int n8 = 0;
-if (p[0] > 0)
- 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, cb, p[0] + 1,
- (p[1] == NOTACHAR) ? (utf ? 0x10ffffu : 0xffffffffu) : p[1] - 1);
- p++;
- }
-return n8;
-}
+end_nests = (nest_save *)((char *)end_nests -
+ ((cb->workspace_size * sizeof(PCRE2_UCHAR)) % sizeof(nest_save)));
+/* PCRE2_EXTENDED_MORE implies PCRE2_EXTENDED */
+if ((options & PCRE2_EXTENDED_MORE) != 0) options |= PCRE2_EXTENDED;
-/*************************************************
-* Process (*VERB) name for escapes *
-*************************************************/
+/* Now scan the pattern */
-/* 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.
+while (ptr < ptrend)
+ {
+ int prev_expect_cond_assert;
+ uint32_t min_repeat, max_repeat;
+ uint32_t set, unset, *optset;
+ uint32_t terminator;
+ uint32_t prev_meta_quantifier;
+ BOOL prev_okquantifier;
+ PCRE2_SPTR tempptr;
+ PCRE2_SIZE offset;
+
+ if (parsed_pattern >= parsed_pattern_end)
+ {
+ errorcode = ERR63; /* Internal error (parsed pattern overflow) */
+ goto FAILED;
+ }
-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
-*/
+ if (nest_depth > cb->cx->parens_nest_limit)
+ {
+ errorcode = ERR19;
+ goto FAILED; /* Parentheses too deeply nested */
+ }
-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;
+ /* Get next input character, save its position for callout handling. */
-for (; ptr < cb->end_pattern; ptr++)
- {
- uint32_t x = *ptr;
+ thisptr = ptr;
+ GETCHARINCTEST(c, ptr);
- /* Skip over literals */
+ /* Copy quoted literals until \E, allowing for the possibility of automatic
+ callouts, except when processing a (*VERB) "name". */
if (inescq)
{
- if (x == CHAR_BACKSLASH && ptr[1] == CHAR_E)
+ if (c == CHAR_BACKSLASH && ptr < ptrend && *ptr == CHAR_E)
{
inescq = FALSE;
- ptr++;;
- continue;
+ ptr++; /* Skip E */
}
+ else
+ {
+ if (expect_cond_assert > 0) /* A literal is not allowed if we are */
+ { /* expecting a conditional assertion, */
+ ptr--; /* but an empty \Q\E sequence is OK. */
+ errorcode = ERR28;
+ goto FAILED;
+ }
+ if (!inverbname && after_manual_callout-- <= 0)
+ parsed_pattern = manage_callouts(thisptr, &previous_callout,
+ auto_callout, parsed_pattern, cb);
+ PARSED_LITERAL(c, parsed_pattern);
+ meta_quantifier = 0;
+ }
+ continue; /* Next character */
}
- else /* Not a literal character */
+ /* If we are processing the "name" part of a (*VERB:NAME) item, all
+ characters up to the closing parenthesis are literals except when
+ PCRE2_ALT_VERBNAMES is set. That causes backslash interpretation, but only \Q
+ and \E and escaped characters are allowed (no character types such as \d). If
+ PCRE2_EXTENDED is also set, we must ignore white space and # comments. Do
+ this by not entering the special (*VERB:NAME) processing - they are then
+ picked up below. Note that c is a character, not a code unit, so we must not
+ use MAX_255 to test its size because MAX_255 tests code units and is assumed
+ TRUE in 8-bit mode. */
+
+ if (inverbname &&
+ (
+ /* EITHER: not both options set */
+ ((options & (PCRE2_EXTENDED | PCRE2_ALT_VERBNAMES)) !=
+ (PCRE2_EXTENDED | PCRE2_ALT_VERBNAMES)) ||
+ /* OR: character > 255 */
+ c > 255 ||
+ /* OR: not a # comment or white space */
+ (c != CHAR_NUMBER_SIGN && (cb->ctypes[c] & ctype_space) == 0)
+ ))
{
- if (x == CHAR_RIGHT_PARENTHESIS) break;
+ PCRE2_SIZE verbnamelength;
- /* Skip over comments and whitespace in extended mode. */
-
- if ((options & PCRE2_EXTENDED) != 0)
+ switch(c)
{
- PCRE2_SPTR wscptr = ptr;
- while (MAX_255(x) && (cb->ctypes[x] & ctype_space) != 0) x = *(++ptr);
- if (x == CHAR_NUMBER_SIGN)
+ default:
+ PARSED_LITERAL(c, parsed_pattern);
+ break;
+
+ case CHAR_RIGHT_PARENTHESIS:
+ inverbname = FALSE;
+ okquantifier = FALSE; /* Was probably set by literals */
+ /* This is the length in characters */
+ verbnamelength = (PCRE2_SIZE)(parsed_pattern - verblengthptr - 1);
+ /* But the limit on the length is in code units */
+ if (ptr - verbnamestart - 1 > (int)MAX_MARK)
{
- 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
- }
+ ptr--;
+ errorcode = ERR76;
+ goto FAILED;
}
+ *verblengthptr = (uint32_t)verbnamelength;
+ break;
- /* If we have skipped any characters, restart the loop. */
+ case CHAR_BACKSLASH:
+ if ((options & PCRE2_ALT_VERBNAMES) != 0)
+ {
+ escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,
+ FALSE, cb);
+ if (errorcode != 0) goto FAILED;
+ }
+ else escape = 0; /* Treat all as literal */
- if (ptr > wscptr)
+ switch(escape)
{
- ptr--;
- continue;
+ case 0:
+ PARSED_LITERAL(c, parsed_pattern);
+ break;
+
+ case ESC_Q:
+ inescq = TRUE;
+ break;
+
+ case ESC_E: /* Ignore */
+ break;
+
+ default:
+ errorcode = ERR40; /* Invalid in verb name */
+ goto FAILED;
}
}
+ continue; /* Next character in pattern */
+ }
- /* Process escapes */
+ /* Not a verb name character. At this point we must process everything that
+ must not change the quantification state. This is mainly comments, but we
+ handle \Q and \E here as well, so that an item such as A\Q\E+ is treated as
+ A+, as in Perl. An isolated \E is ignored. */
- if (x == '\\')
+ if (c == CHAR_BACKSLASH && ptr < ptrend)
+ {
+ if (*ptr == CHAR_Q || *ptr == CHAR_E)
{
- 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;
- }
+ inescq = *ptr == CHAR_Q;
+ ptr++;
+ continue;
}
}
- /* We have the next character in the name. */
+ /* Skip over whitespace and # comments in extended mode. Note that c is a
+ character, not a code unit, so we must not use MAX_255 to test its size
+ because MAX_255 tests code units and is assumed TRUE in 8-bit mode. */
-#ifdef SUPPORT_UNICODE
- if (utf)
+ if ((options & PCRE2_EXTENDED) != 0)
{
- if (code == NULL) /* Just want the length */
+ if (c < 256 && (cb->ctypes[c] & ctype_space) != 0) continue;
+ if (c == CHAR_NUMBER_SIGN)
{
-#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++;
+ while (ptr < ptrend)
+ {
+ 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) FORWARDCHARTEST(ptr, ptrend);
#endif
- }
- else
- {
- PCRE2_UCHAR cbuff[8];
- x = PRIV(ord2utf)(x, cbuff);
- memcpy(code, cbuff, CU2BYTES(x));
- code += x;
+ }
+ continue; /* Next character in pattern */
}
}
- else
-#endif /* SUPPORT_UNICODE */
- /* Not UTF */
+ /* Skip over bracketed comments */
+
+ if (c == CHAR_LEFT_PARENTHESIS && ptrend - ptr >= 2 &&
+ ptr[0] == CHAR_QUESTION_MARK && ptr[1] == CHAR_NUMBER_SIGN)
{
- if (code != NULL) *code++ = (PCRE2_UCHAR)x;
+ while (++ptr < ptrend && *ptr != CHAR_RIGHT_PARENTHESIS);
+ if (ptr >= ptrend)
+ {
+ errorcode = ERR18; /* A special error for missing ) in a comment */
+ goto FAILED; /* to make it easier to debug. */
+ }
+ ptr++;
+ continue; /* Next character in pattern */
}
- arglen++;
+ /* If the next item is not a quantifier, fill in length of any previous
+ callout and create an auto callout if required. */
- if ((unsigned int)arglen > MAX_MARK)
+ if (c != CHAR_ASTERISK && c != CHAR_PLUS && c != CHAR_QUESTION_MARK &&
+ (c != CHAR_LEFT_CURLY_BRACKET ||
+ (tempptr = ptr,
+ !read_repeat_counts(&tempptr, ptrend, NULL, NULL, &errorcode))))
{
- *errorcodeptr = ERR76;
- *ptrptr = ptr;
- return -1;
+ if (after_manual_callout-- <= 0)
+ parsed_pattern = manage_callouts(thisptr, &previous_callout, auto_callout,
+ parsed_pattern, cb);
}
- }
-/* Update the pointers before returning. */
+ /* If expect_cond_assert is 2, we have just passed (?( and are expecting an
+ assertion, possibly preceded by a callout. If the value is 1, we have just
+ had the callout and expect an assertion. There must be at least 3 more
+ characters in all cases. When expect_cond_assert is 2, we know that the
+ current character is an opening parenthesis, as otherwise we wouldn't be
+ here. However, when it is 1, we need to check, and it's easiest just to check
+ always. Note that expect_cond_assert may be negative, since all callouts just
+ decrement it. */
-*ptrptr = ptr;
-if (codeptr != NULL) *codeptr = code;
-return arglen;
-}
+ if (expect_cond_assert > 0)
+ {
+ BOOL ok = c == CHAR_LEFT_PARENTHESIS && ptrend - ptr >= 3 &&
+ ptr[0] == CHAR_QUESTION_MARK;
+ if (ok) switch(ptr[1])
+ {
+ case CHAR_C:
+ ok = expect_cond_assert == 2;
+ break;
+ case CHAR_EQUALS_SIGN:
+ case CHAR_EXCLAMATION_MARK:
+ break;
+ case CHAR_LESS_THAN_SIGN:
+ ok = ptr[2] == CHAR_EQUALS_SIGN || ptr[2] == CHAR_EXCLAMATION_MARK;
+ break;
-/*************************************************
-* Macro for the next two functions *
-*************************************************/
+ default:
+ ok = FALSE;
+ }
-/* 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; \
- } \
+ if (!ok)
+ {
+ ptr--; /* Adjust error offset */
+ errorcode = ERR28;
+ goto FAILED;
+ }
}
+ /* Remember whether we are expecting a conditional assertion, and set the
+ default for this item. */
+ prev_expect_cond_assert = expect_cond_assert;
+ expect_cond_assert = 0;
-/*************************************************
-* Scan regex to identify named groups *
-*************************************************/
+ /* Remember quantification status for the previous significant item, then set
+ default for this item. */
-/* 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.
+ prev_okquantifier = okquantifier;
+ prev_meta_quantifier = meta_quantifier;
+ okquantifier = FALSE;
+ meta_quantifier = 0;
-Arguments:
- ptrptr points to pointer to the start of the pattern
- options compiling dynamic options
- cb pointer to the compile data block
+ /* If the previous significant item was a quantifier, adjust the parsed code
+ if there is a following modifier. The base meta value is always followed by
+ the PLUS and QUERY values, in that order. We do this here rather than after
+ reading a quantifier so that intervening comments and /x whitespace can be
+ ignored without having to replicate code. */
-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;
+ if (prev_meta_quantifier != 0 && (c == CHAR_QUESTION_MARK || c == CHAR_PLUS))
+ {
+ parsed_pattern[(prev_meta_quantifier == META_MINMAX)? -3 : -1] =
+ prev_meta_quantifier + ((c == CHAR_QUESTION_MARK)?
+ 0x00020000u : 0x00010000u);
+ continue; /* Next character in pattern */
+ }
-#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);
+ /* Process the next item in the main part of a pattern. */
-/* 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. */
+ switch(c)
+ {
+ default: /* Non-special character */
+ PARSED_LITERAL(c, parsed_pattern);
+ break;
-end_nests = (nest_save *)((char *)end_nests -
- ((cb->workspace_size * sizeof(PCRE2_UCHAR)) % sizeof(nest_save)));
-/* Now scan the pattern */
+ /* ---- Escape sequence ---- */
-for (; ptr < cb->end_pattern; ptr++)
- {
- c = *ptr;
+ case CHAR_BACKSLASH:
+ tempptr = ptr;
+ escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode, options,
+ FALSE, cb);
+ if (errorcode != 0)
+ {
+ ESCAPE_FAILED:
+ if ((cb->cx->extra_options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0)
+ goto FAILED;
+ ptr = tempptr;
+ if (ptr >= ptrend) c = CHAR_BACKSLASH; else
+ {
+ GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */
+ }
+ escape = 0; /* Treat as literal character */
+ }
- /* 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). */
+ /* The escape was a data escape or literal character. */
- if (skiptoket != 0)
- {
- if (c != CHAR_RIGHT_PARENTHESIS) continue;
- skiptoket = 0;
- }
+ if (escape == 0)
+ {
+ PARSED_LITERAL(c, parsed_pattern);
+ }
- /* Skip over literals */
+ /* The escape was a back (or forward) reference. We keep the offset in
+ order to give a more useful diagnostic for a bad forward reference. For
+ references to groups numbered less than 10 we can't use more than two items
+ in parsed_pattern because they may be just two characters in the input (and
+ in a 64-bit world an offset may need two elements). So for them, the offset
+ of the first occurrent is held in a special vector. */
- if (inescq)
- {
- if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E)
+ else if (escape < 0)
{
- inescq = FALSE;
- ptr++;
+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 1);
+ escape = -escape;
+ *parsed_pattern++ = META_BACKREF | (uint32_t)escape;
+ if (escape < 10)
+ {
+ if (cb->small_ref_offset[escape] == PCRE2_UNSET)
+ cb->small_ref_offset[escape] = offset;
+ }
+ else
+ {
+ PUTOFFSET(offset, parsed_pattern);
+ }
+ okquantifier = TRUE;
}
- 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)
+ /* The escape was a character class such as \d etc. or other special
+ escape indicator such as \A or \X. Most of them generate just a single
+ parsed item, but \P and \p are followed by a 16-bit type and a 16-bit
+ value. They are supported only when Unicode is available. The type and
+ value are packed into a single 32-bit value so that the whole sequences
+ uses only two elements in the parsed_vector. This is because the same
+ coding is used if \d (for example) is turned into \p{Nd} when PCRE2_UCP is
+ set.
+
+ There are also some cases where the escape sequence is followed by a name:
+ \k{name}, \k<name>, and \k'name' are backreferences by name, and \g<name>
+ and \g'name' are subroutine calls by name; \g{name} is a synonym for
+ \k{name}. Note that \g<number> and \g'number' are handled by check_escape()
+ and returned as a negative value (handled above). A name is coded as an
+ offset into the pattern and a length. */
+
+ else switch (escape)
{
- ptr++;
- while (ptr < cb->end_pattern)
+ case ESC_C:
+#ifdef NEVER_BACKSLASH_C
+ errorcode = ERR85;
+ goto ESCAPE_FAILED;
+#else
+ if ((options & PCRE2_NEVER_BACKSLASH_C) != 0)
{
- if (IS_NEWLINE(ptr)) /* For non-fixed-length newline cases, */
- { /* IS_NEWLINE sets cb->nllen. */
- ptr += cb->nllen;
+ errorcode = ERR83;
+ goto ESCAPE_FAILED;
+ }
+#endif
+ okquantifier = TRUE;
+ *parsed_pattern++ = META_ESCAPE + escape;
+ break;
+
+ case ESC_X:
+#ifndef SUPPORT_UNICODE
+ errorcode = ERR45; /* Supported only with Unicode support */
+ goto ESCAPE_FAILED;
+#endif
+ case ESC_H:
+ case ESC_h:
+ case ESC_N:
+ case ESC_R:
+ case ESC_V:
+ case ESC_v:
+ okquantifier = TRUE;
+ *parsed_pattern++ = META_ESCAPE + escape;
+ break;
+
+ default: /* \A, \B, \b, \G, \K, \Z, \z cannot be quantified. */
+ *parsed_pattern++ = META_ESCAPE + escape;
+ break;
+
+ /* Escapes that change in UCP mode. Note that PCRE2_UCP will never be set
+ without Unicode support because it is checked when pcre2_compile() is
+ called. */
+
+ case ESC_d:
+ case ESC_D:
+ case ESC_s:
+ case ESC_S:
+ case ESC_w:
+ case ESC_W:
+ okquantifier = TRUE;
+ if ((options & PCRE2_UCP) == 0)
+ {
+ *parsed_pattern++ = META_ESCAPE + escape;
+ }
+ else
+ {
+ *parsed_pattern++ = META_ESCAPE +
+ ((escape == ESC_d || escape == ESC_s || escape == ESC_w)?
+ ESC_p : ESC_P);
+ switch(escape)
+ {
+ case ESC_d:
+ case ESC_D:
+ *parsed_pattern++ = (PT_PC << 16) | ucp_Nd;
+ break;
+
+ case ESC_s:
+ case ESC_S:
+ *parsed_pattern++ = PT_SPACE << 16;
+ break;
+
+ case ESC_w:
+ case ESC_W:
+ *parsed_pattern++ = PT_WORD << 16;
break;
}
- ptr++;
+ }
+ break;
+
+ /* Unicode property matching */
+
+ case ESC_P:
+ case ESC_p:
#ifdef SUPPORT_UNICODE
- if (utf) FORWARDCHAR(ptr);
+ {
+ BOOL negated;
+ uint16_t ptype = 0, pdata = 0;
+ if (!get_ucp(&ptr, &negated, &ptype, &pdata, &errorcode, cb))
+ goto ESCAPE_FAILED;
+ if (negated) escape = (escape == ESC_P)? ESC_p : ESC_P;
+ *parsed_pattern++ = META_ESCAPE + escape;
+ *parsed_pattern++ = (ptype << 16) | pdata;
+ okquantifier = TRUE;
+ }
+#else
+ errorcode = ERR45;
+ goto ESCAPE_FAILED;
#endif
+ break; /* End \P and \p */
+
+ /* When \g is used with quotes or angle brackets as delimiters, it is a
+ numerical or named subroutine call, and control comes here. When used
+ with brace delimiters it is a numberical back reference and does not come
+ here because check_escape() returns it directly as a reference. \k is
+ always a named back reference. */
+
+ case ESC_g:
+ case ESC_k:
+ if (ptr >= ptrend || (*ptr != CHAR_LEFT_CURLY_BRACKET &&
+ *ptr != CHAR_LESS_THAN_SIGN && *ptr != CHAR_APOSTROPHE))
+ {
+ errorcode = (escape == ESC_g)? ERR57 : ERR69;
+ goto ESCAPE_FAILED;
}
+ terminator = (*ptr == CHAR_LESS_THAN_SIGN)?
+ CHAR_GREATER_THAN_SIGN : (*ptr == CHAR_APOSTROPHE)?
+ CHAR_APOSTROPHE : CHAR_RIGHT_CURLY_BRACKET;
+
+ /* For a non-braced \g, check for a numerical recursion. */
+
+ if (escape == ESC_g && terminator != CHAR_RIGHT_CURLY_BRACKET)
+ {
+ PCRE2_SPTR p = ptr + 1;
+
+ if (read_number(&p, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &i,
+ &errorcode))
+ {
+ if (p >= ptrend || *p != terminator)
+ {
+ errorcode = ERR57;
+ goto ESCAPE_FAILED;
+ }
+ ptr = p;
+ goto SET_RECURSION;
+ }
+ if (errorcode != 0) goto ESCAPE_FAILED;
+ }
+
+ /* Not a numerical recursion */
+
+ if (!read_name(&ptr, ptrend, terminator, &offset, &name, &namelen,
+ &errorcode, cb)) goto ESCAPE_FAILED;
+
+ /* \k and \g when used with braces are back references, whereas \g used
+ with quotes or angle brackets is a recursion */
+
+ *parsed_pattern++ =
+ (escape == ESC_k || terminator == CHAR_RIGHT_CURLY_BRACKET)?
+ META_BACKREF_BYNAME : META_RECURSE_BYNAME;
+ *parsed_pattern++ = namelen;
+
+ PUTOFFSET(offset, parsed_pattern);
+ okquantifier = TRUE;
+ break; /* End special escape processing */
}
+ break; /* End escape sequence processing */
+
+
+ /* ---- Single-character special items ---- */
+
+ case CHAR_CIRCUMFLEX_ACCENT:
+ *parsed_pattern++ = META_CIRCUMFLEX;
+ break;
+
+ case CHAR_DOLLAR_SIGN:
+ *parsed_pattern++ = META_DOLLAR;
+ break;
+
+ case CHAR_DOT:
+ *parsed_pattern++ = META_DOT;
+ okquantifier = TRUE;
+ break;
+
- /* If we skipped any characters, restart the loop. Otherwise, we didn't see
- a comment. */
+ /* ---- Single-character quantifiers ---- */
- if (ptr > wscptr)
+ case CHAR_ASTERISK:
+ meta_quantifier = META_ASTERISK;
+ goto CHECK_QUANTIFIER;
+
+ case CHAR_PLUS:
+ meta_quantifier = META_PLUS;
+ goto CHECK_QUANTIFIER;
+
+ case CHAR_QUESTION_MARK:
+ meta_quantifier = META_QUERY;
+ goto CHECK_QUANTIFIER;
+
+
+ /* ---- Potential {n,m} quantifier ---- */
+
+ case CHAR_LEFT_CURLY_BRACKET:
+ if (!read_repeat_counts(&ptr, ptrend, &min_repeat, &max_repeat,
+ &errorcode))
{
- ptr--;
- continue;
+ if (errorcode != 0) goto FAILED; /* Error in quantifier. */
+ PARSED_LITERAL(c, parsed_pattern); /* Not a quantifier */
+ break; /* No more quantifier processing */
}
- }
+ meta_quantifier = META_MINMAX;
+ /* Fall through */
- /* Process the next pattern item. */
- switch(c)
- {
- default: /* Most characters are just skipped */
- break;
+ /* ---- Quantifier post-processing ---- */
- /* Skip escapes except for \Q */
+ /* Check that a quantifier is allowed after the previous item. */
- 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;
+ CHECK_QUANTIFIER:
+ if (!prev_okquantifier)
+ {
+ errorcode = ERR9;
+ goto FAILED_BACK;
+ }
+
+ /* Now we can put the quantifier into the parsed pattern vector. At this
+ stage, we have only the basic quantifier. The check for a following + or ?
+ modifier happens at the top of the loop, after any intervening comments
+ have been removed. */
+
+ *parsed_pattern++ = meta_quantifier;
+ if (c == CHAR_LEFT_CURLY_BRACKET)
+ {
+ *parsed_pattern++ = min_repeat;
+ *parsed_pattern++ = max_repeat;
+ }
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. */
+
+ /* ---- Character class ---- */
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)
+ okquantifier = TRUE;
+
+ /* 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. */
+
+ if (ptrend - ptr >= 6 &&
+ (PRIV(strncmp_c8)(ptr, STRING_WEIRD_STARTWORD, 6) == 0 ||
+ PRIV(strncmp_c8)(ptr, STRING_WEIRD_ENDWORD, 6) == 0))
{
+ *parsed_pattern++ = META_ESCAPE + ESC_b;
+
+ if (ptr[2] == CHAR_LESS_THAN_SIGN)
+ {
+ *parsed_pattern++ = META_LOOKAHEAD;
+ }
+ else
+ {
+ *parsed_pattern++ = META_LOOKBEHIND;
+ *has_lookbehind = TRUE;
+
+ /* The offset is used only for the "non-fixed length" error; this won't
+ occur here, so just store zero. */
+
+ PUTOFFSET((PCRE2_SIZE)0, parsed_pattern);
+ }
+
+ if ((options & PCRE2_UCP) == 0)
+ *parsed_pattern++ = META_ESCAPE + ESC_w;
+ else
+ {
+ *parsed_pattern++ = META_ESCAPE + ESC_p;
+ *parsed_pattern++ = PT_WORD << 16;
+ }
+ *parsed_pattern++ = META_KET;
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. */
+ /* PCRE supports POSIX class stuff inside a class. Perl gives an error if
+ they are encountered at the top level, so we'll do that too. */
+
+ if (ptr < ptrend && (*ptr == CHAR_COLON || *ptr == CHAR_DOT ||
+ *ptr == CHAR_EQUALS_SIGN) &&
+ check_posix_syntax(ptr, ptrend, &tempptr))
+ {
+ errorcode = (*ptr-- == CHAR_COLON)? ERR12 : ERR13;
+ goto FAILED;
+ }
+
+ /* Process a regular character class. If the first character is '^', set
+ the negation flag. If the first few characters (either before or after ^)
+ are \Q\E or \E or space or tab in extended-more mode, we skip them too.
+ This makes for compatibility with Perl. */
negate_class = FALSE;
- for (;;)
+ while (ptr < ptrend)
{
- c = *(++ptr); /* First character in class */
+ GETCHARINCTEST(c, ptr);
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)
+ if (ptr < ptrend && *ptr == CHAR_E) ptr++;
+ else if (ptrend - ptr >= 3 &&
+ PRIV(strncmp_c8)(ptr, STR_Q STR_BACKSLASH STR_E, 3) == 0)
ptr += 3;
else
break;
}
+ else if ((options & PCRE2_EXTENDED_MORE) != 0 &&
+ (c == CHAR_SPACE || c == CHAR_HT)) /* Note: just these two */
+ continue;
else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT)
negate_class = TRUE;
else break;
}
+ /* Now the real contents of the class; c has the first "real" character.
+ Empty classes are permitted only if the option is set. */
+
if (c == CHAR_RIGHT_SQUARE_BRACKET &&
(cb->external_options & PCRE2_ALLOW_EMPTY_CLASS) != 0)
- break;
+ {
+ *parsed_pattern++ = negate_class? META_CLASS_EMPTY_NOT : META_CLASS_EMPTY;
+ break; /* End of class processing */
+ }
+
+ /* Process a non-empty class. */
+
+ *parsed_pattern++ = negate_class? META_CLASS_NOT : META_CLASS;
+ class_range_state = RANGE_NO;
+
+ /* 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 ranges where both values are literal; [\xC1-\xE9] is different to [A-Z]
+ in this respect. In order to accommodate this, we keep track of whether
+ character values are literal or not, and a state variable for handling
+ ranges. */
/* 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
+ BOOL char_is_literal = TRUE;
/* Inside \Q...\E everything is literal except \E */
if (inescq)
{
- if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E) /* If we are at \E */
+ if (c == CHAR_BACKSLASH && ptr < ptrend && *ptr == CHAR_E)
{
inescq = FALSE; /* Reset literal state */
ptr++; /* Skip the 'E' */
+ goto CLASS_CONTINUE;
}
- goto CONTINUE_CLASS;
+ goto CLASS_LITERAL;
}
- /* Skip POSIX class names. */
+ /* Skip over space and tab (only) in extended-more mode. */
+
+ if ((options & PCRE2_EXTENDED_MORE) != 0 &&
+ (c == CHAR_SPACE || c == CHAR_HT))
+ goto CLASS_CONTINUE;
+
+ /* Handle POSIX class names. Perl allows a negation extension of the
+ form [:^name:]. A square bracket that doesn't match the syntax is
+ treated as a literal. We also recognize the POSIX constructions
+ [.ch.] and [=ch=] ("collating elements") and fault them, as Perl
+ 5.6 and 5.8 do. */
+
if (c == CHAR_LEFT_SQUARE_BRACKET &&
- (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
- ptr[1] == CHAR_EQUALS_SIGN) && check_posix_syntax(ptr, &tempptr))
+ ptrend - ptr >= 3 &&
+ (*ptr == CHAR_COLON || *ptr == CHAR_DOT ||
+ *ptr == CHAR_EQUALS_SIGN) &&
+ check_posix_syntax(ptr, ptrend, &tempptr))
{
- ptr = tempptr + 1;
+ BOOL posix_negate = FALSE;
+ int posix_class;
+
+ /* Perl treats a hyphen before a POSIX class as a literal, not the
+ start of a range. However, it gives a warning in its warning mode. PCRE
+ does not have a warning mode, so we give an error, because this is
+ likely an error on the user's part. */
+
+ if (class_range_state == RANGE_STARTED)
+ {
+ errorcode = ERR50;
+ goto FAILED;
+ }
+
+ if (*ptr != CHAR_COLON)
+ {
+ errorcode = ERR13;
+ goto FAILED_BACK;
+ }
+
+ if (*(++ptr) == CHAR_CIRCUMFLEX_ACCENT)
+ {
+ posix_negate = TRUE;
+ ptr++;
+ }
+
+ posix_class = check_posix_name(ptr, (int)(tempptr - ptr));
+ if (posix_class < 0)
+ {
+ errorcode = ERR30;
+ goto FAILED;
+ }
+ ptr = tempptr + 2;
+
+ /* Perl treats a hyphen after a POSIX class as a literal, not the
+ start of a range. However, it gives a warning in its warning mode
+ unless the hyphen is the last character in the class. PCRE does not
+ have a warning mode, so we give an error, because this is likely an
+ error on the user's part. */
+
+ if (ptr < ptrend - 1 && *ptr == CHAR_MINUS &&
+ ptr[1] != CHAR_RIGHT_SQUARE_BRACKET)
+ {
+ errorcode = ERR50;
+ goto FAILED;
+ }
+
+ /* Set "a hyphen is not the start of a range" for the -] case, and also
+ in case the POSIX class is followed by \E or \Q\E (possibly repeated -
+ fuzzers do that kind of thing) and *then* a hyphen. This causes that
+ hyphen to be treated as a literal. I don't think it's worth setting up
+ special apparatus to do otherwise. */
+
+ class_range_state = RANGE_NO;
+
+ /* When PCRE2_UCP is set, some of the POSIX classes are converted to
+ use Unicode properties \p or \P or, in one case, \h or \H. The
+ substitutes table has two values per class, containing the type and
+ value of a \p or \P item. The special cases are specified with a
+ negative type: a non-zero value causes \h or \H to be used, and a zero
+ value falls through to behave like a non-UCP POSIX class. */
+
+#ifdef SUPPORT_UNICODE
+ if ((options & PCRE2_UCP) != 0)
+ {
+ int ptype = posix_substitutes[2*posix_class];
+ int pvalue = posix_substitutes[2*posix_class + 1];
+ if (ptype >= 0)
+ {
+ *parsed_pattern++ = META_ESCAPE + (posix_negate? ESC_P : ESC_p);
+ *parsed_pattern++ = (ptype << 16) | pvalue;
+ goto CLASS_CONTINUE;
+ }
+
+ if (pvalue != 0)
+ {
+ *parsed_pattern++ = META_ESCAPE + (posix_negate? ESC_H : ESC_h);
+ goto CLASS_CONTINUE;
+ }
+
+ /* Fall through */
+ }
+#endif /* SUPPORT_UNICODE */
+
+ /* Non-UCP POSIX class */
+
+ *parsed_pattern++ = posix_negate? META_POSIX_NEG : META_POSIX;
+ *parsed_pattern++ = posix_class;
+ }
+
+ /* Handle potential start of range */
+
+ else if (c == CHAR_MINUS && class_range_state >= RANGE_OK_ESCAPED)
+ {
+ *parsed_pattern++ = (class_range_state == RANGE_OK_LITERAL)?
+ META_RANGE_LITERAL : META_RANGE_ESCAPED;
+ class_range_state = RANGE_STARTED;
+ }
+
+ /* Handle a literal character */
+
+ else if (c != CHAR_BACKSLASH)
+ {
+ CLASS_LITERAL:
+ if (class_range_state == RANGE_STARTED)
+ {
+ if (c == parsed_pattern[-2]) /* Optimize one-char range */
+ parsed_pattern--;
+ else if (parsed_pattern[-2] > c) /* Check range is in order */
+ {
+ errorcode = ERR8;
+ goto FAILED_BACK;
+ }
+ else
+ {
+ if (!char_is_literal && parsed_pattern[-1] == META_RANGE_LITERAL)
+ parsed_pattern[-1] = META_RANGE_ESCAPED;
+ PARSED_LITERAL(c, parsed_pattern);
+ }
+ class_range_state = RANGE_NO;
+ }
+ else /* Potential start of range */
+ {
+ class_range_state = char_is_literal?
+ RANGE_OK_LITERAL : RANGE_OK_ESCAPED;
+ PARSED_LITERAL(c, parsed_pattern);
+ }
}
- else if (c == CHAR_BACKSLASH)
+
+ /* Handle escapes in a class */
+
+ else
{
- errorcode = 0;
- escape = PRIV(check_escape)(&ptr, cb->end_pattern, &c, &errorcode,
+ tempptr = ptr;
+ escape = PRIV(check_escape)(&ptr, ptrend, &c, &errorcode,
options, TRUE, cb);
- if (errorcode != 0) goto FAILED;
- if (escape == ESC_Q) inescq = TRUE;
+
+ if (errorcode != 0)
+ {
+ CLASS_ESCAPE_FAILED:
+ if ((cb->cx->extra_options & PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL) == 0)
+ goto FAILED;
+ ptr = tempptr;
+ if (ptr >= ptrend) c = CHAR_BACKSLASH; else
+ {
+ GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */
+ }
+ escape = 0; /* Treat as literal character */
+ }
+
+ if (escape == 0) /* Escaped character code point is in c */
+ {
+ char_is_literal = FALSE;
+ goto CLASS_LITERAL;
+ }
+
+ /* These three escapes do not alter the class range state. */
+
+ if (escape == ESC_b)
+ {
+ c = CHAR_BS; /* \b is backspace in a class */
+ char_is_literal = FALSE;
+ goto CLASS_LITERAL;
+ }
+
+ else if (escape == ESC_Q)
+ {
+ inescq = TRUE; /* Enter literal mode */
+ goto CLASS_CONTINUE;
+ }
+
+ else if (escape == ESC_E) /* Ignore orphan \E */
+ goto CLASS_CONTINUE;
+
+ /* The second part of a range can be a single-character escape
+ sequence (detected above), but not any of the other escapes. Perl
+ treats a hyphen as a literal in such circumstances. However, in Perl's
+ warning mode, a warning is given, so PCRE now faults it, as it is
+ almost certainly a mistake on the user's part. */
+
+ if (class_range_state == RANGE_STARTED)
+ {
+ errorcode = ERR50;
+ goto CLASS_ESCAPE_FAILED;
+ }
+
+ /* Of the remaining escapes, only those that define characters are
+ allowed in a class. None may start a range. */
+
+ class_range_state = RANGE_NO;
+ switch(escape)
+ {
+ case ESC_N:
+ errorcode = ERR71; /* Not supported in a class */
+ goto CLASS_ESCAPE_FAILED;
+
+ case ESC_H:
+ case ESC_h:
+ case ESC_V:
+ case ESC_v:
+ *parsed_pattern++ = META_ESCAPE + escape;
+ break;
+
+ /* These escapes are converted to Unicode property tests when
+ PCRE2_UCP is set. */
+
+ case ESC_d:
+ case ESC_D:
+ case ESC_s:
+ case ESC_S:
+ case ESC_w:
+ case ESC_W:
+ if ((options & PCRE2_UCP) == 0)
+ {
+ *parsed_pattern++ = META_ESCAPE + escape;
+ }
+ else
+ {
+ *parsed_pattern++ = META_ESCAPE +
+ ((escape == ESC_d || escape == ESC_s || escape == ESC_w)?
+ ESC_p : ESC_P);
+ switch(escape)
+ {
+ case ESC_d:
+ case ESC_D:
+ *parsed_pattern++ = (PT_PC << 16) | ucp_Nd;
+ break;
+
+ case ESC_s:
+ case ESC_S:
+ *parsed_pattern++ = PT_SPACE << 16;
+ break;
+
+ case ESC_w:
+ case ESC_W:
+ *parsed_pattern++ = PT_WORD << 16;
+ break;
+ }
+ }
+ break;
+
+ /* Explicit Unicode property matching */
+
+ case ESC_P:
+ case ESC_p:
+#ifdef SUPPORT_UNICODE
+ {
+ BOOL negated;
+ uint16_t ptype = 0, pdata = 0;
+ if (!get_ucp(&ptr, &negated, &ptype, &pdata, &errorcode, cb))
+ goto FAILED;
+ if (negated) escape = (escape == ESC_P)? ESC_p : ESC_P;
+ *parsed_pattern++ = META_ESCAPE + escape;
+ *parsed_pattern++ = (ptype << 16) | pdata;
+ }
+#else
+ errorcode = ERR45;
+ goto CLASS_ESCAPE_FAILED;
+#endif
+ break; /* End \P and \p */
+
+ default: /* All others are not allowed in a class */
+ errorcode = ERR7;
+ ptr--;
+ goto CLASS_ESCAPE_FAILED;
+ }
+
+ /* Perl gives a warning unless a following hyphen is the last character
+ in the class. PCRE throws an error. */
+
+ if (ptr < ptrend - 1 && *ptr == CHAR_MINUS &&
+ ptr[1] != CHAR_RIGHT_SQUARE_BRACKET)
+ {
+ errorcode = ERR50;
+ goto FAILED;
+ }
}
- CONTINUE_CLASS:
- c = *(++ptr);
+ /* Proceed to next thing in the class. */
+
+ CLASS_CONTINUE:
+ if (ptr >= ptrend)
+ {
+ errorcode = ERR6; /* Missing terminating ']' */
+ goto FAILED;
+ }
+ GETCHARINCTEST(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. */
+ if (class_range_state == RANGE_STARTED)
+ {
+ parsed_pattern[-1] = CHAR_MINUS;
+ class_range_state = RANGE_NO;
+ }
+
+ *parsed_pattern++ = META_CLASS_END;
+ break; /* End of character class */
+
+
+ /* ---- Opening parenthesis ---- */
case CHAR_LEFT_PARENTHESIS:
- nest_depth++;
+ if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
- if (ptr[1] != CHAR_QUESTION_MARK)
+ /* If ( is not followed by ? it is either a capture or a special verb. */
+
+ if (*ptr != CHAR_QUESTION_MARK)
{
- if (ptr[1] != CHAR_ASTERISK)
+ const char *vn;
+
+ /* Handle capturing brackets (or non-capturing if auto-capture is turned
+ off). */
+
+ if (*ptr != CHAR_ASTERISK)
{
- if ((options & PCRE2_NO_AUTO_CAPTURE) == 0) cb->bracount++;
+ nest_depth++;
+ if ((options & PCRE2_NO_AUTO_CAPTURE) == 0)
+ {
+ cb->bracount++;
+ *parsed_pattern++ = META_CAPTURE | cb->bracount;
+ }
+ else *parsed_pattern++ = META_NOCAPTURE;
}
- /* (*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
+ /* ---- Handle (*VERB) and (*VERB:NAME) ---- */
+
+ /* Do nothing for (*) so it gives a "bad quantifier" error rather than
+ "(*MARK) must have an argument". */
+
+ else if (ptrend - ptr > 1 && ptr[1] != CHAR_RIGHT_PARENTHESIS)
{
- ptr += 2;
- while (MAX_255(*ptr) && (cb->ctypes[*ptr] & ctype_word) != 0) ptr++;
- if (*ptr == CHAR_COLON && (options & PCRE2_ALT_VERBNAMES) != 0)
+ vn = verbnames;
+ if (!read_name(&ptr, ptrend, 0, &offset, &name, &namelen, &errorcode,
+ cb)) goto FAILED;
+ if (ptr >= ptrend || (*ptr != CHAR_COLON &&
+ *ptr != CHAR_RIGHT_PARENTHESIS))
{
- ptr++;
- if (process_verb_name(&ptr, NULL, &errorcode, options, utf, cb) < 0)
+ errorcode = ERR60; /* Malformed */
+ goto FAILED;
+ }
+
+ /* Scan the table of verb names */
+
+ for (i = 0; i < verbcount; i++)
+ {
+ if (namelen == verbs[i].len &&
+ PRIV(strncmp_c8)(name, vn, namelen) == 0)
+ break;
+ vn += verbs[i].len + 1;
+ }
+
+ if (i >= verbcount)
+ {
+ errorcode = ERR60; /* Verb not recognized */
+ goto FAILED;
+ }
+
+ /* An empty argument is treated as no argument. */
+
+ if (*ptr == CHAR_COLON && ptr + 1 < ptrend &&
+ ptr[1] == CHAR_RIGHT_PARENTHESIS)
+ ptr++; /* Advance to the closing parens */
+
+ /* Check for mandatory non-empty argument; this is (*MARK) */
+
+ if (verbs[i].has_arg > 0 && *ptr != CHAR_COLON)
+ {
+ errorcode = ERR66;
+ goto FAILED;
+ }
+
+ /* It appears that Perl allows any characters whatsoever, other than a
+ closing parenthesis, to appear in arguments ("names"), so we no longer
+ insist on 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. We set inverbname TRUE here, and let the
+ main loop take care of this so that escape and \x processing is done by
+ the main code above. */
+
+ if (*ptr++ == CHAR_COLON) /* Skip past : or ) */
+ {
+ if (verbs[i].has_arg < 0) /* Argument is forbidden */
+ {
+ errorcode = ERR59;
goto FAILED;
+ }
+ *parsed_pattern++ = verbs[i].meta +
+ ((verbs[i].meta != META_MARK)? 0x00010000u:0);
+ verblengthptr = parsed_pattern++;
+ verbnamestart = ptr;
+ inverbname = TRUE;
}
- else
+ else /* No verb "name" argument */
{
- while (ptr < cb->end_pattern && *ptr != CHAR_RIGHT_PARENTHESIS)
- ptr++;
+ *parsed_pattern++ = verbs[i].meta;
}
- nest_depth--;
- }
- }
+ } /* End of (*VERB) handling */
+ break; /* Done with this parenthesis */
+ } /* End of groups that don't start with (? */
+
+
+ /* ---- Items starting (? ---- */
+
+ /* The type of item is determined by what follows (?. Handle (?| and option
+ changes under "default" because both need a new block on the nest stack.
+ Comments starting with (?# are handled above. Note that there is some
+ ambiguity about the sequence (?- because if a digit follows it's a relative
+ recursion or subroutine call whereas otherwise it's an option unsetting. */
- /* Handle (?...) groups */
+ if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
- else switch(ptr[2])
+ switch(*ptr)
{
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;
- }
+ if (*ptr == CHAR_MINUS && ptrend - ptr > 1 && IS_DIGIT(ptr[1]))
+ goto RECURSION_BYNUMBER; /* The + case is handled by CHAR_PLUS */
- /* Handle (?| and (?imsxJU: which are the only other valid forms. Both
- need a new block on the nest stack. */
+ /* We now have either (?| or a (possibly empty) option setting,
+ optionally followed by a non-capturing group. */
+ nest_depth++;
if (top_nest == NULL) top_nest = (nest_save *)(cb->start_workspace);
else if (++top_nest >= end_nests)
{
@@ -3474,8 +3502,10 @@ for (; ptr < cb->end_pattern; ptr++)
}
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;
+ top_nest->options = options & PARSE_TRACKED_OPTIONS;
+
+ /* Start of non-capturing group that resets the capture count for each
+ branch. */
if (*ptr == CHAR_VERTICAL_LINE)
{
@@ -3483,76 +3513,226 @@ for (; ptr < cb->end_pattern; ptr++)
top_nest->max_group = (uint16_t)cb->bracount;
top_nest->flags |= NSF_RESET;
cb->external_flags |= PCRE2_DUPCAPUSED;
- break;
+ *parsed_pattern++ = META_NOCAPTURE;
+ ptr++;
}
- /* Scan options */
+ /* Scan for options imnsxJU to be set or unset. */
- top_nest->reset_group = 0;
- top_nest->max_group = 0;
+ else
+ {
+ top_nest->reset_group = 0;
+ top_nest->max_group = 0;
+ set = unset = 0;
+ optset = &set;
- set = unset = 0;
- optset = &set;
+ while (ptr < ptrend && *ptr != CHAR_RIGHT_PARENTHESIS &&
+ *ptr != CHAR_COLON)
+ {
+ switch (*ptr++)
+ {
+ case CHAR_MINUS: optset = &unset; break;
- /* Need only track (?x: and (?J: at this stage */
+ case CHAR_J: /* Record that it changed in the external options */
+ *optset |= PCRE2_DUPNAMES;
+ cb->external_flags |= PCRE2_JCHANGED;
+ break;
- while (*ptr != CHAR_RIGHT_PARENTHESIS && *ptr != CHAR_COLON)
- {
- switch (*ptr++)
- {
- case CHAR_MINUS: optset = &unset; break;
+ case CHAR_i: *optset |= PCRE2_CASELESS; break;
+ case CHAR_m: *optset |= PCRE2_MULTILINE; break;
+ case CHAR_n: *optset |= PCRE2_NO_AUTO_CAPTURE; break;
+ case CHAR_s: *optset |= PCRE2_DOTALL; break;
+ case CHAR_U: *optset |= PCRE2_UNGREEDY; break;
- case CHAR_x: *optset |= PCRE2_EXTENDED; break;
+ /* If x appears twice it sets the extended extended option. */
- case CHAR_J:
- *optset |= PCRE2_DUPNAMES;
- cb->external_flags |= PCRE2_JCHANGED;
- break;
+ case CHAR_x:
+ *optset |= PCRE2_EXTENDED;
+ if (ptr < ptrend && *ptr == CHAR_x)
+ {
+ *optset |= PCRE2_EXTENDED_MORE;
+ ptr++;
+ }
+ break;
- case CHAR_i:
- case CHAR_m:
- case CHAR_s:
- case CHAR_U:
- break;
+ default:
+ errorcode = ERR11;
+ ptr--; /* Correct the offset */
+ goto FAILED;
+ }
+ }
- default:
- errorcode = ERR11;
- ptr--; /* Correct the offset */
- goto FAILED;
+ /* If we are setting extended without extended-more, ensure that any
+ existing extended-more gets unset. Also, unsetting extended must also
+ unset extended-more. */
+
+ if ((set & (PCRE2_EXTENDED|PCRE2_EXTENDED_MORE)) == PCRE2_EXTENDED ||
+ (unset & PCRE2_EXTENDED) != 0)
+ unset |= PCRE2_EXTENDED_MORE;
+
+ 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.
+ In this case, if the previous level set up a nest block, discard the
+ one we have just created. Otherwise adjust it for the previous level.
+ If the options ended with ':' we are starting a non-capturing group,
+ possibly with an options setting. */
+
+ if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
+ if (*ptr++ == CHAR_RIGHT_PARENTHESIS)
+ {
+ nest_depth--; /* This is not a nested group after all. */
+ if (top_nest > (nest_save *)(cb->start_workspace) &&
+ (top_nest-1)->nest_depth == nest_depth) top_nest--;
+ else top_nest->nest_depth = nest_depth;
+ }
+ else *parsed_pattern++ = META_NOCAPTURE;
+
+ /* If nothing changed, no need to record. */
+
+ if (set != 0 || unset != 0)
+ {
+ *parsed_pattern++ = META_OPTIONS;
+ *parsed_pattern++ = options;
}
+ } /* End options processing */
+ break; /* End default case after (? */
+
+
+ /* ---- Python syntax support ---- */
+
+ case CHAR_P:
+ if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
+
+ /* (?P<name> is the same as (?<name>, which defines a named group. */
+
+ if (*ptr == CHAR_LESS_THAN_SIGN)
+ {
+ terminator = CHAR_GREATER_THAN_SIGN;
+ goto DEFINE_NAME;
}
- options = (options | set) & (~unset);
+ /* (?P>name) is the same as (?&name), which is a recursion or subroutine
+ call. */
+
+ if (*ptr == CHAR_GREATER_THAN_SIGN) goto RECURSE_BY_NAME;
- /* 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. */
+ /* (?P=name) is the same as \k<name>, a back reference by name. Anything
+ else after (?P is an error. */
- if (*ptr == CHAR_RIGHT_PARENTHESIS)
+ if (*ptr != CHAR_EQUALS_SIGN)
{
- 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;
+ errorcode = ERR41;
+ goto FAILED;
}
- break;
+ if (!read_name(&ptr, ptrend, CHAR_RIGHT_PARENTHESIS, &offset, &name,
+ &namelen, &errorcode, cb)) goto FAILED;
+ *parsed_pattern++ = META_BACKREF_BYNAME;
+ *parsed_pattern++ = namelen;
+ PUTOFFSET(offset, parsed_pattern);
+ okquantifier = TRUE;
+ break; /* End of (?P processing */
- /* 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]))
+ /* ---- Recursion/subroutine calls by number ---- */
+
+ case CHAR_R:
+ i = 0; /* (?R) == (?R0) */
+ ptr++;
+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)
{
- while (IS_DIGIT(ptr[1])) ptr++;
+ errorcode = ERR58;
+ goto FAILED;
}
+ goto SET_RECURSION;
- /* Handle a string argument */
+ /* An item starting (?- followed by a digit comes here via the "default"
+ case because (?- followed by a non-digit is an options setting. */
- else
+ case CHAR_PLUS:
+ if (ptrend - ptr < 2 || !IS_DIGIT(ptr[1]))
{
- ptr++;
+ errorcode = ERR29; /* Missing number */
+ goto FAILED;
+ }
+ /* Fall through */
+
+ 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:
+ RECURSION_BYNUMBER:
+ if (!read_number(&ptr, ptrend,
+ (IS_DIGIT(*ptr))? -1:(int)(cb->bracount), /* + and - are relative */
+ MAX_GROUP_NUMBER, ERR61,
+ &i, &errorcode)) goto FAILED;
+ if (i < 0) /* NB (?0) is permitted */
+ {
+ errorcode = ERR15; /* Unknown group */
+ goto FAILED_BACK;
+ }
+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)
+ goto UNCLOSED_PARENTHESIS;
+
+ SET_RECURSION:
+ *parsed_pattern++ = META_RECURSE | (uint32_t)i;
+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern);
+ ptr++;
+ PUTOFFSET(offset, parsed_pattern);
+ okquantifier = TRUE;
+ break; /* End of recursive call by number handling */
+
+
+ /* ---- Recursion/subroutine calls by name ---- */
+
+ case CHAR_AMPERSAND:
+ RECURSE_BY_NAME:
+ if (!read_name(&ptr, ptrend, CHAR_RIGHT_PARENTHESIS, &offset, &name,
+ &namelen, &errorcode, cb)) goto FAILED;
+ *parsed_pattern++ = META_RECURSE_BYNAME;
+ *parsed_pattern++ = namelen;
+ PUTOFFSET(offset, parsed_pattern);
+ okquantifier = TRUE;
+ break;
+
+ /* ---- Callout with numerical or string argument ---- */
+
+ case CHAR_C:
+ if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
+
+ /* If the previous item was a condition starting (?(? an assertion,
+ optionally preceded by a callout, is expected. This is checked later on,
+ during actual compilation. However we need to identify this kind of
+ assertion in this pass because it must not be qualified. The value of
+ expect_cond_assert is set to 2 after (?(? is processed. We decrement it
+ for a callout - still leaving a positive value that identifies the
+ assertion. Multiple callouts or any other items will make it zero or
+ less, which doesn't matter because they will cause an error later. */
+
+ expect_cond_assert = prev_expect_cond_assert - 1;
+
+ /* If previous_callout is not NULL, it means this follows a previous
+ callout. If it was a manual callout, do nothing; this means its "length
+ of next pattern item" field will remain zero. If it was an automatic
+ callout, abolish it. */
+
+ if (previous_callout != NULL && (options & PCRE2_AUTO_CALLOUT) != 0 &&
+ previous_callout == parsed_pattern - 4 &&
+ parsed_pattern[-1] == 255)
+ parsed_pattern = previous_callout;
+
+ /* Save for updating next pattern item length, and skip one item before
+ completing. */
+
+ previous_callout = parsed_pattern;
+ after_manual_callout = 1;
+
+ /* Handle a string argument; specific delimiter is required. */
+
+ if (*ptr != CHAR_RIGHT_PARENTHESIS && !IS_DIGIT(*ptr))
+ {
+ PCRE2_SIZE calloutlength;
+ PCRE2_SPTR startptr = ptr;
+
delimiter = 0;
for (i = 0; PRIV(callout_start_delims)[i] != 0; i++)
{
@@ -3562,130 +3742,338 @@ for (; ptr < cb->end_pattern; ptr++)
break;
}
}
-
if (delimiter == 0)
{
errorcode = ERR82;
goto FAILED;
}
- start = ptr;
- do
+ *parsed_pattern = META_CALLOUT_STRING;
+ parsed_pattern += 3; /* Skip pattern info */
+
+ for (;;)
{
- if (++ptr >= cb->end_pattern)
+ if (++ptr >= ptrend)
{
errorcode = ERR81;
- ptr = start; /* To give a more useful message */
+ ptr = startptr; /* To give a more useful message */
+ goto FAILED;
+ }
+ if (*ptr == delimiter && (++ptr >= ptrend || *ptr != delimiter))
+ break;
+ }
+
+ calloutlength = (PCRE2_SIZE)(ptr - startptr);
+ if (calloutlength > UINT32_MAX)
+ {
+ errorcode = ERR72;
+ goto FAILED;
+ }
+ *parsed_pattern++ = (uint32_t)calloutlength;
+ offset = (PCRE2_SIZE)(startptr - cb->start_pattern);
+ PUTOFFSET(offset, parsed_pattern);
+ }
+
+ /* 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;
+ *parsed_pattern = META_CALLOUT_NUMBER; /* Numerical callout */
+ parsed_pattern += 3; /* Skip pattern info */
+ while (ptr < ptrend && IS_DIGIT(*ptr))
+ {
+ n = n * 10 + *ptr++ - CHAR_0;
+ if (n > 255)
+ {
+ errorcode = ERR38;
goto FAILED;
}
- if (ptr[0] == delimiter && ptr[1] == delimiter) ptr += 2;
}
- while (ptr[0] != delimiter);
+ *parsed_pattern++ = n;
}
- /* Check terminating ) */
+ /* Both formats must have a closing parenthesis */
- if (ptr[1] != CHAR_RIGHT_PARENTHESIS)
+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)
{
errorcode = ERR39;
- ptr++;
goto FAILED;
}
- break;
+ ptr++;
- /* Conditional group */
+ /* Remember the offset to the next item in the pattern, and set a default
+ length. This should get updated after the next item is read. */
- case CHAR_LEFT_PARENTHESIS:
- if (ptr[3] != CHAR_QUESTION_MARK) /* Not assertion or callout */
- {
- nest_depth++;
- ptr += 2;
- break;
- }
+ previous_callout[1] = ptr - cb->start_pattern;
+ previous_callout[2] = 0;
+ break; /* End callout */
- /* 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;
+ /* ---- Conditional group ---- */
- default:
- MISSING_ASSERTION:
- ptr += 3; /* To improve error message */
- errorcode = ERR28;
- goto FAILED;
- }
- break;
+ /* A condition can be an assertion, a number (referring to a numbered
+ group's having been set), a name (referring to a named group), or 'R',
+ referring to overall recursion. R<digits> and R&name are also permitted
+ for recursion state tests. Numbers may be preceded by + or - to specify a
+ relative group number.
- 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;
+ There are several syntaxes for testing a named group: (?(name)) is used
+ by Python; Perl 5.10 onwards uses (?(<name>) or (?('name')).
- case CHAR_P:
- if (ptr[3] != CHAR_LESS_THAN_SIGN)
+ There are two unfortunate ambiguities. 'R' can be the recursive thing or
+ the name 'R' (and similarly for 'R' followed by digits). 'DEFINE' can be
+ the Perl DEFINE feature or the Python named test. We look for a name
+ first; if not found, we try the other case.
+
+ For compatibility with auto-callouts, we allow a callout to be specified
+ before a condition that is an assertion. */
+
+ case CHAR_LEFT_PARENTHESIS:
+ if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
+ nest_depth++;
+
+ /* If the next character is ? there must be an assertion next (optionally
+ preceded by a callout). We do not check this here, but instead we set
+ expect_cond_assert to 2. If this is still greater than zero (callouts
+ decrement it) when the next assertion is read, it will be marked as a
+ condition that must not be repeated. A value greater than zero also
+ causes checking that an assertion (possibly with callout) follows. */
+
+ if (*ptr == CHAR_QUESTION_MARK)
{
- ptr += 3;
- break;
+ *parsed_pattern++ = META_COND_ASSERT;
+ ptr--; /* Pull pointer back to the opening parenthesis. */
+ expect_cond_assert = 2;
+ break; /* End of conditional */
}
- 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)
+ /* Handle (?([+-]number)... */
+
+ if (read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61, &i,
+ &errorcode))
{
- ptr += 3;
- break;
+ if (i <= 0)
+ {
+ errorcode = ERR15;
+ goto FAILED;
+ }
+ *parsed_pattern++ = META_COND_NUMBER;
+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 2);
+ PUTOFFSET(offset, parsed_pattern);
+ *parsed_pattern++ = i;
}
- c = CHAR_GREATER_THAN_SIGN; /* Terminator */
- goto DEFINE_NAME;
-
- case CHAR_APOSTROPHE:
- c = CHAR_APOSTROPHE; /* Terminator */
+ else if (errorcode != 0) goto FAILED; /* Number too big */
- DEFINE_NAME:
- name = ptr = ptr + 3;
+ /* No number found. Handle the special case (?(VERSION[>]=n.m)... */
- if (*ptr == c) /* Empty name */
+ else if (ptrend - ptr >= 10 &&
+ PRIV(strncmp_c8)(ptr, STRING_VERSION, 7) == 0 &&
+ ptr[7] != CHAR_RIGHT_PARENTHESIS)
{
- errorcode = ERR62;
- goto FAILED;
+ uint32_t ge = 0;
+ int major = 0;
+ int minor = 0;
+
+ ptr += 7;
+ if (*ptr == CHAR_GREATER_THAN_SIGN)
+ {
+ ge = 1;
+ ptr++;
+ }
+
+ /* NOTE: cannot write IS_DIGIT(*(++ptr)) here because IS_DIGIT
+ references its argument twice. */
+
+ if (*ptr != CHAR_EQUALS_SIGN || (ptr++, !IS_DIGIT(*ptr)))
+ goto BAD_VERSION_CONDITION;
+
+ if (!read_number(&ptr, ptrend, -1, 1000, ERR79, &major, &errorcode))
+ goto FAILED;
+
+ if (ptr >= ptrend) goto BAD_VERSION_CONDITION;
+ if (*ptr == CHAR_DOT)
+ {
+ if (++ptr >= ptrend || !IS_DIGIT(*ptr)) goto BAD_VERSION_CONDITION;
+ if (!read_number(&ptr, ptrend, -1, 99 , ERR79, &minor, &errorcode))
+ goto FAILED;
+ if (minor < 10) minor *= 10;
+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)
+ goto BAD_VERSION_CONDITION;
+ }
+
+ *parsed_pattern++ = META_COND_VERSION;
+ *parsed_pattern++ = ge;
+ *parsed_pattern++ = major;
+ *parsed_pattern++ = minor;
}
- if (IS_DIGIT(*ptr))
+ /* All the remaining cases now require us to read a name. We cannot at
+ this stage distinguish ambiguous cases such as (?(R12) which might be a
+ recursion test by number or a name, because the named groups have not yet
+ all been identified. Those cases are treated as names, but given a
+ different META code. */
+
+ else
{
- errorcode = ERR44; /* Group name must start with non-digit */
- goto FAILED;
- }
+ BOOL was_r_ampersand = FALSE;
+
+ if (*ptr == CHAR_R && ptrend - ptr > 1 && ptr[1] == CHAR_AMPERSAND)
+ {
+ terminator = CHAR_RIGHT_PARENTHESIS;
+ was_r_ampersand = TRUE;
+ ptr++;
+ }
+ else if (*ptr == CHAR_LESS_THAN_SIGN)
+ terminator = CHAR_GREATER_THAN_SIGN;
+ else if (*ptr == CHAR_APOSTROPHE)
+ terminator = CHAR_APOSTROPHE;
+ else
+ {
+ terminator = CHAR_RIGHT_PARENTHESIS;
+ ptr--; /* Point to char before name */
+ }
+ if (!read_name(&ptr, ptrend, terminator, &offset, &name, &namelen,
+ &errorcode, cb)) goto FAILED;
+
+ /* Handle (?(R&name) */
- if (MAX_255(*ptr) && (cb->ctypes[*ptr] & ctype_word) == 0)
+ if (was_r_ampersand)
+ {
+ *parsed_pattern = META_COND_RNAME;
+ ptr--; /* Back to closing parens */
+ }
+
+ /* Handle (?(name). If the name is "DEFINE" we identify it with a
+ special code. Likewise if the name consists of R followed only by
+ digits. Otherwise, handle it like a quoted name. */
+
+ else if (terminator == CHAR_RIGHT_PARENTHESIS)
+ {
+ if (namelen == 6 && PRIV(strncmp_c8)(name, STRING_DEFINE, 6) == 0)
+ *parsed_pattern = META_COND_DEFINE;
+ else
+ {
+ for (i = 1; i < (int)namelen; i++)
+ if (!IS_DIGIT(name[i])) break;
+ *parsed_pattern = (*name == CHAR_R && i >= (int)namelen)?
+ META_COND_RNUMBER : META_COND_NAME;
+ }
+ ptr--; /* Back to closing parens */
+ }
+
+ /* Handle (?('name') or (?(<name>) */
+
+ else *parsed_pattern = META_COND_NAME;
+
+ /* All these cases except DEFINE end with the name length and offset;
+ DEFINE just has an offset (for the "too many branches" error). */
+
+ if (*parsed_pattern++ != META_COND_DEFINE) *parsed_pattern++ = namelen;
+ PUTOFFSET(offset, parsed_pattern);
+ } /* End cases that read a name */
+
+ /* Check the closing parenthesis of the condition */
+
+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)
{
errorcode = ERR24;
goto FAILED;
}
+ ptr++;
+ break; /* End of condition processing */
+
+
+ /* ---- Atomic group ---- */
+
+ case CHAR_GREATER_THAN_SIGN:
+ *parsed_pattern++ = META_ATOMIC;
+ nest_depth++;
+ ptr++;
+ break;
+
- /* Advance ptr, set namelen and check its length. */
- READ_NAME(ctype_word, ERR48, errorcode);
+ /* ---- Lookahead assertions ---- */
- if (*ptr != c)
+ case CHAR_EQUALS_SIGN:
+ *parsed_pattern++ = META_LOOKAHEAD;
+ ptr++;
+ goto POST_ASSERTION;
+
+ case CHAR_EXCLAMATION_MARK:
+ *parsed_pattern++ = META_LOOKAHEADNOT;
+ ptr++;
+ goto POST_ASSERTION;
+
+
+ /* ---- Lookbehind assertions ---- */
+
+ /* (?< followed by = or ! is a lookbehind assertion. Otherwise (?< is the
+ start of the name of a capturing group. */
+
+ case CHAR_LESS_THAN_SIGN:
+ if (ptrend - ptr <= 1 ||
+ (ptr[1] != CHAR_EQUALS_SIGN && ptr[1] != CHAR_EXCLAMATION_MARK))
{
- errorcode = ERR42;
- goto FAILED;
+ terminator = CHAR_GREATER_THAN_SIGN;
+ goto DEFINE_NAME;
+ }
+ *parsed_pattern++ = (ptr[1] == CHAR_EQUALS_SIGN)?
+ META_LOOKBEHIND : META_LOOKBEHINDNOT;
+ *has_lookbehind = TRUE;
+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 2);
+ PUTOFFSET(offset, parsed_pattern);
+ ptr += 2;
+ /* Fall through */
+
+ /* If the previous item was a condition starting (?(? an assertion,
+ optionally preceded by a callout, is expected. This is checked later on,
+ during actual compilation. However we need to identify this kind of
+ assertion in this pass because it must not be qualified. The value of
+ expect_cond_assert is set to 2 after (?(? is processed. We decrement it
+ for a callout - still leaving a positive value that identifies the
+ assertion. Multiple callouts or any other items will make it zero or
+ less, which doesn't matter because they will cause an error later. */
+
+ POST_ASSERTION:
+ nest_depth++;
+ if (prev_expect_cond_assert > 0)
+ {
+ 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 = NSF_CONDASSERT;
+ top_nest->options = options & PARSE_TRACKED_OPTIONS;
}
+ break;
+
+
+ /* ---- Define a named group ---- */
+
+ /* A named group may be defined as (?'name') or (?<name>). In the latter
+ case we jump to DEFINE_NAME from the disambiguation of (?< above with the
+ terminator set to '>'. */
+
+ case CHAR_APOSTROPHE:
+ terminator = CHAR_APOSTROPHE; /* Terminator */
+
+ DEFINE_NAME:
+ if (!read_name(&ptr, ptrend, terminator, &offset, &name, &namelen,
+ &errorcode, cb)) goto FAILED;
+
+ /* We have a name for this capturing group. It is also assigned a number,
+ which is its primary means of identification. */
+
+ cb->bracount++;
+ *parsed_pattern++ = META_CAPTURE | cb->bracount;
+ nest_depth++;
+
+ /* Check not too many names */
if (cb->names_found >= MAX_NAME_COUNT)
{
@@ -3693,13 +4081,11 @@ for (; ptr < cb->end_pattern; ptr++)
goto FAILED;
}
+ /* Adjust the entry size to accommodate the longest name found. */
+
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.
@@ -3712,7 +4098,7 @@ for (; ptr < cb->end_pattern; ptr++)
for (i = 0; i < cb->names_found; i++, ng++)
{
if (namelen == ng->length &&
- PRIV(strncmp)(name, ng->name, (size_t)namelen) == 0)
+ PRIV(strncmp)(name, ng->name, (PCRE2_SIZE)namelen) == 0)
{
if (ng->number == cb->bracount) break;
if ((options & PCRE2_DUPNAMES) == 0)
@@ -3766,7 +4152,10 @@ for (; ptr < cb->end_pattern; ptr++)
} /* End of (? switch */
break; /* End of ( handling */
- /* At an alternation, reset the capture count if we are in a (?| group. */
+
+ /* ---- Branch terminators ---- */
+
+ /* 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 &&
@@ -3776,48 +4165,617 @@ for (; ptr < cb->end_pattern; ptr++)
top_nest->max_group = (uint16_t)cb->bracount;
cb->bracount = top_nest->reset_group;
}
+ *parsed_pattern++ = META_ALT;
break;
- /* At a right parenthesis, reset the capture count to the maximum if we
- are in a (?| group and/or reset the extended option. */
+ /* End of group; reset the capture count to the maximum if we are in a (?|
+ group and/or reset the options that are tracked during parsing. Disallow
+ quantifier for a condition that is an assertion. */
case CHAR_RIGHT_PARENTHESIS:
+ okquantifier = TRUE;
if (top_nest != NULL && top_nest->nest_depth == nest_depth)
{
+ options = (options & ~PARSE_TRACKED_OPTIONS) | top_nest->options;
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->flags & NSF_CONDASSERT) != 0)
+ okquantifier = FALSE;
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;
+ goto FAILED_BACK;
}
nest_depth--;
+ *parsed_pattern++ = META_KET;
break;
- }
+ } /* End of switch on pattern character */
+ } /* End of main character scan loop */
+
+/* End of pattern reached. Check for missing ) at the end of a verb name. */
+
+if (inverbname && ptr >= ptrend)
+ {
+ errorcode = ERR60;
+ goto FAILED;
+ }
+
+/* Manage callout for the final item */
+
+PARSED_END:
+parsed_pattern = manage_callouts(ptr, &previous_callout, auto_callout,
+ parsed_pattern, cb);
+
+/* Insert trailing items for word and line matching (features provided for the
+benefit of pcre2grep). */
+
+if ((cb->cx->extra_options & PCRE2_EXTRA_MATCH_LINE) != 0)
+ {
+ *parsed_pattern++ = META_KET;
+ *parsed_pattern++ = META_DOLLAR;
+ }
+else if ((cb->cx->extra_options & PCRE2_EXTRA_MATCH_WORD) != 0)
+ {
+ *parsed_pattern++ = META_KET;
+ *parsed_pattern++ = META_ESCAPE + ESC_b;
}
-if (nest_depth == 0)
+/* Terminate the parsed pattern, then return success if all groups are closed.
+Otherwise we have unclosed parentheses. */
+
+if (parsed_pattern >= parsed_pattern_end)
{
- cb->final_bracount = cb->bracount;
- return 0;
+ errorcode = ERR63; /* Internal error (parsed pattern overflow) */
+ goto FAILED;
}
-/* We give a special error for a missing closing parentheses after (?# because
-it might otherwise be hard to see where the missing character is. */
+*parsed_pattern = META_END;
+if (nest_depth == 0) return 0;
-errorcode = (skiptoket == CHAR_NUMBER_SIGN)? ERR18 : ERR14;
+UNCLOSED_PARENTHESIS:
+errorcode = ERR14;
+
+/* Come here for all failures. */
FAILED:
-*ptrptr = ptr;
+cb->erroroffset = (PCRE2_SIZE)(ptr - cb->start_pattern);
return errorcode;
+
+/* Some errors need to indicate the previous character. */
+
+FAILED_BACK:
+ptr--;
+goto FAILED;
+
+/* This failure happens several times. */
+
+BAD_VERSION_CONDITION:
+errorcode = ERR79;
+goto FAILED;
+}
+
+
+
+/*************************************************
+* Find first significant op code *
+*************************************************/
+
+/* This is called by several functions that scan a compiled expression looking
+for a fixed first character, or an anchoring op code etc. It skips over things
+that do not influence this. For some calls, it makes sense to skip negative
+forward and all backward assertions, and also the \b assertion; for others it
+does not.
+
+Arguments:
+ code pointer to the start of the group
+ skipassert TRUE if certain assertions are to be skipped
+
+Returns: pointer to the first significant opcode
+*/
+
+static const PCRE2_UCHAR*
+first_significant_code(PCRE2_SPTR code, BOOL skipassert)
+{
+for (;;)
+ {
+ switch ((int)*code)
+ {
+ case OP_ASSERT_NOT:
+ case OP_ASSERTBACK:
+ case OP_ASSERTBACK_NOT:
+ if (!skipassert) return code;
+ do code += GET(code, 1); while (*code == OP_ALT);
+ code += PRIV(OP_lengths)[*code];
+ break;
+
+ case OP_WORD_BOUNDARY:
+ case OP_NOT_WORD_BOUNDARY:
+ if (!skipassert) return code;
+ /* Fall through */
+
+ case OP_CALLOUT:
+ case OP_CREF:
+ case OP_DNCREF:
+ case OP_RREF:
+ case OP_DNRREF:
+ case OP_FALSE:
+ case OP_TRUE:
+ code += PRIV(OP_lengths)[*code];
+ break;
+
+ case OP_CALLOUT_STR:
+ code += GET(code, 1 + 2*LINK_SIZE);
+ break;
+
+ case OP_SKIPZERO:
+ code += 2 + GET(code, 2) + LINK_SIZE;
+ break;
+
+ case OP_COND:
+ case OP_SCOND:
+ if (code[1+LINK_SIZE] != OP_FALSE || /* Not DEFINE */
+ code[GET(code, 1)] != OP_KET) /* More than one branch */
+ return code;
+ code += GET(code, 1) + 1 + LINK_SIZE;
+ break;
+
+ default:
+ return code;
+ }
+ }
+/* Control never reaches here */
+}
+
+
+
+#ifdef SUPPORT_UNICODE
+/*************************************************
+* Get othercase range *
+*************************************************/
+
+/* This function is passed the start and end of a class range in UCP 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
+ d end value
+ ocptr where to put start of othercase range
+ odptr where to put end of othercase range
+
+Yield: -1 when no more
+ 0 when a range is returned
+ >0 the CASESET offset for char with multiple other cases
+ in this case, ocptr contains the original
+*/
+
+static int
+get_othercase_range(uint32_t *cptr, uint32_t d, uint32_t *ocptr,
+ uint32_t *odptr)
+{
+uint32_t c, othercase, next;
+unsigned int co;
+
+/* Find the first character that has an other case. If it has multiple other
+cases, return its case offset value. */
+
+for (c = *cptr; c <= d; c++)
+ {
+ if ((co = UCD_CASESET(c)) != 0)
+ {
+ *ocptr = c++; /* Character that has the set */
+ *cptr = c; /* Rest of input range */
+ return (int)co;
+ }
+ if ((othercase = UCD_OTHERCASE(c)) != c) break;
+ }
+
+if (c > d) return -1; /* Reached end of range */
+
+/* Found a character that has a single other case. Search for the end of the
+range, which is either the end of the input range, or a character that has zero
+or more than one other cases. */
+
+*ocptr = othercase;
+next = othercase + 1;
+
+for (++c; c <= d; c++)
+ {
+ if ((co = UCD_CASESET(c)) != 0 || UCD_OTHERCASE(c) != next) break;
+ next++;
+ }
+
+*odptr = next - 1; /* End of othercase range */
+*cptr = c; /* Rest of input range */
+return 0;
+}
+#endif /* SUPPORT_UNICODE */
+
+
+
+/*************************************************
+* Add a character or range to a class (internal) *
+*************************************************/
+
+/* This function packages up the logic of adding a character or range of
+characters to a class. The character values in the arguments will be within the
+valid values for the current mode (8-bit, 16-bit, UTF, etc). This function is
+called only from within the "add to class" group of functions, some of which
+are recursive and mutually recursive. The external entry point is
+add_to_class().
+
+Arguments:
+ classbits the bit map for characters < 256
+ uchardptr points to the pointer for extra data
+ options the options word
+ cb compile data
+ start start of range character
+ end end of range character
+
+Returns: the number of < 256 characters added
+ the pointer to extra data is updated
+*/
+
+static unsigned int
+add_to_class_internal(uint8_t *classbits, PCRE2_UCHAR **uchardptr,
+ uint32_t options, compile_block *cb, uint32_t start, uint32_t end)
+{
+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 & PCRE2_CASELESS) != 0)
+ {
+#ifdef SUPPORT_UNICODE
+ if ((options & PCRE2_UTF) != 0)
+ {
+ int rc;
+ uint32_t oc, od;
+
+ 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_internal(classbits, uchardptr, options, cb,
+ PRIV(ucd_caseless_sets) + rc, oc);
+
+ /* Do nothing if the other case range is within the original range. */
+
+ else if (oc >= cb->class_range_start && od <= cb->class_range_end) continue;
+
+ /* Extend the original range if there is overlap, noting that if oc < c, we
+ can't have od > end because a subrange is always shorter than the basic
+ range. Otherwise, use a recursive call to add the additional range. */
+
+ else if (oc < start && od >= start - 1) start = oc; /* Extend downwards */
+ else if (od > end && oc <= end + 1)
+ {
+ end = od; /* Extend upwards */
+ if (end > classbits_end) classbits_end = (end <= 0xff ? end : 0xff);
+ }
+ else n8 += add_to_class_internal(classbits, uchardptr, options, cb, oc, od);
+ }
+ }
+ else
+#endif /* SUPPORT_UNICODE */
+
+ /* Not UTF mode */
+
+ for (c = start; c <= classbits_end; c++)
+ {
+ SETBIT(classbits, cb->fcc[c]);
+ n8++;
+ }
+ }
+
+/* Now handle the originally supplied range. Adjust the final value according
+to the bit length - this means that the same lists of (e.g.) horizontal spaces
+can be used in all cases. */
+
+if ((options & PCRE2_UTF) == 0 && end > MAX_NON_UTF_CHAR)
+ end = MAX_NON_UTF_CHAR;
+
+if (start > cb->class_range_start && end < cb->class_range_end) return n8;
+
+/* Use the bitmap for characters < 256. Otherwise use extra data.*/
+
+for (c = start; c <= classbits_end; c++)
+ {
+ /* Regardless of start, c will always be <= 255. */
+ SETBIT(classbits, c);
+ n8++;
+ }
+
+#ifdef SUPPORT_WIDE_CHARS
+if (start <= 0xff) start = 0xff + 1;
+
+if (end >= start)
+ {
+ PCRE2_UCHAR *uchardata = *uchardptr;
+
+#ifdef SUPPORT_UNICODE
+ if ((options & PCRE2_UTF) != 0)
+ {
+ if (start < end)
+ {
+ *uchardata++ = XCL_RANGE;
+ uchardata += PRIV(ord2utf)(start, uchardata);
+ uchardata += PRIV(ord2utf)(end, uchardata);
+ }
+ else if (start == end)
+ {
+ *uchardata++ = XCL_SINGLE;
+ uchardata += PRIV(ord2utf)(start, uchardata);
+ }
+ }
+ else
+#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. */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ {}
+#else
+ if (start < end)
+ {
+ *uchardata++ = XCL_RANGE;
+ *uchardata++ = start;
+ *uchardata++ = end;
+ }
+ else if (start == end)
+ {
+ *uchardata++ = XCL_SINGLE;
+ *uchardata++ = start;
+ }
+#endif /* PCRE2_CODE_UNIT_WIDTH == 8 */
+ *uchardptr = uchardata; /* Updata extra data pointer */
+ }
+#else /* SUPPORT_WIDE_CHARS */
+ (void)uchardptr; /* Avoid compiler warning */
+#endif /* SUPPORT_WIDE_CHARS */
+
+return n8; /* Number of 8-bit characters */
+}
+
+
+
+#ifdef SUPPORT_UNICODE
+/*************************************************
+* Add a list of characters to a class (internal) *
+*************************************************/
+
+/* This function is used for adding a list of case-equivalent characters to a
+class when in UTF mode. This function is called only from within
+add_to_class_internal(), with which it is mutually recursive.
+
+Arguments:
+ classbits the bit map for characters < 256
+ uchardptr points to the pointer for extra data
+ options the options word
+ 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
+ already know about
+
+Returns: the number of < 256 characters added
+ the pointer to extra data is updated
+*/
+
+static unsigned int
+add_list_to_class_internal(uint8_t *classbits, PCRE2_UCHAR **uchardptr,
+ uint32_t options, compile_block *cb, const uint32_t *p, unsigned int except)
+{
+unsigned int n8 = 0;
+while (p[0] < NOTACHAR)
+ {
+ unsigned int n = 0;
+ if (p[0] != except)
+ {
+ while(p[n+1] == p[0] + n + 1) n++;
+ n8 += add_to_class_internal(classbits, uchardptr, options, cb, p[0], p[n]);
+ }
+ p += n + 1;
+ }
+return n8;
+}
+#endif
+
+
+
+/*************************************************
+* External entry point for add range to class *
+*************************************************/
+
+/* This function sets the overall range so that the internal functions can try
+to avoid duplication when handling case-independence.
+
+Arguments:
+ classbits the bit map for characters < 256
+ uchardptr points to the pointer for extra data
+ options the options word
+ cb compile data
+ start start of range character
+ end end of range character
+
+Returns: the number of < 256 characters added
+ the pointer to extra data is updated
+*/
+
+static unsigned int
+add_to_class(uint8_t *classbits, PCRE2_UCHAR **uchardptr, uint32_t options,
+ compile_block *cb, uint32_t start, uint32_t end)
+{
+cb->class_range_start = start;
+cb->class_range_end = end;
+return add_to_class_internal(classbits, uchardptr, options, cb, start, end);
+}
+
+
+/*************************************************
+* External entry point for add list to class *
+*************************************************/
+
+/* This function is used for adding a list of horizontal or vertical whitespace
+characters to a class. The list must be in order so that ranges of characters
+can be detected and handled appropriately. This function sets the overall range
+so that the internal functions can try to avoid duplication when handling
+case-independence.
+
+Arguments:
+ classbits the bit map for characters < 256
+ uchardptr points to the pointer for extra data
+ options the options word
+ 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
+ already know about
+
+Returns: the number of < 256 characters added
+ the pointer to extra data is updated
+*/
+
+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)
+{
+unsigned int n8 = 0;
+while (p[0] < NOTACHAR)
+ {
+ unsigned int n = 0;
+ if (p[0] != except)
+ {
+ while(p[n+1] == p[0] + n + 1) n++;
+ cb->class_range_start = p[0];
+ cb->class_range_end = p[n];
+ n8 += add_to_class_internal(classbits, uchardptr, options, cb, p[0], p[n]);
+ }
+ p += n + 1;
+ }
+return n8;
+}
+
+
+
+/*************************************************
+* Add characters not in a list to a class *
+*************************************************/
+
+/* This function is used for adding the complement of a list of horizontal or
+vertical whitespace to a class. The list must be in order.
+
+Arguments:
+ classbits the bit map for characters < 256
+ uchardptr points to the pointer for extra data
+ options the options word
+ 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 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 & PCRE2_UTF) != 0;
+unsigned int n8 = 0;
+if (p[0] > 0)
+ 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, cb, p[0] + 1,
+ (p[1] == NOTACHAR) ? (utf ? 0x10ffffu : 0xffffffffu) : p[1] - 1);
+ p++;
+ }
+return n8;
+}
+
+
+
+/*************************************************
+* Find details of duplicate group names *
+*************************************************/
+
+/* This is called from compile_branch() when it needs to know the index and
+count of duplicates in the names table when processing named backreferences,
+either directly, or as conditions.
+
+Arguments:
+ name points to the name
+ length the length of the name
+ indexptr where to put the index
+ countptr where to put the count of duplicates
+ errorcodeptr where to put an error code
+ cb the compile block
+
+Returns: TRUE if OK, FALSE if not, error code set
+*/
+
+static BOOL
+find_dupname_details(PCRE2_SPTR name, uint32_t length, int *indexptr,
+ int *countptr, int *errorcodeptr, compile_block *cb)
+{
+uint32_t i, groupnumber;
+int count;
+PCRE2_UCHAR *slot = cb->name_table;
+
+/* Find the first entry in the table */
+
+for (i = 0; i < cb->names_found; i++)
+ {
+ if (PRIV(strncmp)(name, slot+IMM2_SIZE, length) == 0 &&
+ slot[IMM2_SIZE+length] == 0) break;
+ slot += cb->name_entry_size;
+ }
+
+/* This should not occur, because this function is called only when we know we
+have duplicate names. Give an internal error. */
+
+if (i >= cb->names_found)
+ {
+ *errorcodeptr = ERR53;
+ cb->erroroffset = name - cb->start_pattern;
+ return FALSE;
+ }
+
+/* Record the index and then see how many duplicates there are, updating the
+backref map and maximum back reference as we do. */
+
+*indexptr = i;
+count = 0;
+
+for (;;)
+ {
+ count++;
+ groupnumber = GET2(slot,0);
+ cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;
+ if (groupnumber > cb->top_backref) cb->top_backref = groupnumber;
+ if (++i >= cb->names_found) break;
+ slot += cb->name_entry_size;
+ if (PRIV(strncmp)(name, slot+IMM2_SIZE, length) != 0 ||
+ (slot+IMM2_SIZE)[length] != 0) break;
+ }
+
+*countptr = count;
+return TRUE;
}
@@ -3826,63 +4784,64 @@ return errorcode;
* Compile one branch *
*************************************************/
-/* Scan the pattern, compiling it into the a vector. If the options are
-changed during the branch, the pointer is used to change the external options
-bits. This function is used during the pre-compile phase when we are trying
-to find out the amount of memory needed, as well as during the real compile
-phase. The value of lengthptr distinguishes the two phases.
+/* Scan the parsed pattern, compiling it into the a vector of PCRE2_UCHAR. If
+the options are changed during the branch, the pointer is used to change the
+external options bits. This function is used during the pre-compile phase when
+we are trying to find out the amount of memory needed, as well as during the
+real compile phase. The value of lengthptr distinguishes the two phases.
Arguments:
optionsptr pointer to the option bits
codeptr points to the pointer to the current code point
- ptrptr points to the current pattern pointer
+ pptrptr points to the current parsed pattern pointer
errorcodeptr points to error code variable
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
cb contains pointers to tables etc.
lengthptr NULL during the real compile phase
points to length accumulator during pre-compile phase
-Returns: TRUE on success
- FALSE, with *errorcodeptr set non-zero on error
+Returns: 0 There's been an error, *errorcodeptr is non-zero
+ +1 Success, this branch must match at least one character
+ -1 Success, this branch may match an empty string
*/
-static BOOL
-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_block *cb, size_t *lengthptr)
+static int
+compile_branch(uint32_t *optionsptr, PCRE2_UCHAR **codeptr, uint32_t **pptrptr,
+ int *errorcodeptr, uint32_t *firstcuptr, int32_t *firstcuflagsptr,
+ uint32_t *reqcuptr, int32_t *reqcuflagsptr, branch_chain *bcptr,
+ compile_block *cb, PCRE2_SIZE *lengthptr)
{
-int repeat_min = 0, repeat_max = 0; /* To please picky compilers */
int bravalue = 0;
+int okreturn = -1;
+int group_return = 0;
+uint32_t repeat_min = 0, repeat_max = 0; /* To please picky compilers */
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;
+uint32_t escape;
+uint32_t *pptr = *pptrptr;
+uint32_t meta, meta_arg;
+int32_t firstcuflags, reqcuflags;
int32_t zeroreqcuflags, zerofirstcuflags;
int32_t req_caseopt, reqvary, tempreqvary;
-int after_manual_callout = 0;
-int escape;
-size_t length_prevgroup = 0;
-register uint32_t c;
-register PCRE2_UCHAR *code = *codeptr;
+PCRE2_SIZE offset = 0;
+PCRE2_SIZE length_prevgroup = 0;
+PCRE2_UCHAR *code = *codeptr;
PCRE2_UCHAR *last_code = code;
PCRE2_UCHAR *orig_code = code;
PCRE2_UCHAR *tempcode;
-BOOL inescq = FALSE;
-BOOL groupsetfirstcu = FALSE;
-PCRE2_SPTR ptr = *ptrptr;
-PCRE2_SPTR tempptr;
PCRE2_UCHAR *previous = NULL;
-PCRE2_UCHAR *previous_callout = NULL;
+PCRE2_UCHAR op_previous;
+BOOL groupsetfirstcu = FALSE;
+BOOL matched_char = FALSE;
+BOOL previous_matched_char = FALSE;
+const uint8_t *cbits = cb->cbits;
uint8_t classbits[32];
/* We can fish out the UTF setting once and for all into a BOOL, but we must
@@ -3891,10 +4850,6 @@ dynamically as we process the pattern. */
#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 /* No UTF support */
BOOL utf = FALSE;
#endif
@@ -3935,57 +4890,36 @@ to record the case status of the value. This is used only for ASCII characters.
req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS:0;
-/* Switch on next character until the end of the branch */
+/* Switch on next META item until the end of the branch */
-for (;; ptr++)
+for (;; pptr++)
{
+#ifdef SUPPORT_WIDE_CHARS
+ BOOL xclass_has_prop;
+#endif
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;
+ BOOL note_group_empty;
int class_has_8bitchar;
- int class_one_char;
-#ifdef SUPPORT_WIDE_CHARS
- BOOL xclass_has_prop;
-#endif
- int recno; /* Must be signed */
- int refsign; /* Must be signed */
- int terminator; /* Must be signed */
- unsigned int mclength;
- unsigned int tempbracount;
- uint32_t ec;
- uint32_t newoptions;
+ int i;
+ uint32_t mclength;
uint32_t skipunits;
uint32_t subreqcu, subfirstcu;
+ uint32_t groupnumber;
+ uint32_t verbarglen, verbculen;
int32_t subreqcuflags, subfirstcuflags; /* Must be signed */
+ open_capitem *oc;
PCRE2_UCHAR mcbuffer[8];
- /* Come here to restart the loop. */
-
- REDO_LOOP:
-
- /* Get next character in the pattern */
+ /* Get next META item in the pattern and its potential argument. */
- c = *ptr;
-
- /* If we are at the end of a nested substitution, revert to the outer level
- string. Nesting only happens one or two levels deep, and the inserted string
- is always zero terminated. */
-
- if (c == CHAR_NULL && cb->nestptr[0] != NULL)
- {
- ptr = cb->nestptr[0];
- cb->nestptr[0] = cb->nestptr[1];
- cb->nestptr[1] = NULL;
- c = *ptr;
- }
+ meta = META_CODE(*pptr);
+ meta_arg = META_DATA(*pptr);
/* If we are in the pre-compile phase, accumulate the length used for the
- previous cycle of this loop. */
+ previous cycle of this loop, unless the next item is a quantifier. */
if (lengthptr != NULL)
{
@@ -3994,202 +4928,81 @@ for (;; ptr++)
{
*errorcodeptr = (code >= cb->start_workspace + cb->workspace_size)?
ERR52 : ERR86;
- goto FAILED;
+ return 0;
}
/* There is at least one situation where code goes backwards: this is the
- case of a zero quantifier after a class (e.g. [ab]{0}). At compile time,
- the class is simply eliminated. However, it is created first, so we have to
- allow memory for it. Therefore, don't ever reduce the length at this point.
- */
+ case of a zero quantifier after a class (e.g. [ab]{0}). When the quantifier
+ is processed, the whole class is eliminated. However, it is created first,
+ so we have to allow memory for it. Therefore, don't ever reduce the length
+ at this point. */
if (code < last_code) code = last_code;
- /* Paranoid check for integer overflow */
-
- if (OFLOW_MAX - *lengthptr < (size_t)(code - last_code))
- {
- *errorcodeptr = ERR20;
- goto FAILED;
- }
- *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,
- if "previous" is NULL, reset the current code pointer to the start. */
+ /* If the next thing is not a quantifier, we add the length of the previous
+ item into the total, and reset the code pointer to the start of the
+ workspace. Otherwise leave the previous item available to be quantified. */
- if (previous != NULL)
- {
- if (previous > orig_code)
- {
- memmove(orig_code, previous, (size_t)CU2BYTES(code - previous));
- code -= previous - orig_code;
- previous = orig_code;
- }
- }
- else code = orig_code;
-
- /* Remember where this code item starts so we can pick up the length
- next time round. */
-
- last_code = code;
- }
-
- /* 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 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 || ptr < cb->end_pattern)
- {
- if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E)
- {
- inescq = FALSE;
- ptr++;
- continue;
- }
- else if (inescq) /* Literal character */
+ if (meta < META_ASTERISK || meta > META_MINMAX_QUERY)
{
- if (previous_callout != NULL)
+ if (OFLOW_MAX - *lengthptr < (PCRE2_SIZE)(code - orig_code))
{
- if (lengthptr == NULL) /* Don't attempt in pre-compile phase */
- complete_callout(previous_callout, ptr, cb);
- previous_callout = NULL;
+ *errorcodeptr = ERR20; /* Integer overflow */
+ return 0;
}
- if ((options & PCRE2_AUTO_CALLOUT) != 0)
+ *lengthptr += (PCRE2_SIZE)(code - orig_code);
+ if (*lengthptr > MAX_PATTERN_SIZE)
{
- previous_callout = code;
- code = auto_callout(code, ptr, cb);
+ *errorcodeptr = ERR20; /* Pattern is too large */
+ return 0;
}
- goto NORMAL_CHAR;
+ code = orig_code;
}
- /* Check for the start of a \Q...\E sequence. We must do this here rather
- than later in case it is immediately followed by \E, which turns it into a
- "do nothing" sequence. */
+ /* Remember where this code item starts so we can catch the "backwards"
+ case above next time round. */
- if (c == CHAR_BACKSLASH && ptr[1] == CHAR_Q)
- {
- inescq = TRUE;
- ptr++;
- continue;
- }
- }
-
- /* In extended mode, skip white space and #-comments that end at newline. */
-
- 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) goto REDO_LOOP;
- }
-
- /* Skip over (?# comments. */
-
- if (c == CHAR_LEFT_PARENTHESIS && ptr[1] == CHAR_QUESTION_MARK &&
- ptr[2] == CHAR_NUMBER_SIGN)
- {
- ptr += 3;
- while (ptr < cb->end_pattern && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
- if (*ptr != CHAR_RIGHT_PARENTHESIS)
- {
- *errorcodeptr = ERR18;
- goto FAILED;
- }
- continue;
+ last_code = code;
}
- /* 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));
+ /* Process the next parsed pattern item. If it is not a quantifier, remember
+ where it starts so that it can be quantified when a quantifier follows.
+ Checking for the legality of quantifiers happens in parse_regex(), except for
+ a quantifier after an assertion that is a condition. */
- /* 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 && cb->nestptr[0] == NULL)
+ if (meta < META_ASTERISK || meta > META_MINMAX_QUERY)
{
- 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 & PCRE2_AUTO_CALLOUT) != 0)
- {
- previous_callout = code;
- code = auto_callout(code, ptr, cb);
- }
+ previous = code;
+ if (matched_char) okreturn = 1;
}
- /* Process the next pattern item. */
+ previous_matched_char = matched_char;
+ matched_char = FALSE;
+ note_group_empty = FALSE;
+ skipunits = 0; /* Default value for most subgroups */
- switch(c)
+ switch(meta)
{
/* ===================================================================*/
- /* The branch terminates at string end or | or ) */
-
- case CHAR_NULL:
- if (ptr < cb->end_pattern) goto NORMAL_CHAR; /* Zero data character */
- /* Fall through */
+ /* The branch terminates at pattern end or | or ) */
- case CHAR_VERTICAL_LINE:
- case CHAR_RIGHT_PARENTHESIS:
+ case META_END:
+ case META_ALT:
+ case META_KET:
*firstcuptr = firstcu;
*firstcuflagsptr = firstcuflags;
*reqcuptr = reqcu;
*reqcuflagsptr = reqcuflags;
*codeptr = code;
- *ptrptr = ptr;
- if (lengthptr != NULL)
- {
- if (OFLOW_MAX - *lengthptr < (size_t)(code - last_code))
- {
- *errorcodeptr = ERR20;
- goto FAILED;
- }
- *lengthptr += (size_t)(code - last_code); /* To include callout length */
- }
- return TRUE;
+ *pptrptr = pptr;
+ return okreturn;
/* ===================================================================*/
/* Handle single-character metacharacters. In multiline mode, ^ disables
the setting of any following char as a first character. */
- case CHAR_CIRCUMFLEX_ACCENT:
- previous = NULL;
+ case META_CIRCUMFLEX:
if ((options & PCRE2_MULTILINE) != 0)
{
if (firstcuflags == REQ_UNSET)
@@ -4199,117 +5012,112 @@ for (;; ptr++)
else *code++ = OP_CIRC;
break;
- case CHAR_DOLLAR_SIGN:
- previous = NULL;
+ case META_DOLLAR:
*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 reqcu doesn't change either. */
- case CHAR_DOT:
+ case META_DOT:
+ matched_char = TRUE;
if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
zerofirstcu = firstcu;
zerofirstcuflags = firstcuflags;
zeroreqcu = reqcu;
zeroreqcuflags = reqcuflags;
- previous = code;
*code++ = ((options & PCRE2_DOTALL) != 0)? OP_ALLANY: OP_ANY;
break;
/* ===================================================================*/
- /* Character classes. If the included characters are all < 256, we build a
- 32-byte bitmap of the permitted characters, except in the special case
- where there is only one such character. For negated classes, we build the
- map as usual, then invert it at the end. However, we use a different opcode
- so that data characters > 255 can be handled correctly.
+ /* Empty character classes are allowed if PCRE2_ALLOW_EMPTY_CLASS is set.
+ Otherwise, an initial ']' is taken as a data character. When empty classes
+ are allowed, [] must always fail, so generate OP_FAIL, whereas [^] must
+ match any character, so generate OP_ALLANY. */
+
+ case META_CLASS_EMPTY:
+ case META_CLASS_EMPTY_NOT:
+ matched_char = TRUE;
+ *code++ = (meta == META_CLASS_EMPTY_NOT)? OP_ALLANY : OP_FAIL;
+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
+ zerofirstcu = firstcu;
+ zerofirstcuflags = firstcuflags;
+ break;
+
+
+ /* ===================================================================*/
+ /* Non-empty character class. If the included characters are all < 256, we
+ build a 32-byte bitmap of the permitted characters, except in the special
+ case where there is only one such character. For negated classes, we build
+ the map as usual, then invert it at the end. However, we use a different
+ opcode so that data characters > 255 can be handled correctly.
If the class contains characters outside the 0-255 range, a different
opcode is compiled. It may optionally have a bit map for characters < 256,
- but those above are are explicitly listed afterwards. A flag byte tells
- whether the bitmap is present, and whether this is a negated class or not.
+ but those above are are explicitly listed afterwards. A flag code unit
+ tells whether the bitmap is present, and whether this is a negated class or
+ not. */
- 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 META_CLASS_NOT:
+ case META_CLASS:
+ matched_char = TRUE;
+ negate_class = meta == META_CLASS_NOT;
- 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. 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. */
+ /* We can optimize the case of a single character in a class by generating
+ OP_CHAR or OP_CHARI if it's positive, or OP_NOT or OP_NOTI if it's
+ negative. In the negative case there can be no first char if this item is
+ first, whatever repeat count may follow. In the case of reqcu, save the
+ previous value for reinstating. */
- case CHAR_LEFT_SQUARE_BRACKET:
- if (PRIV(strncmp_c8)(ptr+1, STRING_WEIRD_STARTWORD, 6) == 0)
- {
- cb->nestptr[0] = ptr + 7;
- ptr = sub_start_of_word;
- goto REDO_LOOP;
- }
+ /* NOTE: at present this optimization is not effective if the only
+ character in a class in 32-bit, non-UCP mode has its top bit set. */
- if (PRIV(strncmp_c8)(ptr+1, STRING_WEIRD_ENDWORD, 6) == 0)
+ if (pptr[1] < META_END && pptr[2] == META_CLASS_END)
{
- cb->nestptr[0] = ptr + 7;
- ptr = sub_end_of_word;
- goto REDO_LOOP;
- }
+#ifdef SUPPORT_UNICODE
+ uint32_t d;
+#endif
+ uint32_t c = pptr[1];
- /* Handle a real character class. */
+ pptr += 2; /* Move on to class end */
+ if (meta == META_CLASS) /* A positive one-char class can be */
+ { /* handled as a normal literal character. */
+ meta = c; /* Set up the character */
+ goto NORMAL_CHAR_SET;
+ }
- previous = code;
+ /* Handle a negative one-character class */
- /* PCRE supports POSIX class stuff inside a class. Perl gives an error if
- they are encountered at the top level, so we'll do that too. */
-
- if ((ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
- ptr[1] == CHAR_EQUALS_SIGN) &&
- check_posix_syntax(ptr, &tempptr))
- {
- *errorcodeptr = (ptr[1] == CHAR_COLON)? ERR12 : ERR13;
- goto FAILED;
- }
+ zeroreqcu = reqcu;
+ zeroreqcuflags = reqcuflags;
+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
+ zerofirstcu = firstcu;
+ zerofirstcuflags = firstcuflags;
- /* If the first character is '^', set the negation flag and skip it. Also,
- if the first few characters (either before or after ^) are \Q\E or \E we
- skip them too. This makes for compatibility with Perl. */
+ /* 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. */
- negate_class = FALSE;
- for (;;)
- {
- c = *(++ptr);
- if (c == CHAR_BACKSLASH)
+#ifdef SUPPORT_UNICODE
+ if (utf && (options & PCRE2_CASELESS) != 0 &&
+ (d = UCD_CASESET(c)) != 0)
{
- 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;
+ *code++ = OP_NOTPROP;
+ *code++ = PT_CLIST;
+ *code++ = d;
+ break; /* We are finished with this class */
}
- else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT)
- negate_class = TRUE;
- else break;
- }
+#endif
+ /* Char has only one other case, or UCP not available */
- /* 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. When empty classes are allowed, [] must always fail, so generate
- OP_FAIL, whereas [^] must match any character, so generate OP_ALLANY. */
+ *code++ = ((options & PCRE2_CASELESS) != 0)? OP_NOTI: OP_NOT;
+ code += PUTCHAR(c, code);
+ break; /* We are finished with this class */
+ } /* End of 1-char optimization */
- if (c == CHAR_RIGHT_SQUARE_BRACKET &&
- (cb->external_options & PCRE2_ALLOW_EMPTY_CLASS) != 0)
- {
- *code++ = negate_class? OP_ALLANY : OP_FAIL;
- if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
- zerofirstcu = firstcu;
- zerofirstcuflags = firstcuflags;
- break;
- }
+ /* Handle character classes that contain more than just one literal
+ character. */
/* 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
@@ -4329,13 +5137,11 @@ for (;; ptr++)
#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 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 will be non-zero if the class contains at least one
+ character with a code point less than 256; xclass_has_prop will be TRUE if
+ Unicode property checks are present in the class. */
class_has_8bitchar = 0;
- class_one_char = 0;
#ifdef SUPPORT_WIDE_CHARS
xclass_has_prop = FALSE;
#endif
@@ -4347,156 +5153,77 @@ for (;; ptr++)
memset(classbits, 0, 32 * sizeof(uint8_t));
- /* 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. */
+ /* Process items until META_CLASS_END is reached. */
- for(;;)
+ while ((meta = *(++pptr)) != META_CLASS_END)
{
- PCRE2_SPTR oldptr;
-#ifdef EBCDIC
- BOOL range_is_literal = TRUE;
-#endif
-
- 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
+ /* Handle POSIX classes such as [:alpha:] etc. */
- /* Inside \Q...\E everything is literal except \E */
-
- if (inescq)
+ if (meta == META_POSIX || meta == META_POSIX_NEG)
{
- 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; /* Carry on with next char */
- }
- goto CHECK_RANGE; /* Could be range if \E follows */
- }
-
- /* Handle POSIX class names. Perl allows a negation extension of the
- form [:^name:]. A square bracket that doesn't match the syntax is
- treated as a literal. We also recognize the POSIX constructions
- [.ch.] and [=ch=] ("collating elements") and fault them, as Perl
- 5.6 and 5.8 do. */
-
- if (c == CHAR_LEFT_SQUARE_BRACKET &&
- (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
- ptr[1] == CHAR_EQUALS_SIGN) && check_posix_syntax(ptr, &tempptr))
- {
- BOOL local_negate = FALSE;
- int posix_class, taboffset, tabopt;
- register const uint8_t *cbits = cb->cbits;
+ BOOL local_negate = (meta == META_POSIX_NEG);
+ int posix_class = *(++pptr);
+ int taboffset, tabopt;
uint8_t pbits[32];
- if (ptr[1] != CHAR_COLON)
- {
- *errorcodeptr = ERR13;
- goto FAILED;
- }
+ should_flip_negation = local_negate; /* Note negative special */
- ptr += 2;
- if (*ptr == CHAR_CIRCUMFLEX_ACCENT)
- {
- local_negate = TRUE;
- should_flip_negation = TRUE; /* Note negative special */
- ptr++;
- }
-
- posix_class = check_posix_name(ptr, (int)(tempptr - ptr));
- if (posix_class < 0)
- {
- *errorcodeptr = ERR30;
- goto FAILED;
- }
-
- /* If matching is caseless, upper and lower are converted to
- alpha. This relies on the fact that the class table starts with
- alpha, lower, upper as the first 3 entries. */
+ /* If matching is caseless, upper and lower are converted to alpha.
+ This relies on the fact that the class table starts with alpha,
+ lower, upper as the first 3 entries. */
if ((options & PCRE2_CASELESS) != 0 && posix_class <= 2)
posix_class = 0;
/* 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. UCP support is not available unless UTF support is.*/
+ different escape sequences that use Unicode properties \p or \P.
+ Others that are not available via \p or \P have to generate
+ XCL_PROP/XCL_NOTPROP directly, which is done here. */
#ifdef SUPPORT_UNICODE
- if ((options & PCRE2_UCP) != 0)
+ if ((options & PCRE2_UCP) != 0) switch(posix_class)
{
- 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. 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)
- {
- cb->nestptr[0] = tempptr + 1;
- ptr = posix_substitutes[pc] - 1;
- goto CONTINUE_CLASS;
- }
-
- /* There are three other classes that generate special property calls
- that are recognized only in an XCLASS. */
+ case PC_GRAPH:
+ case PC_PRINT:
+ case PC_PUNCT:
+ *class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP;
+ *class_uchardata++ = (PCRE2_UCHAR)
+ ((posix_class == PC_GRAPH)? PT_PXGRAPH :
+ (posix_class == PC_PRINT)? PT_PXPRINT : PT_PXPUNCT);
+ *class_uchardata++ = 0;
+ xclass_has_prop = TRUE;
+ goto CONTINUE_CLASS;
- else switch(posix_class)
- {
- case PC_GRAPH:
- ptype = PT_PXGRAPH;
- /* Fall through */
- case PC_PRINT:
- if (ptype == 0) ptype = PT_PXPRINT;
- /* Fall through */
- case PC_PUNCT:
- if (ptype == 0) ptype = PT_PXPUNCT;
- *class_uchardata++ = local_negate? XCL_NOTPROP : XCL_PROP;
- *class_uchardata++ = (PCRE2_UCHAR)ptype;
- *class_uchardata++ = 0;
- xclass_has_prop = TRUE;
- ptr = tempptr + 1;
- 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. */
+ /* 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. In the 8-bit library this is relevant only in
+ utf mode, since no wide characters can exist otherwise. */
- default:
- match_all_or_no_wide_chars |= local_negate;
- break;
- }
+ default:
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ if (utf)
+#endif
+ match_all_or_no_wide_chars |= local_negate;
+ break;
}
#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
- may be in the main map already. At the end we or the result into the
- bit map that is being built. */
+ bit map for the POSIX class in a chunk of local store because we may
+ be adding and subtracting from it, and we don't want to subtract bits
+ that may be in the main map already. At the end we or the result into
+ the bit map that is being built. */
posix_class *= 3;
@@ -4513,9 +5240,9 @@ for (;; ptr++)
if (taboffset >= 0)
{
if (tabopt >= 0)
- for (c = 0; c < 32; c++) pbits[c] |= cbits[(int)c + taboffset];
+ for (i = 0; i < 32; i++) pbits[i] |= cbits[(int)i + taboffset];
else
- for (c = 0; c < 32; c++) pbits[c] &= ~cbits[(int)c + taboffset];
+ for (i = 0; i < 32; i++) pbits[i] &= ~cbits[(int)i + taboffset];
}
/* Now see if we need to remove any special characters. An option
@@ -4529,432 +5256,223 @@ for (;; ptr++)
being built and we are done. */
if (local_negate)
- for (c = 0; c < 32; c++) classbits[c] |= ~pbits[c];
+ for (i = 0; i < 32; i++) classbits[i] |= ~pbits[i];
else
- for (c = 0; c < 32; c++) classbits[c] |= pbits[c];
+ for (i = 0; i < 32; i++) classbits[i] |= pbits[i];
- ptr = tempptr + 1;
/* Every class contains at least one < 256 character. */
+
class_has_8bitchar = 1;
- /* Every class contains at least two characters. */
- class_one_char = 2;
- goto CONTINUE_CLASS; /* End of POSIX syntax handling */
+ goto CONTINUE_CLASS; /* End of POSIX handling */
}
- /* Backslash may introduce a single character, or it may introduce one
- of the specials, which just set a flag. The sequence \b is a special
- case. Inside a class (and only there) it is treated as backspace. We
- assume that other escapes have more than one character in them, so
- speculatively set both class_has_8bitchar and class_one_char bigger
- than one. Unrecognized escapes fall through and are faulted. */
+ /* Other than POSIX classes, the only items we should encounter are
+ \d-type escapes and literal characters (possibly as ranges). */
- if (c == CHAR_BACKSLASH)
+ if (meta == META_BIGVALUE)
{
- escape = PRIV(check_escape)(&ptr, cb->end_pattern, &ec, errorcodeptr,
- options, TRUE, cb);
- if (*errorcodeptr != 0) goto FAILED;
- if (escape == 0) /* Escaped single char */
+ meta = *(++pptr);
+ goto CLASS_LITERAL;
+ }
+
+ /* Any other non-literal must be an escape */
+
+ if (meta >= META_END)
+ {
+ if (META_CODE(meta) != META_ESCAPE)
{
- c = ec;
-#ifdef EBCDIC
- range_is_literal = FALSE;
+#ifdef DEBUG_SHOW_PARSED
+ fprintf(stderr, "** Unrecognized parsed pattern item 0x%.8x "
+ "in character class\n", meta);
#endif
+ *errorcodeptr = ERR89; /* Internal error - unrecognized. */
+ return 0;
}
- 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 */
- {
- *errorcodeptr = ERR71;
- goto FAILED;
- }
- else if (escape == ESC_Q) /* Handle start of quoted string */
- {
- if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E)
- {
- ptr += 2; /* avoid empty string */
- }
- else inescq = TRUE;
- goto CONTINUE_CLASS;
- }
- else if (escape == ESC_E) goto CONTINUE_CLASS; /* Ignore orphan \E */
+ escape = META_DATA(meta);
+
+ /* Every class contains at least one < 256 character. */
- else /* Handle \d-type escapes */
+ class_has_8bitchar++;
+
+ switch(escape)
{
- 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. */
- class_one_char += 2;
+ case ESC_d:
+ for (i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_digit];
+ break;
- switch (escape)
- {
-#ifdef SUPPORT_UNICODE
- case ESC_du: /* These are the values given for \d etc */
- 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. 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! */
- break;
-#endif
- case ESC_d:
- for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_digit];
- break;
+ case ESC_D:
+ should_flip_negation = TRUE;
+ for (i = 0; i < 32; i++) classbits[i] |= ~cbits[i+cbit_digit];
+ break;
- case ESC_D:
- should_flip_negation = TRUE;
- for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_digit];
- break;
+ case ESC_w:
+ for (i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_word];
+ break;
- case ESC_w:
- for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_word];
- break;
+ case ESC_W:
+ should_flip_negation = TRUE;
+ for (i = 0; i < 32; i++) classbits[i] |= ~cbits[i+cbit_word];
+ break;
- case ESC_W:
- should_flip_negation = TRUE;
- for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_word];
- 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
+ previously set by something earlier in the character class.
+ Luckily, the value of CHAR_VT is 0x0b in both ASCII and EBCDIC, so
+ we could just adjust the appropriate bit. From PCRE 8.34 we no
+ longer treat \s and \S specially. */
- /* 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
- previously set by something earlier in the character class.
- Luckily, the value of CHAR_VT is 0x0b in both ASCII and EBCDIC, so
- we could just adjust the appropriate bit. From PCRE 8.34 we no
- longer treat \s and \S specially. */
+ case ESC_s:
+ for (i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_space];
+ break;
- case ESC_s:
- for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_space];
- break;
+ case ESC_S:
+ should_flip_negation = TRUE;
+ for (i = 0; i < 32; i++) classbits[i] |= ~cbits[i+cbit_space];
+ break;
- case ESC_S:
- should_flip_negation = TRUE;
- for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_space];
- break;
+ /* When adding the horizontal or vertical space lists to a class, or
+ their complements, disable PCRE2_CASELESS, because it justs wastes
+ time, and in the "not-x" UTF cases can create unwanted duplicates in
+ the XCLASS list (provoked by characters that have more than one other
+ case and by both cases being in the same "not-x" sublist). */
- /* The rest apply in both UCP and non-UCP cases. */
+ case ESC_h:
+ (void)add_list_to_class(classbits, &class_uchardata,
+ options & ~PCRE2_CASELESS, cb, PRIV(hspace_list), NOTACHAR);
+ break;
- case ESC_h:
- (void)add_list_to_class(classbits, &class_uchardata, options, cb,
- PRIV(hspace_list), NOTACHAR);
- break;
+ case ESC_H:
+ (void)add_not_list_to_class(classbits, &class_uchardata,
+ options & ~PCRE2_CASELESS, cb, PRIV(hspace_list));
+ break;
- case ESC_H:
- (void)add_not_list_to_class(classbits, &class_uchardata, options,
- cb, PRIV(hspace_list));
- break;
+ case ESC_v:
+ (void)add_list_to_class(classbits, &class_uchardata,
+ options & ~PCRE2_CASELESS, cb, PRIV(vspace_list), NOTACHAR);
+ break;
- case ESC_v:
- (void)add_list_to_class(classbits, &class_uchardata, options, cb,
- PRIV(vspace_list), NOTACHAR);
- break;
+ case ESC_V:
+ (void)add_not_list_to_class(classbits, &class_uchardata,
+ options & ~PCRE2_CASELESS, cb, PRIV(vspace_list));
+ break;
- case ESC_V:
- (void)add_not_list_to_class(classbits, &class_uchardata, options,
- cb, PRIV(vspace_list));
- break;
+ /* If Unicode is not supported, \P and \p are not allowed and are
+ faulted at parse time, so will never appear here. */
- case ESC_p:
- case ESC_P:
#ifdef SUPPORT_UNICODE
- {
- BOOL negated;
- unsigned int ptype = 0, pdata = 0;
- if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr, cb))
- goto FAILED;
- *class_uchardata++ = ((escape == ESC_p) != negated)?
- XCL_PROP : XCL_NOTPROP;
- *class_uchardata++ = ptype;
- *class_uchardata++ = pdata;
- xclass_has_prop = TRUE;
- class_has_8bitchar--; /* Undo! */
- }
- break;
-#else
- *errorcodeptr = ERR45;
- goto FAILED;
-#endif
- /* Unrecognized escapes are faulted. */
-
- default:
- *errorcodeptr = ERR7;
- goto FAILED;
+ case ESC_p:
+ case ESC_P:
+ {
+ uint32_t ptype = *(++pptr) >> 16;
+ uint32_t pdata = *pptr & 0xffff;
+ *class_uchardata++ = (escape == ESC_p)? XCL_PROP : XCL_NOTPROP;
+ *class_uchardata++ = ptype;
+ *class_uchardata++ = pdata;
+ xclass_has_prop = TRUE;
+ class_has_8bitchar--; /* Undo! */
}
-
- /* Handled \d-type escape */
-
- goto CONTINUE_CLASS;
+ break;
+#endif
}
- /* 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
- not permit ']' to be the end of the range. A '-' character at the end is
- treated as a literal. Perl ignores orphaned \E sequences entirely. The
- code for handling \Q and \E is messy. */
-
- CHECK_RANGE:
- while (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E)
- {
- inescq = FALSE;
- ptr += 2;
- }
- oldptr = ptr;
-
- /* Remember if \r or \n were explicitly used */
-
- if (c == CHAR_CR || c == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF;
+ goto CONTINUE_CLASS;
+ } /* End handling \d-type escapes */
- /* Check for range */
+ /* A literal character may be followed by a range meta. At parse time
+ there are checks for out-of-order characters, for ranges where the two
+ characters are equal, and for hyphens that cannot indicate a range. At
+ this point, therefore, no checking is needed. */
- if (!inescq && ptr[1] == CHAR_MINUS)
+ else
{
- uint32_t d;
- ptr += 2;
- while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E) ptr += 2;
-
- /* If we hit \Q (not followed by \E) at this point, go into escaped
- mode. */
-
- while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_Q)
- {
- ptr += 2;
- if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E)
- { ptr += 2; continue; }
- inescq = TRUE;
- break;
- }
+ uint32_t c, d;
- /* Minus (hyphen) at the end of a class is treated as a literal, so put
- back the pointer and jump to handle the character that preceded it. */
-
- if (*ptr == CHAR_NULL || (!inescq && *ptr == CHAR_RIGHT_SQUARE_BRACKET))
- {
- ptr = oldptr;
- goto CLASS_SINGLE_CHARACTER;
- }
+ CLASS_LITERAL:
+ c = d = meta;
- /* Otherwise, we have a potential range; pick up the next character */
+ /* Remember if \r or \n were explicitly used */
-#ifdef SUPPORT_UNICODE
- if (utf)
- { /* Braces are required because the */
- GETCHARLEN(d, ptr, ptr); /* macro generates multiple statements */
- }
- else
-#endif
- d = *ptr; /* Not UTF mode */
+ if (c == CHAR_CR || c == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF;
- /* 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
- literal in such circumstances. However, in Perl's warning mode, a
- warning is given, so PCRE now faults it as it is almost certainly a
- mistake on the user's part. */
+ /* Process a character range */
- if (!inescq)
+ if (pptr[1] == META_RANGE_LITERAL || pptr[1] == META_RANGE_ESCAPED)
{
- if (d == CHAR_BACKSLASH)
- {
- int descape;
- descape = PRIV(check_escape)(&ptr, cb->end_pattern, &d,
- errorcodeptr, options, TRUE, cb);
- if (*errorcodeptr != 0) goto FAILED;
#ifdef EBCDIC
- range_is_literal = FALSE;
+ BOOL range_is_literal = (pptr[1] == META_RANGE_LITERAL);
#endif
- /* 0 means a character was put into d; \b is backspace; any other
- special causes an error. */
-
- if (descape != 0)
- {
- if (descape == ESC_b) d = CHAR_BS; else
- {
- *errorcodeptr = ERR50;
- goto FAILED;
- }
- }
- }
+ pptr += 2;
+ d = *pptr;
+ if (d == META_BIGVALUE) d = *(++pptr);
- /* A hyphen followed by a POSIX class is treated in the same way. */
+ /* Remember an explicit \r or \n, and add the range to the class. */
- else if (d == CHAR_LEFT_SQUARE_BRACKET &&
- (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT ||
- ptr[1] == CHAR_EQUALS_SIGN) &&
- check_posix_syntax(ptr, &tempptr))
- {
- *errorcodeptr = ERR50;
- goto FAILED;
- }
- }
+ if (d == CHAR_CR || d == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF;
- /* Check that the two values are in the correct order. Optimize
- one-character ranges. */
-
- if (d < c)
- {
- *errorcodeptr = ERR8;
- goto FAILED;
- }
- if (d == c) goto CLASS_SINGLE_CHARACTER; /* A few lines below */
-
- /* We have found a character range, so single character optimizations
- cannot be done anymore. Any value greater than 1 indicates that there
- is more than one character. */
-
- class_one_char = 2;
-
- /* Remember an explicit \r or \n, and add the range to the class. */
-
- if (d == CHAR_CR || d == CHAR_NL) cb->external_flags |= PCRE2_HASCRORLF;
-
- /* 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]. */
+ /* 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;
- }
-
- if (C <= D && C <= CHAR_r)
+ if (range_is_literal &&
+ (cb->ctypes[c] & ctype_letter) != 0 &&
+ (cb->ctypes[d] & ctype_letter) != 0 &&
+ (d <= CHAR_z) == (d <= CHAR_z))
{
- class_has_8bitchar +=
- add_to_class(classbits, &class_uchardata, options, cb, C + uc,
- ((D < CHAR_r)? D : CHAR_r) + uc);
- C = CHAR_s;
- }
+ uint32_t uc = (d <= CHAR_z)? 0 : 64;
+ uint32_t C = d - uc;
+ uint32_t D = d - uc;
- 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
- char, or after \ that introduces a single character or for an apparent
- range that isn't. Only the value 1 matters for class_one_char, so don't
- increase it if it is already 2 or more ... just in case there's a class
- with a zillion characters in it. */
-
- CLASS_SINGLE_CHARACTER:
- if (class_one_char < 2) class_one_char++;
-
- /* 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 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
- reqcu, save the previous value for reinstating. */
-
- if (!inescq &&
-#ifdef SUPPORT_UNICODE
- !xclass_has_prop &&
-#endif
- class_one_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET)
- {
- ptr++;
- zeroreqcu = reqcu;
- zeroreqcuflags = reqcuflags;
-
- if (negate_class)
- {
-#ifdef SUPPORT_UNICODE
- int d;
-#endif
- if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
- zerofirstcu = firstcu;
- zerofirstcuflags = firstcuflags;
+ 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;
+ }
- /* 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. */
+ 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;
+ }
-#ifdef SUPPORT_UNICODE
- if (utf && (options & PCRE2_CASELESS) != 0 &&
- (d = UCD_CASESET(c)) != 0)
- {
- *code++ = OP_NOTPROP;
- *code++ = PT_CLIST;
- *code++ = d;
+ if (C <= D)
+ {
+ class_has_8bitchar +=
+ add_to_class(classbits, &class_uchardata, options, cb, C + uc,
+ D + uc);
+ }
}
else
#endif
- /* Char has only one other case, or UCP not available */
+ /* Not an EBCDIC special range */
- {
- *code++ = ((options & PCRE2_CASELESS) != 0)? OP_NOTI: OP_NOT;
- code += PUTCHAR(c, code);
- }
-
- /* We are finished with this character class */
-
- goto END_CLASS;
- }
+ class_has_8bitchar +=
+ add_to_class(classbits, &class_uchardata, options, cb, c, d);
+ goto CONTINUE_CLASS; /* Go get the next char in the class */
+ } /* End of range handling */
- /* For a single, positive character, get the value into mcbuffer, and
- then we can handle this with the normal one-character code. */
- mclength = PUTCHAR(c, mcbuffer);
- goto ONE_CHAR;
- } /* End of 1-char optimization */
+ /* Handle a single character. */
- /* There is more than one character in the class, or an XCLASS item
- has been generated. Add this character to the class. */
-
- class_has_8bitchar +=
- add_to_class(classbits, &class_uchardata, options, cb, c, c);
+ class_has_8bitchar +=
+ add_to_class(classbits, &class_uchardata, options, cb, meta, meta);
+ }
- /* 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). */
+ /* Continue to the next item in the class. */
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);
- }
#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 any wide characters or Unicode properties have been encountered,
+ set xclass = TRUE. Then, in the pre-compile phase, accumulate the length
+ of the extra data and reset the pointer. This is so that very large
+ classes that contain a zillion wide characters or Unicode property tests
+ do not overwrite the work space (which is on the stack). */
if (class_uchardata > class_uchardata_base)
{
@@ -4966,13 +5484,12 @@ for (;; ptr++)
}
}
#endif
- /* An unescaped ] ends the class */
- if (c == CHAR_RIGHT_SQUARE_BRACKET && !inescq) break;
+ continue; /* Needed to avoid error when not supporting wide chars */
} /* 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 reqcu setting must remain
+ /* If this class is the first thing in the branch, there can be no first
+ char setting, whatever the repeat count. Any reqcu setting must remain
unchanged after any kind of repeat. */
if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
@@ -4993,23 +5510,46 @@ for (;; ptr++)
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.
+ This applies only in UTF and 16-bit and 32-bit non-UTF modes, since there
+ cannot be any wide characters in 8-bit non-UTF mode.
+
+ When there *are* properties in a positive UTF-8 or any 16-bit or 32_bit
+ class where \S etc is present without PCRE2_UCP, causing an extended class
+ to be compiled, we make sure that all characters > 255 are included by
+ forcing match_all_or_no_wide_chars to be true.
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_WIDE_CHARS /* Defined for 16/32 bits, or 8-bit with Unicode */
+ if (xclass && (
#ifdef SUPPORT_UNICODE
- if (xclass && (xclass_has_prop || !should_flip_negation ||
- (options & PCRE2_UCP) != 0))
-#elif PCRE2_CODE_UNIT_WIDTH != 8
- if (xclass && (xclass_has_prop || !should_flip_negation))
+ (options & PCRE2_UCP) != 0 ||
#endif
+ xclass_has_prop || !should_flip_negation))
{
- if (match_all_or_no_wide_chars)
+ if (match_all_or_no_wide_chars || (
+#if PCRE2_CODE_UNIT_WIDTH == 8
+ utf &&
+#endif
+ should_flip_negation && !negate_class && (options & PCRE2_UCP) == 0))
{
*class_uchardata++ = XCL_RANGE;
- class_uchardata += PRIV(ord2utf)(0x100, class_uchardata);
- class_uchardata += PRIV(ord2utf)(MAX_UTF_CODE_POINT, class_uchardata);
+ if (utf) /* Will always be utf in the 8-bit library */
+ {
+ class_uchardata += PRIV(ord2utf)(0x100, class_uchardata);
+ class_uchardata += PRIV(ord2utf)(MAX_UTF_CODE_POINT, class_uchardata);
+ }
+ else /* Can only happen for the 16-bit & 32-bit libraries */
+ {
+#if PCRE2_CODE_UNIT_WIDTH == 16
+ *class_uchardata++ = 0x100;
+ *class_uchardata++ = 0xffffu;
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+ *class_uchardata++ = 0x100;
+ *class_uchardata++ = 0xffffffffu;
+#endif
+ }
}
*class_uchardata++ = XCL_END; /* Marks the end of extra data */
*code++ = OP_XCLASS;
@@ -5026,7 +5566,7 @@ for (;; ptr++)
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];
+ for (i = 0; i < 32; i++) classbits[i] = ~classbits[i];
memcpy(code, classbits, 32);
code = class_uchardata + (32 / sizeof(PCRE2_UCHAR));
}
@@ -5037,7 +5577,7 @@ for (;; ptr++)
PUT(previous, 1, (int)(code - previous));
break; /* End of class handling */
}
-#endif
+#endif /* SUPPORT_WIDE_CHARS */
/* If there are no characters > 255, or they are all to be included or
excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the
@@ -5049,2421 +5589,1705 @@ for (;; ptr++)
if (lengthptr == NULL) /* Save time in the pre-compile phase */
{
if (negate_class)
- for (c = 0; c < 32; c++) classbits[c] = ~classbits[c];
+ for (i = 0; i < 32; i++) classbits[i] = ~classbits[i];
memcpy(code, classbits, 32);
}
code += 32 / sizeof(PCRE2_UCHAR);
-
- END_CLASS:
- break;
+ break; /* End of class processing */
/* ===================================================================*/
- /* Various kinds of repeat; '{' is not necessarily a quantifier, but this
- has been tested above. */
+ /* Deal with (*VERB)s. */
- case CHAR_LEFT_CURLY_BRACKET:
- if (!is_quantifier) goto NORMAL_CHAR;
- ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorcodeptr);
- if (*errorcodeptr != 0) goto FAILED;
- goto REPEAT;
-
- case CHAR_ASTERISK:
- repeat_min = 0;
- repeat_max = -1;
- goto REPEAT;
+ /* Check for open captures before ACCEPT and convert it to ASSERT_ACCEPT if
+ in an assertion. In the first pass, just accumulate the length required;
+ otherwise hitting (*ACCEPT) inside many nested parentheses can cause
+ workspace overflow. Do not set firstcu after *ACCEPT. */
- case CHAR_PLUS:
- repeat_min = 1;
- repeat_max = -1;
- goto REPEAT;
-
- case CHAR_QUESTION_MARK:
- repeat_min = 0;
- repeat_max = 1;
-
- REPEAT:
- if (previous == NULL)
+ case META_ACCEPT:
+ cb->had_accept = TRUE;
+ for (oc = cb->open_caps; oc != NULL; oc = oc->next)
{
- *errorcodeptr = ERR9;
- goto FAILED;
- }
-
- if (repeat_min == 0)
- {
- firstcu = zerofirstcu; /* Adjust for zero repeat */
- firstcuflags = zerofirstcuflags;
- reqcu = zeroreqcu; /* Ditto */
- reqcuflags = zeroreqcuflags;
+ if (lengthptr != NULL)
+ {
+ *lengthptr += CU2BYTES(1) + IMM2_SIZE;
+ }
+ else
+ {
+ *code++ = OP_CLOSE;
+ PUT2INC(code, 0, oc->number);
+ }
}
+ *code++ = (cb->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT;
+ if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
+ break;
- /* Remember whether this is a variable length repeat */
-
- reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY;
-
- op_type = 0; /* Default single-char op codes */
- possessive_quantifier = FALSE; /* Default not possessive quantifier */
+ case META_PRUNE:
+ case META_SKIP:
+ cb->had_pruneorskip = TRUE;
+ /* Fall through */
+ case META_COMMIT:
+ case META_FAIL:
+ *code++ = verbops[(meta - META_MARK) >> 16];
+ break;
- /* Save start of previous item, in case we have to move it up in order to
- insert something before it. */
+ case META_THEN:
+ cb->external_flags |= PCRE2_HASTHEN;
+ *code++ = OP_THEN;
+ break;
- tempcode = previous;
+ /* Handle verbs with arguments. Arguments can be very long, especially in
+ 16- and 32-bit modes, and can overflow the workspace in the first pass.
+ However, the argument length is constrained to be small enough to fit in
+ one code unit. This check happens in parse_regex(). In the first pass,
+ instead of putting the argument into memory, we just update the length
+ counter and set up an empty argument. */
- /* Before checking for a possessive quantifier, we must skip over
- whitespace and comments in extended mode because Perl allows white space at
- this point. */
+ case META_THEN_ARG:
+ cb->external_flags |= PCRE2_HASTHEN;
+ goto VERB_ARG;
- if ((options & PCRE2_EXTENDED) != 0)
+ case META_PRUNE_ARG:
+ case META_SKIP_ARG:
+ cb->had_pruneorskip = TRUE;
+ /* Fall through */
+ case META_MARK:
+ VERB_ARG:
+ *code++ = verbops[(meta - META_MARK) >> 16];
+ /* The length is in characters. */
+ verbarglen = *(++pptr);
+ verbculen = 0;
+ tempcode = code++;
+ for (i = 0; i < (int)verbarglen; i++)
{
- ptr++;
- for (;;)
- {
- 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(ptr)) /* For non-fixed-length newline cases, */
- { /* IS_NEWLINE sets cb->nllen. */
- ptr += cb->nllen;
- break;
- }
- ptr++;
+ meta = *(++pptr);
#ifdef SUPPORT_UNICODE
- if (utf) FORWARDCHAR(ptr);
+ if (utf) mclength = PRIV(ord2utf)(meta, mcbuffer); else
#endif
- } /* Loop for comment characters */
- } /* Loop for multiple comments */
- ptr--; /* Last code unit of previous character. */
+ {
+ mclength = 1;
+ mcbuffer[0] = meta;
+ }
+ if (lengthptr != NULL) *lengthptr += mclength; else
+ {
+ memcpy(code, mcbuffer, CU2BYTES(mclength));
+ code += mclength;
+ verbculen += mclength;
+ }
}
- /* If the next character is '+', we have a possessive quantifier. This
- implies greediness, whatever the setting of the PCRE2_UNGREEDY option.
- If the next character is '?' this is a minimizing repeat, by default,
- 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)
- {
- repeat_type = 0; /* Force greedy */
- possessive_quantifier = TRUE;
- ptr++;
- }
- else if (ptr[1] == CHAR_QUESTION_MARK)
- {
- repeat_type = greedy_non_default;
- ptr++;
- }
- else repeat_type = greedy_default;
+ *tempcode = verbculen; /* Fill in the code unit length */
+ *code++ = 0; /* Terminating zero */
+ break;
- /* If the repeat is {1} we can ignore it. */
- if (repeat_max == 1 && repeat_min == 1) goto END_REPEAT;
+ /* ===================================================================*/
+ /* Handle options change. The new setting must be passed back for use in
+ subsequent branches. Reset the greedy defaults and the case value for
+ firstcu and reqcu. */
+
+ case META_OPTIONS:
+ *optionsptr = options = *(++pptr);
+ greedy_default = ((options & PCRE2_UNGREEDY) != 0);
+ greedy_non_default = greedy_default ^ 1;
+ req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS : 0;
+ break;
- /* If previous was a recursion call, wrap it in atomic brackets so that
- previous becomes the atomic group. All recursions were so wrapped in the
- past, but it no longer happens for non-repeated recursions. In fact, the
- repeated ones could be re-implemented independently so as not to need this,
- but for the moment we rely on the code for repeating groups. */
- if (*previous == OP_RECURSE)
+ /* ===================================================================*/
+ /* Handle conditional subpatterns. The case of (?(Rdigits) is ambiguous
+ because it could be a numerical check on recursion, or a name check on a
+ group's being set. The pre-pass sets up META_COND_RNUMBER as a name so that
+ we can handle it either way. We first try for a name; if not found, process
+ the number. */
+
+ case META_COND_RNUMBER: /* (?(Rdigits) */
+ case META_COND_NAME: /* (?(name) or (?'name') or ?(<name>) */
+ case META_COND_RNAME: /* (?(R&name) - test for recursion */
+ bravalue = OP_COND;
{
- 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;
- }
+ int count, index;
+ PCRE2_SPTR name;
+ named_group *ng = cb->named_groups;
+ uint32_t length = *(++pptr);
- /* Now handle repetition for the different types of item. */
+ GETPLUSOFFSET(offset, pptr);
+ name = cb->start_pattern + offset;
- /* 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 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 firstcu instead. */
+ /* In the first pass, the names generated in the pre-pass are available,
+ but the main name table has not yet been created. Scan the list of names
+ generated in the pre-pass in order to get a number and whether or not
+ this name is duplicated. If it is not duplicated, we can handle it as a
+ numerical group. */
- if (*previous == OP_CHAR || *previous == OP_CHARI
- || *previous == OP_NOT || *previous == OP_NOTI)
- {
- switch (*previous)
+ for (i = 0; i < cb->names_found; i++, ng++)
{
- default: /* Make compiler happy. */
- case OP_CHAR: op_type = OP_STAR - OP_STAR; break;
- case OP_CHARI: op_type = OP_STARI - OP_STAR; break;
- case OP_NOT: op_type = OP_NOTSTAR - OP_STAR; break;
- case OP_NOTI: op_type = OP_NOTSTARI - OP_STAR; break;
+ if (length == ng->length &&
+ PRIV(strncmp)(name, ng->name, length) == 0)
+ {
+ if (!ng->isdup)
+ {
+ code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF;
+ PUT2(code, 2+LINK_SIZE, ng->number);
+ if (ng->number > cb->top_backref) cb->top_backref = ng->number;
+ skipunits = 1+IMM2_SIZE;
+ goto GROUP_PROCESS_NOTE_EMPTY;
+ }
+ break; /* Found a duplicated name */
+ }
}
- /* 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 code units, plus UTF_LENGTH to flag
- that it's a length rather than a small character. */
+ /* If the name was not found we have a bad reference, unless we are
+ dealing with R<digits>, which is treated as a recursion test by number.
+ */
-#ifdef MAYBE_UTF_MULTI
- if (utf && NOT_FIRSTCU(code[-1]))
+ if (i >= cb->names_found)
{
- PCRE2_UCHAR *lastchar = code - 1;
- BACKCHAR(lastchar);
- 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 /* MAYBE_UTF_MULTI */
-
- /* Handle the case of a single charater - either with no UTF support, or
- with UTF disabled, or for a single-code-unit UTF character. */
- {
- c = code[-1];
- if (*previous <= OP_CHARI && repeat_min > 1)
+ groupnumber = 0;
+ if (meta == META_COND_RNUMBER)
{
- reqcu = c;
- reqcuflags = req_caseopt | cb->req_varyopt;
+ for (i = 1; i < (int)length; i++)
+ {
+ groupnumber = groupnumber * 10 + name[i] - CHAR_0;
+ if (groupnumber > MAX_GROUP_NUMBER)
+ {
+ *errorcodeptr = ERR61;
+ cb->erroroffset = offset + i;
+ return 0;
+ }
+ }
}
- }
- goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */
- }
+ if (meta != META_COND_RNUMBER || groupnumber > cb->bracount)
+ {
+ *errorcodeptr = ERR15;
+ cb->erroroffset = offset;
+ return 0;
+ }
- /* 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_UNICODE is
- defined, but we don't wrap the little bits of code here because it just
- makes it horribly messy. */
+ /* (?Rdigits) treated as a recursion reference by number. A value of
+ zero (which is the result of both (?R) and (?R0)) means "any", and is
+ translated into RREF_ANY (which is 0xffff). */
- else if (*previous < OP_EODN)
- {
- PCRE2_UCHAR *oldcode;
- int prop_type, prop_value;
- 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
- {
- /* Come here from just above with a character in c */
- OUTPUT_SINGLE_REPEAT:
- prop_type = prop_value = -1;
+ if (groupnumber == 0) groupnumber = RREF_ANY;
+ code[1+LINK_SIZE] = OP_RREF;
+ PUT2(code, 2+LINK_SIZE, groupnumber);
+ skipunits = 1+IMM2_SIZE;
+ goto GROUP_PROCESS_NOTE_EMPTY;
}
- /* 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. */
+ /* A duplicated name was found. Note that if an R<digits> name is found
+ (META_COND_RNUMBER), it is a reference test, not a recursion test. */
- oldcode = code; /* Save where we were */
- code = previous; /* Usually overwrite previous item */
+ code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF;
- /* If the maximum is zero then the minimum must also be zero; Perl allows
- this case, so we do too - by simply omitting the item altogether. */
+ /* We have a duplicated name. In the compile pass we have to search the
+ main table in order to get the index and count values. */
- if (repeat_max == 0) goto END_REPEAT;
+ count = 0; /* Values for first pass (avoids compiler warning) */
+ index = 0;
+ if (lengthptr == NULL && !find_dupname_details(name, length, &index,
+ &count, errorcodeptr, cb)) return 0;
- /* Combine the op_type with the repeat_type */
+ /* Add one to the opcode to change CREF/RREF into DNCREF/DNRREF and
+ insert appropriate data values. */
- repeat_type += op_type;
+ code[1+LINK_SIZE]++;
+ skipunits = 1+2*IMM2_SIZE;
+ PUT2(code, 2+LINK_SIZE, index);
+ PUT2(code, 2+LINK_SIZE+IMM2_SIZE, count);
+ }
+ goto GROUP_PROCESS_NOTE_EMPTY;
+
+ /* The DEFINE condition is always false. It's internal groups may never
+ be called, so matched_char must remain false, hence the jump to
+ GROUP_PROCESS rather than GROUP_PROCESS_NOTE_EMPTY. */
+
+ case META_COND_DEFINE:
+ bravalue = OP_COND;
+ GETPLUSOFFSET(offset, pptr);
+ code[1+LINK_SIZE] = OP_DEFINE;
+ skipunits = 1;
+ goto GROUP_PROCESS;
+
+ /* Conditional test of a group's being set. */
+
+ case META_COND_NUMBER:
+ bravalue = OP_COND;
+ GETPLUSOFFSET(offset, pptr);
+ groupnumber = *(++pptr);
+ if (groupnumber > cb->bracount)
+ {
+ *errorcodeptr = ERR15;
+ cb->erroroffset = offset;
+ return 0;
+ }
+ if (groupnumber > cb->top_backref) cb->top_backref = groupnumber;
+ offset -= 2; /* Point at initial ( for too many branches error */
+ code[1+LINK_SIZE] = OP_CREF;
+ skipunits = 1+IMM2_SIZE;
+ PUT2(code, 2+LINK_SIZE, groupnumber);
+ goto GROUP_PROCESS_NOTE_EMPTY;
+
+ /* Test for the PCRE2 version. */
+
+ case META_COND_VERSION:
+ bravalue = OP_COND;
+ if (pptr[1] > 0)
+ code[1+LINK_SIZE] = ((PCRE2_MAJOR > pptr[2]) ||
+ (PCRE2_MAJOR == pptr[2] && PCRE2_MINOR >= pptr[3]))?
+ OP_TRUE : OP_FALSE;
+ else
+ code[1+LINK_SIZE] = (PCRE2_MAJOR == pptr[2] && PCRE2_MINOR == pptr[3])?
+ OP_TRUE : OP_FALSE;
+ skipunits = 1;
+ pptr += 3;
+ goto GROUP_PROCESS_NOTE_EMPTY;
- /* A minimum of zero is handled either as the special case * or ?, or as
- an UPTO, with the maximum given. */
+ /* The condition is an assertion, possibly preceded by a callout. */
- if (repeat_min == 0)
- {
- if (repeat_max == -1) *code++ = OP_STAR + repeat_type;
- else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;
- else
- {
- *code++ = OP_UPTO + repeat_type;
- PUT2INC(code, 0, repeat_max);
- }
- }
+ case META_COND_ASSERT:
+ bravalue = OP_COND;
+ goto GROUP_PROCESS_NOTE_EMPTY;
- /* A repeat minimum of 1 is optimized into some special cases. If the
- maximum is unlimited, we use OP_PLUS. Otherwise, the original item is
- left in place and, if the maximum is greater than 1, we use OP_UPTO with
- one less than the maximum. */
- else if (repeat_min == 1)
- {
- if (repeat_max == -1)
- *code++ = OP_PLUS + repeat_type;
- else
- {
- code = oldcode; /* Leave previous item in place */
- if (repeat_max == 1) goto END_REPEAT;
- *code++ = OP_UPTO + repeat_type;
- PUT2INC(code, 0, repeat_max - 1);
- }
- }
+ /* ===================================================================*/
+ /* Handle all kinds of nested bracketed groups. The non-capturing,
+ non-conditional cases are here; others come to GROUP_PROCESS via goto. */
+
+ case META_LOOKAHEAD:
+ bravalue = OP_ASSERT;
+ cb->assert_depth += 1;
+ goto GROUP_PROCESS;
+
+ /* Optimize (?!) to (*FAIL) unless it is quantified - which is a weird
+ thing to do, but Perl allows all assertions to be quantified, and when
+ they contain capturing parentheses there may be a potential use for
+ this feature. Not that that applies to a quantified (?!) but we allow
+ it for uniformity. */
+
+ case META_LOOKAHEADNOT:
+ if (pptr[1] == META_KET &&
+ (pptr[2] < META_ASTERISK || pptr[2] > META_MINMAX_QUERY))
+ {
+ *code++ = OP_FAIL;
+ pptr++;
+ }
+ else
+ {
+ bravalue = OP_ASSERT_NOT;
+ cb->assert_depth += 1;
+ goto GROUP_PROCESS;
+ }
+ break;
- /* The case {n,n} is just an EXACT, while the general case {n,m} is
- handled as an EXACT followed by an UPTO or STAR or QUERY. */
+ case META_LOOKBEHIND:
+ bravalue = OP_ASSERTBACK;
+ cb->assert_depth += 1;
+ goto GROUP_PROCESS;
- else
- {
- *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */
- PUT2INC(code, 0, repeat_min);
+ case META_LOOKBEHINDNOT:
+ bravalue = OP_ASSERTBACK_NOT;
+ cb->assert_depth += 1;
+ goto GROUP_PROCESS;
- /* 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. */
+ case META_ATOMIC:
+ bravalue = OP_ONCE;
+ goto GROUP_PROCESS_NOTE_EMPTY;
- if (repeat_max != repeat_min)
- {
-#ifdef MAYBE_UTF_MULTI
- if (utf && (c & UTF_LENGTH) != 0)
- {
- memcpy(code, utf_units, CU2BYTES(c & 7));
- code += c & 7;
- }
- else
-#endif /* MAYBE_UTF_MULTI */
- {
- *code++ = c;
- if (prop_type >= 0)
- {
- *code++ = prop_type;
- *code++ = prop_value;
- }
- }
+ case META_NOCAPTURE:
+ bravalue = OP_BRA;
+ /* Fall through */
- /* Now set up the following opcode */
+ /* Process nested bracketed regex. The nesting depth is maintained for the
+ benefit of the stackguard function. The test for too deep nesting is now
+ done in parse_regex(). Assertion and DEFINE groups come to GROUP_PROCESS;
+ others come to GROUP_PROCESS_NOTE_EMPTY, to indicate that we need to take
+ note of whether or not they may match an empty string. */
- if (repeat_max < 0) *code++ = OP_STAR + repeat_type; else
- {
- repeat_max -= repeat_min;
- if (repeat_max == 1)
- {
- *code++ = OP_QUERY + repeat_type;
- }
- else
- {
- *code++ = OP_UPTO + repeat_type;
- PUT2INC(code, 0, repeat_max);
- }
- }
- }
- }
+ GROUP_PROCESS_NOTE_EMPTY:
+ note_group_empty = TRUE;
- /* Fill in the character or character type for the final opcode. */
+ GROUP_PROCESS:
+ cb->parens_depth += 1;
+ *code = bravalue;
+ pptr++;
+ tempcode = code;
+ tempreqvary = cb->req_varyopt; /* Save value before group */
+ length_prevgroup = 0; /* Initialize for pre-compile phase */
-#ifdef MAYBE_UTF_MULTI
- if (utf && (c & UTF_LENGTH) != 0)
- {
- memcpy(code, utf_units, CU2BYTES(c & 7));
- code += c & 7;
- }
- else
-#endif /* MAYBEW_UTF_MULTI */
- {
- *code++ = c;
- if (prop_type >= 0)
- {
- *code++ = prop_type;
- *code++ = prop_value;
- }
- }
- }
+ if ((group_return =
+ compile_regex(
+ options, /* The option state */
+ &tempcode, /* Where to put code (updated) */
+ &pptr, /* Input pointer (updated) */
+ errorcodeptr, /* Where to put an error message */
+ skipunits, /* Skip over bracket number */
+ &subfirstcu, /* For possible first char */
+ &subfirstcuflags,
+ &subreqcu, /* For possible last char */
+ &subreqcuflags,
+ bcptr, /* Current branch chain */
+ cb, /* Compile data block */
+ (lengthptr == NULL)? NULL : /* Actual compile phase */
+ &length_prevgroup /* Pre-compile phase */
+ )) == 0)
+ return 0; /* Error */
- /* 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}. */
+ cb->parens_depth -= 1;
- else if (*previous == OP_CLASS || *previous == OP_NCLASS ||
-#ifdef SUPPORT_WIDE_CHARS
- *previous == OP_XCLASS ||
-#endif
- *previous == OP_REF || *previous == OP_REFI ||
- *previous == OP_DNREF || *previous == OP_DNREFI)
- {
- if (repeat_max == 0)
- {
- code = previous;
- goto END_REPEAT;
- }
+ /* If that was a non-conditional significant group (not an assertion, not a
+ DEFINE) that matches at least one character, then the current item matches
+ a character. Conditionals are handled below. */
- if (repeat_min == 0 && repeat_max == -1)
- *code++ = OP_CRSTAR + repeat_type;
- else if (repeat_min == 1 && repeat_max == -1)
- *code++ = OP_CRPLUS + repeat_type;
- else if (repeat_min == 0 && repeat_max == 1)
- *code++ = OP_CRQUERY + repeat_type;
- else
- {
- *code++ = OP_CRRANGE + repeat_type;
- PUT2INC(code, 0, repeat_min);
- if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */
- PUT2INC(code, 0, repeat_max);
- }
- }
+ if (note_group_empty && bravalue != OP_COND && group_return > 0)
+ matched_char = TRUE;
- /* If previous was a bracket group, we may have to replicate it in certain
- cases. Note that at this point we can encounter only the "basic" bracket
- opcodes such as BRA and CBRA, as this is the place where they get converted