diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-10-29 10:35:26 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2021-10-29 10:35:26 +0900 |
commit | 5ae663c280fa741754b78a4d442c1b5a33e502de (patch) | |
tree | 1ed23b28f45a28cd112bffd1a81b713c369b927e | |
parent | 8f331da86bcb848ebee6f930317fdb1553c56851 (diff) | |
download | glib-5ae663c280fa741754b78a4d442c1b5a33e502de.tar.gz glib-5ae663c280fa741754b78a4d442c1b5a33e502de.tar.bz2 glib-5ae663c280fa741754b78a4d442c1b5a33e502de.zip |
Imported Upstream version 2.69.0upstream/2.69.0
353 files changed, 7551 insertions, 39620 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 05e473138..73fbc1ba6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,11 +10,11 @@ cache: - _ccache/ variables: - FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/glib/fedora:v10" + FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/glib/fedora:v11" COVERITY_IMAGE: "registry.gitlab.gnome.org/gnome/glib/coverity:v1" - DEBIAN_IMAGE: "registry.gitlab.gnome.org/gnome/glib/debian-stable:v7" - ANDROID_IMAGE: "registry.gitlab.gnome.org/gnome/glib/android-ndk:v3" - MINGW_IMAGE: "registry.gitlab.gnome.org/gnome/glib/mingw:v2" + DEBIAN_IMAGE: "registry.gitlab.gnome.org/gnome/glib/debian-stable:v8" + ANDROID_IMAGE: "registry.gitlab.gnome.org/gnome/glib/android-ndk:v4" + MINGW_IMAGE: "registry.gitlab.gnome.org/gnome/glib/mingw:v3" MESON_TEST_TIMEOUT_MULTIPLIER: 2 G_MESSAGES_DEBUG: all MESON_COMMON_OPTIONS_NO_WARNING: "--buildtype debug --wrap-mode=nodownload" @@ -170,7 +170,7 @@ installed-tests: # FIXME install newer gobject-introspection # with GMemoryMonitor support, see: # https://gitlab.gnome.org/GNOME/gobject-introspection/merge_requests/193 - - git clone --branch master --depth 1 --no-tags https://gitlab.gnome.org/GNOME/gobject-introspection.git + - git clone --single-branch --depth 1 --no-tags https://gitlab.gnome.org/GNOME/gobject-introspection.git - cd gobject-introspection - /usr/bin/meson _build --prefix=/usr --libdir=/usr/lib64 - ninja -C _build @@ -270,7 +270,10 @@ cross-android_api21_arm64: # FIXME: add --werror # We use -Diconv=auto to test that we successfully detect that iconv is not # provided by android api 21, and detect the external iconv instead. - - meson ${MESON_COMMON_OPTIONS} --cross-file=/opt/cross_file_android_arm64_21.txt -Diconv=auto -Dinternal_pcre=true _build + # FIXME: Work around a bug in Meson 0.49 where --wrap-mode=nodownload also + # disables fallback subprojects, by passing --wrap-mode=default. Fixed in + # Meson commit 47b9c1a564756ac48a55da9a7c4d91787399c645 + - meson ${MESON_COMMON_OPTIONS} --cross-file=/opt/cross_file_android_arm64_21.txt -Diconv=auto --wrap-mode=default _build - ninja -C _build cross-android_api28_arm64: @@ -278,7 +281,10 @@ cross-android_api28_arm64: image: $ANDROID_IMAGE script: # FIXME: add --werror - - meson ${MESON_COMMON_OPTIONS} --cross-file=/opt/cross_file_android_arm64_28.txt -Dinternal_pcre=true _build + # FIXME: Work around a bug in Meson 0.49 where --wrap-mode=nodownload also + # disables fallback subprojects, by passing --wrap-mode=default. Fixed in + # Meson commit 47b9c1a564756ac48a55da9a7c4d91787399c645 + - meson ${MESON_COMMON_OPTIONS} --cross-file=/opt/cross_file_android_arm64_28.txt --wrap-mode=default _build - ninja -C _build cross-mingw64: @@ -286,7 +292,10 @@ cross-mingw64: image: $MINGW_IMAGE script: # FIXME: Add --werror - - meson ${MESON_COMMON_OPTIONS} --cross-file=/opt/cross_file_mingw64.txt _build + # FIXME: Work around a bug in Meson 0.49 where --wrap-mode=nodownload also + # disables fallback subprojects, by passing --wrap-mode=default. Fixed in + # Meson commit 47b9c1a564756ac48a55da9a7c4d91787399c645 + - meson ${MESON_COMMON_OPTIONS} --cross-file=/opt/cross_file_mingw64.txt --wrap-mode=default _build - ninja -C _build msys2-mingw32: @@ -513,7 +522,7 @@ coverity: pages: stage: deploy only: - - master + - main needs: ['coverage', 'style-check-diff'] script: - mv _coverage/ public/ diff --git a/.gitlab-ci/android-ndk.Dockerfile b/.gitlab-ci/android-ndk.Dockerfile index 56b186cbb..90b95826d 100644 --- a/.gitlab-ci/android-ndk.Dockerfile +++ b/.gitlab-ci/android-ndk.Dockerfile @@ -1,4 +1,4 @@ -FROM fedora:28 +FROM fedora:31 RUN dnf -y install \ autoconf \ @@ -44,6 +44,7 @@ RUN dnf -y install \ ncurses-compat-libs \ ninja-build \ pcre-devel \ + python-unversioned-command \ python3 \ python3-pip \ python3-wheel \ diff --git a/.gitlab-ci/meson-junit-report.py b/.gitlab-ci/meson-junit-report.py index 1855b4907..1d57ead50 100755 --- a/.gitlab-ci/meson-junit-report.py +++ b/.gitlab-ci/meson-junit-report.py @@ -27,7 +27,7 @@ aparser.add_argument( "--branch", metavar="NAME", help="Branch of the project being tested", - default="master", + default="main", ) aparser.add_argument( "--output", diff --git a/.gitlab-ci/mingw.Dockerfile b/.gitlab-ci/mingw.Dockerfile index d89de8cfb..2928b562c 100644 --- a/.gitlab-ci/mingw.Dockerfile +++ b/.gitlab-ci/mingw.Dockerfile @@ -1,4 +1,4 @@ -FROM fedora:29 +FROM fedora:31 RUN dnf -y install \ bindfs \ diff --git a/.gitlab-ci/run-style-check-diff.sh b/.gitlab-ci/run-style-check-diff.sh index a04bd0731..929cf28a4 100755 --- a/.gitlab-ci/run-style-check-diff.sh +++ b/.gitlab-ci/run-style-check-diff.sh @@ -25,7 +25,7 @@ exit_status=$? # style with the changes they’re making.) echo "" echo "Note that clang-format output is advisory and cannot always match the GLib coding style, documented at" -echo " https://gitlab.gnome.org/GNOME/gtk/blob/master/docs/CODING-STYLE" +echo " https://gitlab.gnome.org/GNOME/gtk/blob/HEAD/docs/CODING-STYLE.md" echo "Warnings from this tool can be ignored in favour of the documented coding style," echo "or in favour of matching the style of existing surrounding code." diff --git a/.gitlab-ci/search-common-ancestor.sh b/.gitlab-ci/search-common-ancestor.sh index a7a3ac44c..96f45fe69 100755 --- a/.gitlab-ci/search-common-ancestor.sh +++ b/.gitlab-ci/search-common-ancestor.sh @@ -9,7 +9,7 @@ ancestor_horizon=28 # days (4 weeks) # branches. # # Limit the fetch to a certain date horizon to limit the amount of data we get. -# If the branch was forked from origin/master before this horizon, it should +# If the branch was forked from origin/main before this horizon, it should # probably be rebased. if ! git ls-remote --exit-code upstream >/dev/null 2>&1 ; then git remote add upstream https://gitlab.gnome.org/GNOME/glib.git @@ -18,7 +18,7 @@ git fetch --shallow-since="$(date --date="${ancestor_horizon} days ago" +%Y-%m-% # Work out the newest common ancestor between the detached HEAD that this CI job # has checked out, and the upstream target branch (which will typically be -# `upstream/master` or `upstream/glib-2-62`). +# `upstream/main` or `upstream/glib-2-62`). # `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` or `${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}` # are only defined if we’re running in a merge request pipeline, # fall back to `${CI_DEFAULT_BRANCH}` or `${CI_COMMIT_BRANCH}` respectively @@ -29,8 +29,8 @@ git fetch --shallow-since="$(date --date="${ancestor_horizon} days ago" +%Y-%m-% newest_common_ancestor_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "upstream/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}") <(git rev-list --first-parent "origin/${source_branch}") | head -1) if [ -z "${newest_common_ancestor_sha}" ]; then - echo "Couldn’t find common ancestor with upstream master. This typically" - echo "happens if you branched from master a long time ago. Please update" + echo "Couldn’t find common ancestor with upstream main branch. This typically" + echo "happens if you branched from main a long time ago. Please update" echo "your clone, rebase, and re-push your branch." exit 1 fi diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 52f17b1d9..ba8039d4c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -256,7 +256,7 @@ to avoid unnecessary breakage, and to take advantage of the knowledge about GLib that has been built up over the years, we’d like to ask people contributing to GLib to follow a few rules: -0. Never push to the `master` branch, or any stable branches, directly; you +0. Never push to the `main` branch, or any stable branches, directly; you should always go through a merge request, to ensure that the code is tested on the CI infrastructure at the very least. A merge request is also the proper place to get a comprehensive code review from the core @@ -1,68 +1,255 @@ -Overview of changes in GLib 2.68.4 +Overview of changes in GLib 2.69.0 ================================== -* Bugs fixed: - - #2454 Read past the end of buffer in g_win32_package_parser_enum_packages - - !2158 Backport !2155 “glocalfilemonitor: Avoid a deadlock on finalization” to glib-2-68 - - !2175 Backport !2174 “data-to-c.py: generate new-line at the end of the file” to glib-2-68 - - !2183 Backport !2180 “correctly use 3 parameters for close_range” to glib-2-68 - - !2186 Backport !2185 “glocalfile: Fix the global trash dir detection” to glib-2-68 - - !2209 Backport !2208 “g_string_replace: Don't replace empty string more than once per location” to glib-2-68 - - !2220 Backport GWin32AppInfo fixes to glib-2-68 +* Fix a crash in `GKeyFile` when parsing a file which contains translations + using a `GKeyFile` instance which has loaded another file previously (#2361) -* Translation updates: - - Chinese (China) - - Chinese (Taiwan) - - Occitan (post 1500) +* Pin GIO DLL in memory on Windows (!2016) +* Fix building third-party projects against GLib on CentOS 7 (work by + Ignacio Casal Quinteiro) (#2387) -Overview of changes in GLib 2.68.3 -================================== +* Add `g_thread_pool_new_full()` API to allow queued `GThreadPool` data to be + freed if the pool is freed early (work by Nitin Wartkar) (#121) -* Bugs fixed: - - #2311 testfilemonitor test leaks ip_watched_file_t struct - - #2417 GFile: `g_file_replace_contents()` reports `G_IO_ERROR_WRONG_ETAG` when saving from a symlink - - !2133 Backport !2128 “inotify: Fix a memory leak” to glib-2-68 - - !2137 Backport !2136 “tlscertificate: Avoid possible invalid read” to glib-2-68 - - !2141 Backport !2138 “glocalfileoutputstream: Fix ETag check when replacing through a symlink” to glib-2-68 +* Ensure `dlerror()` is used with locking as it’s not thread-safe in some libc + implementations (#399) +* Add `g_dbus_is_error_name()` and `g_dbus_is_interface_name()` convenience + functions (work by Nitin Wartkar) (#402) -Overview of changes in GLib 2.68.2 -================================== +* Drop internal libpcre copy in favour of a subproject from wrapdb (#962, #642) -* Fix building third-party projects against GLib on CentOS 7 (work by - Ignacio Casal Quinteiro) (#2387) +* Add `g_prefix_error_literal()` helper function (work by Emmanuel Fleury, + building on work by Dan Williams) (#663) -* Bugs fixed: - - #2387 json-glib does not build with glib 2.68.1 - - !2060 gmacros: check that __cplusplus or _MSC_VER is defined - - !2068 gmacros: missing check if __STDC_VERSION__ is defined - - !2079 Backport !2078 “gthreadedresolver: don't ignore flags in lookup_by_name_with_flags” to glib-2-68 +* Add `g_bytes_get_region()` to get data from a `GBytes` with range checks + (work by Nitin Wartkar, building on work by Allison Karlitskaya) (#1098) -* Translation updates: - - Nepali - - Serbian +* Add `g_object_take_ref()` to sink a floating ref (work by Nitin Wartkar, + building on work by Allison Karlitskaya) (#1112) +* Optimise grefcount atomic operations (work by Nishal Kulkarni) (#1583) -Overview of changes in GLib 2.68.1 -================================== +* Fix resolving child GSettings schemas from the parent’s schema source (work + by Christian Persch) (#1884) -* Fix a crash in `GKeyFile` when parsing a file which contains translations - using a `GKeyFile` instance which has loaded another file previously (#2361) +* Fix `g_date_time_format()` return value encoding if `LC_TIME` is not a UTF-8 + locale but other locale settings are (work by Frederic Martinsons) (#2055) -* Pin GIO DLL in memory on Windows (!2016) +* Set app name in freedesktop.org notifications with `GNotification` (work + by André Apitzsch) (#2069) + +* Significantly improve retrieval of mount data on Windows (work by LRN based + on initial analysis by Jehan Pagès) (#2096) + +* Add `g_file_info_get_(access|creation)_date_time()` accessors (work + by Abanoub Ghadban) (#2281) + +* Always apply the remove_dot_segments algorithm to URIs in `g_uri_parse()`; + previously it was only applied to relative URIs (work + by Carlos Garcia Campos) (#2342) + +* Rename git `master` branch to `main` (#2348) + +* Various macro and version check cleanup (work by Gaël Bonithon, + Robin Verdenal-Tallieux, Nishal Kulkarni) (#2376, #2388, #2389) + +* Add a `GTlsConnectionClass.get_negotiated_protocol` vfunc so that + `g_tls_connection_get_negotiated_protocol()` can be made thread-safe + (work by Michael Catanzaro) (#2393) + +* Improve guess about whether a Windows process is a console process + (work by Princeton Ferro with input from LRN) (!1662) + +* Add `g_steal_fd()` function (work by Simon McVittie) (!1966) + +* Add `g_spawn_check_wait_status()` and distinguish more carefully between + wait status and exit status in the `GSpawn` API (work by Simon McVittie) (!1967) + +* Document GLib’s security policy; see + https://gitlab.gnome.org/GNOME/glib/-/blob/main/SECURITY.md (!1985) + +* Add `g_tree_remove_all()` (work by Lighto-Ku) (!1986) + +* Simplify exception handling on Windows to eliminate risk of it failing due + to prior heap corruption (work by LRN) (!2031) + +* Fix handling EOF when reading from SOCKS5 proxy stream (work + by Benjamin Berg) (!2032) + +* Unset the registered state of a `GApplication` after it has shut down (work + by Marco Trevisan) (!2056) + +* Support `GPattern` as a boxed type (work by Marco Trevisan) (!2066) + +* Add `g_tls_connection_get_protocol_version()` and + `g_tls_connection_get_ciphersuite_name()` to get TLS connection information + (work by Michael Catanzaro) (!2077) + +* Make TLS private key properties readable in `GTlsCertificate` (work + by Michael Catanzaro) (!2087) + +* Fix detection of static libintl when building on macOS (work + by Jonas Hahnfeld) (!2109) + +* Add `g_strv_builder_addv()` and `g_strv_builder_add_many()` to the + `GStrvBuilder` API (work by Alexandros Theodotou) (!2112) + +* Add `not-valid-before`, `not-valid-after`, `subject-name`, `issuer-name`, + `dns-names`, `ip-addresses` properties to `GTlsCertificate` + (work by Ross Wollman) (!2113, !2142) + +* Add PKCS#11 flags to `GTlsPasswordFlags` (work by Patrick Griffis) (!2126) * Bugs fixed: + - #121 GThreadPool and the ability to free data waiting to be handled + - #229 g_match_info_fetch_named not return empty string as expected + - #310 ref doc doesn't talk about "helper getters" optimization in g_file_info.c + - #399 dlerror() not thread-safe in all libc, making gmodule-dl.c's fetch_dlerror fail sometimes + - #402 please consider: #define g_dbus_is_error_name(x) g_dbus_is_interface_name (x) + - #626 Add documentation example for GArray and g_array_set_clear_func() + - #642 update to pcre 8.35+ + - #663 [patch] add g_prefix_error_literal() + - #793 Potentially confusing error message when object doesn't exist + - #817 gobject: Allow passing %NULL for @data in g_object_remove_toggle_ref + - #962 drop embedded pcre copy + - #1036 gdbusproxy stops tracking if dbus service restarts + - #1098 GBytes: add range-checked pointer getter + - #1112 GObject: add g_object_take_ref() + - #1583 Optimise gatomicrefcount operations + - #1864 Somewhat misleading documentation of GSourceFuncs + - #1884 `g_settings_get_child` not compatible with `g_settings_schema_source_new_from_directory` + - #2011 Add additional unit tests for D-Bus name watching + - #2055 g_date_time_format() does not return UTF-8 if LC_TIME is not UTF8 but other locale settings are UTF-8 + - #2069 FreedesktopNotification fails to set app_name + - #2096 SHGetFileInfoW() is not reliable (time-wise) + - #2281 Add g_file_info_get_(access|creation)_date_time() + - #2300 Crash on Windows MSVC build around gio + - #2311 testfilemonitor test leaks ip_watched_file_t struct + - #2340 GIO tests fail to build with clang-cl + - #2342 g_uri_parse doesn't apply the remove_dot_segments algorithm to the path + - #2348 Investigate renaming master git branch to main + - #2352 RUN_FIRST | RUN_CLEANUP signals with a default handler ignore return values from user handlers + - #2359 GLib 2.68.0: gio-querymodules segfaults on Windows - #2361 g_key_file_load_from_file segfaults on "Key[*]="like lines - - !1997 Backport !1996 “Include glibconfig.h to get the G_OS_UNIX token” to glib-2-68 + - #2363 g_newa() doesn’t check for multiplication overflow + - #2368 g_task_run_in_thread () limits are not clear + - #2369 glocalfile: Add native exfat magic number to filesystem list + - #2376 GLIB_VERSION_MAX_ALLOWED < 2.60 does not warn when using G_GNUC_FALLTHROUGH + - #2387 json-glib does not build with glib 2.68.1 + - #2388 Pixman compilation error due to glib + - #2389 Use G_GNUC_CHECK_VERSION to check the GNUC version + - #2393 g_tls_connection_get_negotiated_protocol() is not threadsafe + - #2397 Slow to list device in windows + - #2399 Change spelling of ‘serialise’ to ‘serialize’ in documentation + - #2405 Mention that GNotification requires an installed .desktop file to work + - #2409 Project crashes when executing g_application_mark_busy + - #2414 Devhelp: Glib Reference Manual/Glib Overview/Running Glib Applications formatting issue. + - #2416 certificate: g_tls_certificate_new_from_pem invalid read on non null terminated data + - #2417 GFile: `g_file_replace_contents()` reports `G_IO_ERROR_WRONG_ETAG` when saving from a symlink + - #2418 gatomic: __atomic functions are called for CV-qualified output variables + - #2423 resources.c:656:test_resource_binary_linked: 'found' should be TRUE + - !1514 gbookmarkfile: Don't crash if we're not visited + - !1662 gspawn-win32: improve guess whether process is console process + - !1812 docs: Expand documentation about D-Bus GUIDs + - !1957 Fix more warnings + - !1965 gversionmacros: Add version macros for GLib 2.70 + - !1966 Add g_steal_fd() to API + - !1967 Distinguish more clearly between wait status and exit status + - !1969 glib_typeof: Move definition to its own header + - !1985 docs: Add a policy for handling security issues + - !1986 make g_tree_remove_all public + - !1996 Include glibconfig.h to get the G_OS_UNIX token + - !1998 gpollableinputstream: Add missing annotation + - !1999 goption.c: Simplfy parse_short_option() + - !2004 Some improvements to clang-cl builds + - !2005 introspection: Remove 'caller-allocates' from POD types + - !2006 fuzzing: Add fuzz tests for functions which parse paths + - !2008 tests: Deactivate tls-bindings test suite for windows + - !2011 docs: Fix example program link + - !2012 docs: Replace git.gnome.org with gitlab.gnome.org urls + - !2013 fuzzing: Fix assertion failure in fuzz_paths.c - !2016 GIO W32: Pin gio DLL - - !2021 Backport MR !2016 (GIO W32: Pin gio DLL) into glib-2-68 - - !2022 Few fixes and notes for building on Visual Studio 2012 and earlier - - !2034 Backport MR !2032 (gkeyfile: Drop a redundant check) into glib-2-68 - - !2035 Backport !2026 “Split g_test_log() messages that contain multiple lines” to glib-2-68 + - !2023 gtlspassword: Fix g-i annotation of return for g_tls_password_get_value + - !2025 [th/gdbus-cleanup] two minor cleanup patches for gdbusconnection.c + - !2026 Split g_test_log() messages that contain multiple lines + - !2027 Fix a handful of minor leaks found by Coverity + - !2030 Fix more warnings + - !2031 Re-simplify exception handling on Windows + - !2032 gsocks5proxy: Handle EOF when reading from a stream + - !2033 Fix annotation of count arguments + - !2036 gmacros.h: use G_GNUC_CHECK_VERSION + - !2038 Fix more warnings + - !2039 Implement G_ANALYZER_NORETURN for Coverity + - !2040 Fix more warnings + - !2041 refcount: Clarify when the ref count ends up undefined + - !2042 grefcount: Clarify that the initial reference count is 1 + - !2043 gmacros.h: use g_macro__has_attribute() where possible + - !2046 gerror: Clarify docs around message requirements + - !2047 Fix more warnings + - !2048 Fix more warnings + - !2049 Fix typo in g_socket_listener_accept_async()'s comment + - !2050 gdbus: document completion after idle action for g_dbus_connection_signal_unsubscribe() + - !2051 Add nullable annotations in GUnixMountEntry + - !2052 g_string_replace(): Fix documentation of 'limit' parameter + - !2054 docs: Fix formatting of code block + - !2055 Improve handling of FILENAME_MAX + - !2056 application: Unset the registered state after shutting down + - !2063 Fix more warnings + - !2066 gpattern: Register as Boxed type and support introspection for it + - !2067 gmacros: missing check if __STDC_VERSION__ is defined + - !2069 gdbus-tool: Actually use argv[0] basename as program name + - !2071 gstring: Cleanup documentation of g_string_replace + - !2074 Fix more warnings + - !2075 gdtlsconnection: Fix a check for a vfunc being implemented + - !2077 tls: add functions to get protocol version and ciphersuite name + - !2078 gthreadedresolver: don't ignore flags in lookup_by_name_with_flags + - !2080 guuid: fix shift operation to parse hex string in uuid_parse_string() + - !2081 Fix more warnings + - !2085 gcredentials.h: Fix comment typo + - !2087 gtlscertificate: make private key properties readable + - !2088 Fix more warnings + - !2090 docs: Standardize spelling of serializ* + - !2091 Fix more warnings (clang) + - !2098 grefcount: Optimise g_atomic_ref_count_dec + - !2099 gmacros.h: G_NORETURN: remove useless checks + - !2100 tests: Add missing return value check in string test + - !2101 Fix more warnings + - !2104 tests: Drop use of g_test_bug_base() + - !2105 tests: Use a temporary file in the bookmarkfile tests + - !2106 Fix more warnings + - !2108 glib spawn-singlethread test only if F_DUPFD_CLOEXEC is defined + - !2109 meson: Fix detection of static libintl on macOS + - !2112 gstrvbuilder: add addv and add_many to the API + - !2113 tls: expose cert details on GTlsCertificate + - !2119 Fix more warnings + - !2120 gdbusobjectmanagerclient: Call GetManagedObjects async + - !2123 gdbus: Add various missing (nullable) or (not nullable) annotations + - !2126 gtlspassword: Add flags signifying PIN type for PKCS#11 + - !2127 gutils: ensure g_find_program_in_path() return an absolute path + - !2130 Revert "tests: Deactivate tls-bindings test suite for windows" + - !2139 gdbus, win32: Fix accidental dllexport in static builds + - !2142 tls: expose SAN details on GTlsCertificate + - !2143 compiling.xml: Don't recommend backticks + - !2144 pcre: Drop internal libpcre copy + - !2145 gunixmounts: Document NULL return value for g_unix_mount_for() + - !2152 tests: A few small improvements to GBytes tests + - !2153 docs: Fix annotations for optional arguments + - !2155 glocalfilemonitor: Avoid a deadlock on finalization + - !2162 testgdate: fix -Wmisleading-indentation warning + - !2166 gtlscertificate: Add more annotations to new properties + - !2167 g_value_set_string description: clarified (unified), that v_string is a copy. + - !2173 gasyncqueue: Add missing (nullable) annotation to free function + - !2174 data-to-c.py: generate new-line at the end of the file * Translation updates: + - Chinese (China) - English (United Kingdom) + - Hebrew + - Nepali + - Occitan (post 1500) + - Serbian Overview of changes in GLib 2.68.0 @@ -47,3 +47,16 @@ Closes: #123 Otherwise, create a new merge request that introduces the change, filing a separate issue is not required. + +## Default branch renamed to `main` + +The default development branch of GLib has been renamed to `main`. To update +your local checkout, use: +```sh +git checkout master +git branch -m master main +git fetch +git branch --unset-upstream +git branch -u origin/main +git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main +``` diff --git a/README.win32.md b/README.win32.md index e67552270..17b36acbf 100644 --- a/README.win32.md +++ b/README.win32.md @@ -163,71 +163,7 @@ normally. ### Support for pre-2012 Visual Studio -This release of GLib requires at least the Windows 8.0 SDK in order to be built -successfully using Visual Studio, which means that building with Visual Studio -2008 or 2010 is possible only with a special setup and must be done in the -command line with Ninja. Please see -https://devblogs.microsoft.com/cppblog/using-the-windows-software-development-kit-sdk-for-windows-8-consumer-preview-with-visual-studio-2010/ -for references; basically, assuming that your Windows 8.0 SDK is installed in -`C:\Program Files (x86)\Windows Kits\8.0` (`$(WIN8SDKDIR)` in short), you need -to ensure the following before invoking Meson to configure the build: - -- Your `%INCLUDE%` must not include the Windows 7.0/7.1 SDK include directories, - and `$(WIN8SDKDIR)\include\um`, `$(WIN8SDKDIR)\include\um\share` and - `$(WIN8SDKDIR)\include\winrt` (in this order) must be before your stock - Visual Studio 2008/2010 header directories. If you have the DirectX SDK installed, - you should remove its include directory from your `%INCLUDE%` as well. -- You must replace the Windows 7.0/7.1 SDK library directory in `%LIB%` with the - Windows 8.0 SDK library directory, i.e. `$(WIN8SDKDIR)\lib\win8\um\[x86|x64]`. - If you have the DirectX SDK installed, you should remove its library directory - from your `%INCLUDE%` as well. -- You must replace the Windows 7.0/7.1 SDK tools directory from your `%PATH%` with - the Windows 8.0 SDK tools directory, i.e. `$(WIN8SDKDIR)\bin\[x86|x64]`. - If you have the DirectX SDK installed, you should remove its utility directory - from your `%PATH%` as well. - -The Windows 8.0 SDK headers may contain an `roapi.h` that cannot be used under plain -C, so to remedy that, change the following lines (around lines 55-57): - -``` -// RegisterActivationFactory/RevokeActivationFactory registration cookie -typedef struct {} *RO_REGISTRATION_COOKIE; -// RegisterActivationFactory/DllGetActivationFactory callback -``` - -to - -``` -// RegisterActivationFactory/RevokeActivationFactory registration cookie -#ifdef __cplusplus -typedef struct {} *RO_REGISTRATION_COOKIE; -#else -typedef struct _RO_REGISTRATION_COOKIE *RO_REGISTRATION_COOKIE; /* make this header includable in C files */ -#endif -// RegisterActivationFactory/DllGetActivationFactory callback -``` - -This follows what is done in the Windows 8.1 SDK, which contains an `roapi.h` -that is usable under plain C. Please note that you might need to copy that file -into a location that is in your `%INCLUDE%` which precedes the include path for the -Windows 8.0 SDK headers, if you do not have administrative privileges. - -### Visual Studio 2008 hacks - -- You need to run the following lines from your build directory, to embed the - manifests that are generated during the build, assuming the built binaries - are installed to `$(PREFIX)`, after a successful build/installation: - -```cmd -> for /r %f in (*.dll.manifest) do if exist $(PREFIX)\bin\%~nf mt /manifest %f (PREFIX)\bin\%~nf;2 -> for /r %f in (*.exe.manifest) do if exist $(PREFIX)\bin\%~nf mt /manifest %f (PREFIX)\bin\%~nf;1 -``` - - -- If building for amd64/x86_64/x64, sometimes the compilation of sources may seem to hang, which - is caused by an optimization issue in the 2008 x64 compiler. You need to use Task Manager to - remove all running instances of `cl.exe`, which will cause the build process to terminate. Update - the build flags of the sources that hang on compilation by changing its `"/O2"` flag to `"/O1"` - in `build.ninja`, and retry the build, where things should continue to build normally. At the - time of writing, this is needed for compiling `glib/gtestutils.c`, `gio/gsettings.c`, - `gio/gsettingsschema.c`, `glib/tests/fileutils.c` and `gio/tests/gsubprocess-testprog.c` +This release of GLib requires at least the Windows 8 SDK in order to be built +successfully using Visual Studio, which means that it is no longer supported to +build GLib with Visual Studio 2008 nor 2010. People that still need to use +Visual Studio 2008 or 2010 should continue to use glib-2.66.x. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..3505b2abf --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,67 @@ +# Security policy for GLib + + * [Supported Versions](#Supported-Versions) + * [Reporting a Vulnerability](#Reporting-a-Vulnerability) + * [Security Announcements](#Security-Announcements) + * [Acknowledgements](#Acknowledgements) + +## Supported Versions + +Upstream GLib only supports the most recent stable release series, and the +current development release series. Any older stable release series are no +longer supported, although they may still receive backported security updates +in long-term support distributions. Such support is up to the distributions, +though. + +Under GLib’s versioning scheme, stable release series have an *even* minor +component (for example, 2.66.0, 2.66.1, 2.68.3), and development release series +have an *odd* minor component (2.67.1, 2.69.0). + +## Reporting a Vulnerability + +If you think you've identified a security issue in GLib, GObject or GIO, please +**do not** report the issue publicly via a mailing list, IRC, a public issue on +the GitLab issue tracker, a merge request, or any other public venue. + +Instead, report a +[*confidential* issue in the GitLab issue tracker](https://gitlab.gnome.org/GNOME/glib/-/issues/new?issue[confidential]=1), +with the “This issue is confidential” box checked. Please include as many +details as possible, including a minimal reproducible example of the issue, and +an idea of how exploitable/severe you think it is. + +**Do not** provide a merge request to fix the issue, as there is currently no +way to make confidential merge requests on gitlab.gnome.org. If you have patches +which fix the security issue, please attach them to your confidential issue as +patch files. + +Confidential issues are only visible to the reporter and the GLib maintainers. + +As per the [GNOME security policy](https://security.gnome.org/), the next steps +are then: + * The report is triaged. + * Code is audited to find any potential similar problems. + * If it is determined, in consultation with the submitter, that a CVE is + required, the submitter obtains one via [cveform.mitre.org](https://cveform.mitre.org/). + * The fix is prepared for the development branch, and for the most recent + stable branch. + * The fix is submitted to the public repository. + * On the day the issue and fix are made public, an announcement is made on the + [public channels listed below](#Security-Announcements). + * A new release containing the fix is issued. + +## Security Announcements + +Security announcements are made publicly via the +[`distributor` tag on discourse.gnome.org](https://discourse.gnome.org/tag/distributor) +and cross-posted to the +[distributor-list](https://mail.gnome.org/mailman/listinfo/distributor-list). + +Announcements for security issues with wide applicability or high impact may +additionally be made via +[oss-security@lists.openwall.com](https://www.openwall.com/lists/oss-security/). + +## Acknowledgements + +This text was partially based on the +[github.com/containers security policy](https://github.com/containers/common/blob/HEAD/SECURITY.md), +and partially based on the [flatpak security policy](https://github.com/flatpak/flatpak/blob/HEAD/SECURITY.md). diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml index 9cd3d0e39..a09d6d31d 100644 --- a/docs/reference/gio/gio-docs.xml +++ b/docs/reference/gio/gio-docs.xml @@ -389,6 +389,10 @@ <title>Index of new symbols in 2.68</title> <xi:include href="xml/api-index-2.68.xml"><xi:fallback /></xi:include> </index> + <index id="api-index-2-70" role="2.70"> + <title>Index of new symbols in 2.70</title> + <xi:include href="xml/api-index-2.70.xml"><xi:fallback /></xi:include> + </index> <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include> diff --git a/docs/reference/gio/gio-sections-common.txt b/docs/reference/gio/gio-sections-common.txt index 945c26ade..250491a42 100644 --- a/docs/reference/gio/gio-sections-common.txt +++ b/docs/reference/gio/gio-sections-common.txt @@ -397,6 +397,8 @@ g_file_info_get_content_type g_file_info_get_size g_file_info_get_modification_time g_file_info_get_modification_date_time +g_file_info_get_access_date_time +g_file_info_get_creation_date_time g_file_info_get_symlink_target g_file_info_get_etag g_file_info_get_sort_order @@ -415,6 +417,8 @@ g_file_info_set_content_type g_file_info_set_size g_file_info_set_modification_time g_file_info_set_modification_date_time +g_file_info_set_access_date_time +g_file_info_set_creation_date_time g_file_info_set_symlink_target g_file_info_set_sort_order g_file_attribute_matcher_new @@ -2802,6 +2806,7 @@ g_dbus_is_name g_dbus_is_unique_name g_dbus_is_member_name g_dbus_is_interface_name +g_dbus_is_error_name g_dbus_gvalue_to_gvariant g_dbus_gvariant_to_gvalue g_dbus_escape_object_path_bytestring @@ -3663,16 +3668,19 @@ GTlsChannelBindingError <SUBSECTION> GTlsAuthenticationMode GTlsCertificateFlags +GTlsProtocolVersion <SUBSECTION Standard> G_TYPE_TLS_AUTHENTICATION_MODE G_TYPE_TLS_CERTIFICATE_FLAGS G_TYPE_TLS_CHANNEL_BINDING_ERROR G_TYPE_TLS_ERROR +G_TYPE_TLS_PROTOCOL_VERSION g_tls_authentication_mode_get_type g_tls_certificate_flags_get_type g_tls_channel_binding_error_get_type g_tls_channel_binding_error_quark g_tls_error_get_type +g_tls_protocol_version_get_type </SECTION> <SECTION> @@ -3711,7 +3719,13 @@ g_tls_certificate_new_from_file g_tls_certificate_new_from_files g_tls_certificate_new_from_pkcs11_uris g_tls_certificate_list_new_from_file +g_tls_certificate_get_dns_names +g_tls_certificate_get_ip_addresses g_tls_certificate_get_issuer +g_tls_certificate_get_issuer_name +g_tls_certificate_get_not_valid_before +g_tls_certificate_get_not_valid_after +g_tls_certificate_get_subject_name g_tls_certificate_verify g_tls_certificate_is_same <SUBSECTION Standard> @@ -3750,6 +3764,8 @@ g_tls_connection_get_database g_tls_connection_set_database g_tls_connection_get_interaction g_tls_connection_set_interaction +g_tls_connection_get_protocol_version +g_tls_connection_get_ciphersuite_name <SUBSECTION> g_tls_connection_handshake g_tls_connection_handshake_async @@ -3944,6 +3960,8 @@ g_dtls_connection_get_database g_dtls_connection_set_database g_dtls_connection_get_interaction g_dtls_connection_set_interaction +g_dtls_connection_get_protocol_version +g_dtls_connection_get_ciphersuite_name <SUBSECTION> g_dtls_connection_handshake g_dtls_connection_handshake_async diff --git a/docs/reference/gio/gsettings.xml b/docs/reference/gio/gsettings.xml index d7dc65db6..5f720d6e7 100644 --- a/docs/reference/gio/gsettings.xml +++ b/docs/reference/gio/gsettings.xml @@ -136,7 +136,7 @@ the dconf database. <term><option>get</option></term> <listitem><para> Gets the value of <replaceable>KEY</replaceable>. -The value is printed out as a serialised +The value is printed out as a serialized <link linkend="GVariant"><type>GVariant</type></link>. </para></listitem> </varlistentry> @@ -175,7 +175,7 @@ Queries the description of valid values for <replaceable>KEY</replaceable>. <term><option>set</option></term> <listitem><para> Sets the value of <replaceable>KEY</replaceable> to -<replaceable>VALUE</replaceable>. The value is specified as a serialised +<replaceable>VALUE</replaceable>. The value is specified as a serialized <link linkend="GVariant"><type>GVariant</type></link>. </para></listitem> </varlistentry> diff --git a/docs/reference/glib/building.xml b/docs/reference/glib/building.xml index 9ff2fbfe7..d165c5c23 100644 --- a/docs/reference/glib/building.xml +++ b/docs/reference/glib/building.xml @@ -153,12 +153,9 @@ <listitem> <para> GRegex uses the <ulink url="http://www.pcre.org/">PCRE library</ulink> - for regular expression matching. The default is to use the system - version of PCRE, to reduce the chances of security fixes going out - of sync. GLib additionally provides an internal copy of PCRE in case - the system version is too old, or does not support UTF-8; the internal - copy is patched to use GLib for memory management and to share the - same Unicode tables. + for regular expression matching. The system version of PCRE is used, + unless not available (which is the case on Android), in which case a + fallback subproject is used. </para> </listitem> <listitem> @@ -236,45 +233,6 @@ </formalpara> <formalpara> - <title><option>-Dinternal_pcre=true</option></title> - - <para> - Normally, GLib will be configured to use the system-supplied PCRE - library if it is suitable, falling back to an internal version - otherwise. If this option is specified, the internal version will always - be used. - </para> - <para> - Using the internal PCRE is the preferred solution if: - <itemizedlist> - <listitem> - <para> - your system has strict resource constraints; the system-supplied - PCRE has a separated copy of the tables used for Unicode - handling, whereas the internal copy shares the Unicode tables - used by GLib. - </para> - </listitem> - <listitem> - <para> - your system has PCRE built without some needed features, - such as UTF-8 and Unicode support. - </para> - </listitem> - <listitem> - <para> - you are planning to use both GRegex and PCRE API at the same - time, either directly or indirectly through a dependency; PCRE - uses some global variables for memory management and - other features, and if both GLib and PCRE try to access them - at the same time, this could lead to undefined behavior. - </para> - </listitem> - </itemizedlist> - </para> - </formalpara> - - <formalpara> <title><option>-Dbsymbolic_functions=false</option> and <option>-Dbsymbolic_functions=true</option></title> diff --git a/docs/reference/glib/compiling.xml b/docs/reference/glib/compiling.xml index 02971a60f..c7a058c5f 100644 --- a/docs/reference/glib/compiling.xml +++ b/docs/reference/glib/compiling.xml @@ -60,13 +60,13 @@ The difference between the two is that gmodule-2.0 adds which is often not needed. </para> <para> -The simplest way to compile a program is to use the "backticks" -feature of the shell. If you enclose a command in backticks -(<emphasis>not single quotes</emphasis>), then its output will -be substituted into the command line before execution. So to -compile a GLib Hello, World, you would type the following: +The simplest way to compile a program is to use command substitution +feature of a shell. A command written in the format +<literal>$(command)</literal> gets substituted into the command line +before execution. So to compile a GLib Hello, World, you would type +the following: <programlisting> -$ cc hello.c `pkg-config --cflags --libs glib-2.0` -o hello +$ cc hello.c $(pkg-config --cflags --libs glib-2.0) -o hello </programlisting> </para> <note><para> diff --git a/docs/reference/glib/glib-docs.xml b/docs/reference/glib/glib-docs.xml index e464fb792..2f5de9e31 100644 --- a/docs/reference/glib/glib-docs.xml +++ b/docs/reference/glib/glib-docs.xml @@ -288,6 +288,10 @@ <title>Index of new symbols in 2.68</title> <xi:include href="xml/api-index-2.68.xml"><xi:fallback /></xi:include> </index> + <index id="api-index-2-70" role="2.70"> + <title>Index of new symbols in 2.70</title> + <xi:include href="xml/api-index-2.70.xml"><xi:fallback /></xi:include> + </index> <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include> diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 460a299bf..406041253 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -138,6 +138,7 @@ GLIB_VERSION_2_62 GLIB_VERSION_2_64 GLIB_VERSION_2_66 GLIB_VERSION_2_68 +GLIB_VERSION_2_70 GLIB_VERSION_CUR_STABLE GLIB_VERSION_PREV_STABLE GLIB_VERSION_MIN_REQUIRED @@ -168,6 +169,7 @@ GLIB_AVAILABLE_ENUMERATOR_IN_2_62 GLIB_AVAILABLE_ENUMERATOR_IN_2_64 GLIB_AVAILABLE_ENUMERATOR_IN_2_66 GLIB_AVAILABLE_ENUMERATOR_IN_2_68 +GLIB_AVAILABLE_ENUMERATOR_IN_2_70 GLIB_AVAILABLE_IN_ALL GLIB_AVAILABLE_IN_2_26 GLIB_AVAILABLE_IN_2_28 @@ -191,6 +193,7 @@ GLIB_AVAILABLE_IN_2_62 GLIB_AVAILABLE_IN_2_64 GLIB_AVAILABLE_IN_2_66 GLIB_AVAILABLE_IN_2_68 +GLIB_AVAILABLE_IN_2_70 GLIB_AVAILABLE_MACRO_IN_2_26 GLIB_AVAILABLE_MACRO_IN_2_28 GLIB_AVAILABLE_MACRO_IN_2_30 @@ -213,12 +216,14 @@ GLIB_AVAILABLE_MACRO_IN_2_62 GLIB_AVAILABLE_MACRO_IN_2_64 GLIB_AVAILABLE_MACRO_IN_2_66 GLIB_AVAILABLE_MACRO_IN_2_68 +GLIB_AVAILABLE_MACRO_IN_2_70 GLIB_AVAILABLE_STATIC_INLINE_IN_2_44 GLIB_AVAILABLE_STATIC_INLINE_IN_2_60 GLIB_AVAILABLE_STATIC_INLINE_IN_2_62 GLIB_AVAILABLE_STATIC_INLINE_IN_2_64 GLIB_AVAILABLE_STATIC_INLINE_IN_2_66 GLIB_AVAILABLE_STATIC_INLINE_IN_2_68 +GLIB_AVAILABLE_STATIC_INLINE_IN_2_70 GLIB_AVAILABLE_TYPE_IN_2_26 GLIB_AVAILABLE_TYPE_IN_2_28 GLIB_AVAILABLE_TYPE_IN_2_30 @@ -241,6 +246,7 @@ GLIB_AVAILABLE_TYPE_IN_2_62 GLIB_AVAILABLE_TYPE_IN_2_64 GLIB_AVAILABLE_TYPE_IN_2_66 GLIB_AVAILABLE_TYPE_IN_2_68 +GLIB_AVAILABLE_TYPE_IN_2_70 GLIB_DEPRECATED_ENUMERATOR GLIB_DEPRECATED_ENUMERATOR_FOR GLIB_DEPRECATED_ENUMERATOR_IN_2_26 @@ -287,6 +293,8 @@ GLIB_DEPRECATED_ENUMERATOR_IN_2_66 GLIB_DEPRECATED_ENUMERATOR_IN_2_66_FOR GLIB_DEPRECATED_ENUMERATOR_IN_2_68 GLIB_DEPRECATED_ENUMERATOR_IN_2_68_FOR +GLIB_DEPRECATED_ENUMERATOR_IN_2_70 +GLIB_DEPRECATED_ENUMERATOR_IN_2_70_FOR GLIB_DEPRECATED_IN_2_26 GLIB_DEPRECATED_IN_2_26_FOR GLIB_DEPRECATED_IN_2_28 @@ -331,6 +339,8 @@ GLIB_DEPRECATED_IN_2_66 GLIB_DEPRECATED_IN_2_66_FOR GLIB_DEPRECATED_IN_2_68 GLIB_DEPRECATED_IN_2_68_FOR +GLIB_DEPRECATED_IN_2_70 +GLIB_DEPRECATED_IN_2_70_FOR GLIB_DEPRECATED_MACRO GLIB_DEPRECATED_MACRO_FOR GLIB_DEPRECATED_MACRO_IN_2_26 @@ -377,6 +387,8 @@ GLIB_DEPRECATED_MACRO_IN_2_66 GLIB_DEPRECATED_MACRO_IN_2_66_FOR GLIB_DEPRECATED_MACRO_IN_2_68 GLIB_DEPRECATED_MACRO_IN_2_68_FOR +GLIB_DEPRECATED_MACRO_IN_2_70 +GLIB_DEPRECATED_MACRO_IN_2_70_FOR GLIB_DEPRECATED_TYPE GLIB_DEPRECATED_TYPE_FOR GLIB_DEPRECATED_TYPE_IN_2_26 @@ -423,6 +435,8 @@ GLIB_DEPRECATED_TYPE_IN_2_66 GLIB_DEPRECATED_TYPE_IN_2_66_FOR GLIB_DEPRECATED_TYPE_IN_2_68 GLIB_DEPRECATED_TYPE_IN_2_68_FOR +GLIB_DEPRECATED_TYPE_IN_2_70 +GLIB_DEPRECATED_TYPE_IN_2_70_FOR GLIB_VERSION_CUR_STABLE GLIB_VERSION_PREV_STABLE </SECTION> @@ -735,10 +749,25 @@ G_ANALYZER_ANALYZING G_ANALYZER_NORETURN g_autoptr_cleanup_generic_gfree glib_typeof -glib_typeof_2_68 g_macro__has_attribute g_macro__has_builtin g_macro__has_feature +g_macro__has_extension +g_macro__has_attribute___alloc_size__ +g_macro__has_attribute___const__ +g_macro__has_attribute___deprecated__ +g_macro__has_attribute___format__ +g_macro__has_attribute___format_arg__ +g_macro__has_attribute___malloc__ +g_macro__has_attribute___no_instrument_function__ +g_macro__has_attribute___noreturn__ +g_macro__has_attribute___pure__ +g_macro__has_attribute___sentinel__ +g_macro__has_attribute___unused__ +g_macro__has_attribute_fallthrough +g_macro__has_attribute_may_alias +g_macro__has_attribute___noinline__ +g_macro__has_attribute_warn_unused_result </SECTION> <SECTION> @@ -756,6 +785,7 @@ g_set_error_literal g_propagate_error g_clear_error g_prefix_error +g_prefix_error_literal g_propagate_prefixed_error <SUBSECTION> GErrorInitFunc @@ -910,6 +940,9 @@ g_source_remove_by_user_data GClearHandleFunc g_clear_handle_id +<SUBSECTION> +g_steal_fd + <SUBSECTION Private> GLIB_HAVE_ALLOCA_H alloca @@ -1138,6 +1171,7 @@ g_once_init_enter_impl <FILE>thread_pools</FILE> GThreadPool g_thread_pool_new +g_thread_pool_new_full g_thread_pool_push g_thread_pool_set_max_threads g_thread_pool_get_max_threads @@ -1392,6 +1426,9 @@ GPatternSpec g_pattern_spec_new g_pattern_spec_free g_pattern_spec_equal +g_pattern_spec_copy +g_pattern_spec_match +g_pattern_spec_match_string g_pattern_match g_pattern_match_string g_pattern_match_simple @@ -1531,6 +1568,7 @@ g_spawn_async_with_pipes_and_fds g_spawn_async g_spawn_sync G_SPAWN_EXIT_ERROR +g_spawn_check_wait_status g_spawn_check_exit_status g_spawn_command_line_async g_spawn_command_line_sync @@ -1613,6 +1651,7 @@ GOptionArg GOptionFlags G_OPTION_REMAINING GOptionEntry +G_OPTION_ENTRY_NULL g_option_context_add_main_entries GOptionGroup g_option_context_add_group @@ -1828,6 +1867,8 @@ g_strv_builder_new g_strv_builder_ref g_strv_builder_unref g_strv_builder_add +g_strv_builder_addv +g_strv_builder_add_many g_strv_builder_end <SUBSECTION> @@ -2989,6 +3030,7 @@ g_bytes_new_static g_bytes_new_with_free_func g_bytes_new_from_bytes g_bytes_get_data +g_bytes_get_region g_bytes_get_size g_bytes_hash g_bytes_equal @@ -3038,6 +3080,7 @@ g_tree_lower_bound g_tree_upper_bound g_tree_remove g_tree_steal +g_tree_remove_all g_tree_destroy </SECTION> diff --git a/docs/reference/glib/gvariant-varargs.xml b/docs/reference/glib/gvariant-varargs.xml index cd9002ca5..bab12e31e 100644 --- a/docs/reference/glib/gvariant-varargs.xml +++ b/docs/reference/glib/gvariant-varargs.xml @@ -263,7 +263,7 @@ <para> Used as a prefix for a GVariant type string (not a prefix for a format string, so <literal>&s</literal> is a valid format string but <literal>&@s</literal> is not). - Denotes that a C pointer to serialised data + Denotes that a C pointer to serialized data should be used in place of the normal C type. See <link linkend='gvariant-format-strings-pointers'>Pointers</link> below. </para> @@ -946,7 +946,7 @@ data = g_variant_new_parsed ("(%o, {'brightness': {'value': <%i>, 'max': <%i>}}) </para> <para> - The '<code>&</code>' character is used to indicate that serialised data should be directly exchanged via a + The '<code>&</code>' character is used to indicate that serialized data should be directly exchanged via a pointer. </para> <para> @@ -954,7 +954,7 @@ data = g_variant_new_parsed ("(%o, {'brightness': {'value': <%i>, 'max': <%i>}}) '<literal>&o</literal>' or '<code>&g</code>'). For <link linkend='g-variant-new'><function>g_variant_new()</function></link> this has absolutely no effect. The string is collected and duplicated normally. For <link linkend='g-variant-get'><function>g_variant_get()</function></link> - it means that instead of creating a newly allocated copy of the string, a pointer to the serialised data is + it means that instead of creating a newly allocated copy of the string, a pointer to the serialized data is returned. This pointer should not be freed. Validity checks are performed to ensure that the string data will always be properly nul-terminated. </para> diff --git a/docs/reference/glib/meson.build b/docs/reference/glib/meson.build index 43c273855..838a4f777 100644 --- a/docs/reference/glib/meson.build +++ b/docs/reference/glib/meson.build @@ -25,8 +25,6 @@ if get_option('gtk_doc') 'gtrace-private.h', 'glib-mirroring-tab', 'gnulib', - 'pcre', - 'update-pcre', 'gbytesprivate.h', 'gvariant-internal.h', 'gvariant-serialiser.h', diff --git a/docs/reference/glib/running.xml b/docs/reference/glib/running.xml index aaafddf1d..80a8da097 100644 --- a/docs/reference/glib/running.xml +++ b/docs/reference/glib/running.xml @@ -201,8 +201,11 @@ How to run and debug your GLib application reproduced with <literal>G_SLICE=always-malloc</literal>, but will be caught by <literal>G_SLICE=debug-blocks</literal> is as follows: <programlisting> - void *slist = g_slist_alloc (); /* void* gives up type-safety */ - g_list_free (slist); /* corruption: sizeof (GSList) != sizeof (GList) */ + /* void* gives up type-safety */ + void *slist = g_slist_alloc (); + + /* corruption: sizeof (GSList) != sizeof (GList) */ + g_list_free (slist); </programlisting></para> </listitem> </varlistentry> diff --git a/docs/reference/gobject/gobject-docs.xml b/docs/reference/gobject/gobject-docs.xml index ddbc9f274..e8e7c76d9 100644 --- a/docs/reference/gobject/gobject-docs.xml +++ b/docs/reference/gobject/gobject-docs.xml @@ -208,6 +208,10 @@ <title>Index of new symbols in 2.68</title> <xi:include href="xml/api-index-2.68.xml"><xi:fallback /></xi:include> </index> + <index id="api-index-2-70" role="2.70"> + <title>Index of new symbols in 2.70</title> + <xi:include href="xml/api-index-2.70.xml"><xi:fallback /></xi:include> + </index> <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include> diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt index 54fbccaf8..685529708 100644 --- a/docs/reference/gobject/gobject-sections.txt +++ b/docs/reference/gobject/gobject-sections.txt @@ -268,6 +268,7 @@ GParameter g_object_ref g_object_unref g_object_ref_sink +g_object_take_ref g_set_object g_clear_object GInitiallyUnowned @@ -411,6 +412,7 @@ G_TYPE_THREAD G_TYPE_OPTION_GROUP G_TYPE_URI G_TYPE_TREE +G_TYPE_PATTERN_SPEC <SUBSECTION Standard> G_TYPE_IS_BOXED @@ -446,6 +448,7 @@ g_thread_get_type g_option_group_get_type g_uri_get_type g_tree_get_type +g_pattern_spec_get_type </SECTION> <SECTION> diff --git a/docs/reference/meson.build b/docs/reference/meson.build index 3f09be555..53ca12ff8 100644 --- a/docs/reference/meson.build +++ b/docs/reference/meson.build @@ -7,7 +7,7 @@ stable_2_series_versions = [ '26', '28', '30', '32', '34', '36', '38', '40', '42', '44', '46', '48', '50', '52', '54', '56', '58', - '60', '62', '64', '66', '68', + '60', '62', '64', '66', '68', '70', ] ignore_decorators = [ diff --git a/fuzzing/README.md b/fuzzing/README.md index 16f5a05bc..21565e396 100644 --- a/fuzzing/README.md +++ b/fuzzing/README.md @@ -40,7 +40,7 @@ $ DIR/fuzzing/fuzz_target_name FILE Correct MSAN instrumentation is [difficult to achieve](https://clang.llvm.org/docs/MemorySanitizer.html#handling-external-code) locally, so false positives are very likely to mask the actual bug. -If need be, [you can still reproduce](https://github.com/google/oss-fuzz/blob/master/docs/reproducing.md#building-using-docker) those bugs with the oss-fuzz provided docker images. +If need be, [you can still reproduce](https://google.github.io/oss-fuzz/advanced-topics/reproducing/#building-using-docker) those bugs with the oss-fuzz provided docker images. ###### There are no file/function names in the stack trace. diff --git a/fuzzing/driver.c b/fuzzing/driver.c index f6d2396db..296ce5710 100644 --- a/fuzzing/driver.c +++ b/fuzzing/driver.c @@ -30,6 +30,7 @@ main (int argc, char **argv) LLVMFuzzerTestOneInput (buf, len); free (buf); + fclose (f); printf ("Done!\n"); return 0; } diff --git a/fuzzing/fuzz_canonicalize_filename.c b/fuzzing/fuzz_canonicalize_filename.c new file mode 100644 index 000000000..86b323ef9 --- /dev/null +++ b/fuzzing/fuzz_canonicalize_filename.c @@ -0,0 +1,19 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + unsigned char *nul_terminated_data = NULL; + gchar *canonicalized = NULL; + + fuzz_set_logging_func (); + + /* ignore @size (g_canonicalize_filename() doesn’t support it); ensure @data is nul-terminated */ + nul_terminated_data = (unsigned char *) g_strndup ((const gchar *) data, size); + canonicalized = g_canonicalize_filename ((const gchar *) nul_terminated_data, "/"); + g_free (nul_terminated_data); + + g_free (canonicalized); + + return 0; +} diff --git a/fuzzing/fuzz_paths.c b/fuzzing/fuzz_paths.c new file mode 100644 index 000000000..fbed84771 --- /dev/null +++ b/fuzzing/fuzz_paths.c @@ -0,0 +1,32 @@ +#include "fuzz.h" + +int +LLVMFuzzerTestOneInput (const unsigned char *data, size_t size) +{ + unsigned char *nul_terminated_data = NULL; + const gchar *skipped_root; + gchar *basename = NULL, *dirname = NULL; + + fuzz_set_logging_func (); + + /* ignore @size (none of the functions support it); ensure @data is nul-terminated */ + nul_terminated_data = (unsigned char *) g_strndup ((const gchar *) data, size); + + g_path_is_absolute ((const gchar *) nul_terminated_data); + + skipped_root = g_path_skip_root ((const gchar *) nul_terminated_data); + g_assert (skipped_root == NULL || skipped_root >= (const gchar *) nul_terminated_data); + g_assert (skipped_root == NULL || skipped_root <= (const gchar *) nul_terminated_data + size); + + basename = g_path_get_basename ((const gchar *) nul_terminated_data); + g_assert (strcmp (basename, ".") == 0 || strlen (basename) <= size); + + dirname = g_path_get_dirname ((const gchar *) nul_terminated_data); + g_assert (strcmp (dirname, ".") == 0 || strlen (dirname) <= size); + + g_free (nul_terminated_data); + g_free (dirname); + g_free (basename); + + return 0; +} diff --git a/fuzzing/meson.build b/fuzzing/meson.build index a40321200..c60dcf446 100644 --- a/fuzzing/meson.build +++ b/fuzzing/meson.build @@ -1,5 +1,6 @@ fuzz_targets = [ 'fuzz_bookmark', + 'fuzz_canonicalize_filename', 'fuzz_date_parse', 'fuzz_date_time_new_from_iso8601', 'fuzz_dbus_message', @@ -9,6 +10,7 @@ fuzz_targets = [ 'fuzz_key', 'fuzz_network_address_parse', 'fuzz_network_address_parse_uri', + 'fuzz_paths', 'fuzz_uri_escape', 'fuzz_uri_parse', 'fuzz_uri_parse_params', @@ -22,7 +24,7 @@ extra_sources = [] extra_c_args = cc.get_supported_arguments('-Werror=unused-function') # Links in a static library provided by oss-fuzz, else a standalone driver. -# https://github.com/google/oss-fuzz/blob/master/docs/new_project_guide.md#buildsh-script-environment +# https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh-script-environment fuzzing_engine = cxx.find_library('FuzzingEngine', required : get_option('oss_fuzz')) if fuzzing_engine.found() deps += fuzzing_engine diff --git a/gio/data-to-c.py b/gio/data-to-c.py index 1724f7dd1..8407fb4af 100755 --- a/gio/data-to-c.py +++ b/gio/data-to-c.py @@ -1,12 +1,13 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 import sys if len(sys.argv) < 4: print("Usage: {0} <filename> <variable> <output>") -with open(sys.argv[1], "rb") as f: - in_data = f.read().decode("utf-8", "backslashreplace") +with open(sys.argv[1], "r", encoding="utf-8", errors="backslashreplace") as f: + in_data = f.read() + b = [r"\x{:02x}".format(ord(c)) for c in in_data] out_data = 'const char {0}[] = "'.format(sys.argv[2]) diff --git a/gio/gapplication.c b/gio/gapplication.c index 3720146af..cbc467a92 100644 --- a/gio/gapplication.c +++ b/gio/gapplication.c @@ -155,13 +155,13 @@ * respectively. * * For an example of opening files with a GApplication, see - * [gapplication-example-open.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-open.c). + * [gapplication-example-open.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gapplication-example-open.c). * * For an example of using actions with GApplication, see - * [gapplication-example-actions.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-actions.c). + * [gapplication-example-actions.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gapplication-example-actions.c). * * For an example of using extra D-Bus hooks with GApplication, see - * [gapplication-example-dbushooks.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-dbushooks.c). + * [gapplication-example-dbushooks.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gapplication-example-dbushooks.c). */ /** @@ -543,7 +543,7 @@ g_application_parse_command_line (GApplication *application, GOptionEntry entries[] = { { "gapplication-service", '\0', 0, G_OPTION_ARG_NONE, &become_service, N_("Enter GApplication service mode (use from D-Bus service files)"), NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; g_option_group_add_entries (gapplication_group, entries); @@ -555,7 +555,7 @@ g_application_parse_command_line (GApplication *application, GOptionEntry entries[] = { { "gapplication-app-id", '\0', 0, G_OPTION_ARG_STRING, &app_id, N_("Override the application’s ID"), NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; g_option_group_add_entries (gapplication_group, entries); @@ -567,7 +567,7 @@ g_application_parse_command_line (GApplication *application, GOptionEntry entries[] = { { "gapplication-replace", '\0', 0, G_OPTION_ARG_NONE, &replace, N_("Replace the running instance"), NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; g_option_group_add_entries (gapplication_group, entries); @@ -729,7 +729,11 @@ g_application_add_main_option_entries (GApplication *application, for (i = 0; entries[i].long_name; i++) { - GOptionEntry my_entries[2] = { { NULL }, { NULL } }; + GOptionEntry my_entries[2] = + { + G_OPTION_ENTRY_NULL, + G_OPTION_ENTRY_NULL + }; my_entries[0] = entries[i]; if (!my_entries[0].arg_data) @@ -778,7 +782,7 @@ g_application_add_main_option (GApplication *application, gchar *dup_string; GOptionEntry my_entry[2] = { { NULL, short_name, flags, arg, NULL, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; g_return_if_fail (G_IS_APPLICATION (application)); @@ -2395,7 +2399,7 @@ g_application_open (GApplication *application, * and override local_command_line(). In this case, you most likely want * to return %TRUE from your local_command_line() implementation to * suppress the default handling. See - * [gapplication-example-cmdline2.c][gapplication-example-cmdline2] + * [gapplication-example-cmdline2.c][https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gapplication-example-cmdline2.c] * for an example. * * If, after the above is done, the use count of the application is zero @@ -2524,7 +2528,12 @@ g_application_run (GApplication *application, context = g_main_context_default (); acquired_context = g_main_context_acquire (context); - g_return_val_if_fail (acquired_context, 0); + if (!acquired_context) + { + g_critical ("g_application_run() cannot acquire the default main context because it is already acquired by another thread!"); + g_strfreev (arguments); + return 1; + } if (!G_APPLICATION_GET_CLASS (application) ->local_command_line (application, &arguments, &status)) @@ -2573,6 +2582,13 @@ g_application_run (GApplication *application, if (application->priv->impl) { + if (application->priv->is_registered) + { + application->priv->is_registered = FALSE; + + g_object_notify (G_OBJECT (application), "is-registered"); + } + g_application_impl_flush (application->priv->impl); g_application_impl_destroy (application->priv->impl); application->priv->impl = NULL; @@ -2816,6 +2832,8 @@ g_application_quit (GApplication *application) * * To cancel the busy indication, use g_application_unmark_busy(). * + * The application must be registered before calling this function. + * * Since: 2.38 **/ void @@ -2824,6 +2842,7 @@ g_application_mark_busy (GApplication *application) gboolean was_busy; g_return_if_fail (G_IS_APPLICATION (application)); + g_return_if_fail (application->priv->is_registered); was_busy = (application->priv->busy_count > 0); application->priv->busy_count++; diff --git a/gio/gapplicationcommandline.c b/gio/gapplicationcommandline.c index 7d3f0e665..741aa97f1 100644 --- a/gio/gapplicationcommandline.c +++ b/gio/gapplicationcommandline.c @@ -104,7 +104,7 @@ * } * ]| * The complete example can be found here: - * [gapplication-example-cmdline.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-cmdline.c) + * [gapplication-example-cmdline.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gapplication-example-cmdline.c) * * In more complicated cases, the handling of the comandline can be * split between the launcher and the primary instance. @@ -155,7 +155,7 @@ * instance. * * The complete example can be found here: - * [gapplication-example-cmdline2.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-cmdline2.c) + * [gapplication-example-cmdline2.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gapplication-example-cmdline2.c) * * If handling the commandline requires a lot of work, it may * be better to defer it. @@ -197,7 +197,7 @@ * hold the application until you are done with the commandline. * * The complete example can be found here: - * [gapplication-example-cmdline3.c](https://git.gnome.org/browse/glib/tree/gio/tests/gapplication-example-cmdline3.c) + * [gapplication-example-cmdline3.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gapplication-example-cmdline3.c) */ /** diff --git a/gio/gcredentials.h b/gio/gcredentials.h index 25cebf2b4..b61ab786b 100644 --- a/gio/gcredentials.h +++ b/gio/gcredentials.h @@ -82,4 +82,4 @@ gboolean g_credentials_set_unix_user (GCredentials *credentials, G_END_DECLS -#endif /* __G_DBUS_PROXY_H__ */ +#endif /* __G_CREDENTIALS_H__ */ diff --git a/gio/gdbus-tool.c b/gio/gdbus-tool.c index 1f9e308d5..f44253804 100644 --- a/gio/gdbus-tool.c +++ b/gio/gdbus-tool.c @@ -145,7 +145,7 @@ modify_argv0_for_command (gint *argc, gchar **argv[], const gchar *command) remove_arg (1, argc, argv); program_name = g_path_get_basename ((*argv)[0]); - s = g_strdup_printf ("%s %s", (*argv)[0], command); + s = g_strdup_printf ("%s %s", program_name, command); (*argv)[0] = s; g_free (program_name); } @@ -403,7 +403,7 @@ static const GOptionEntry connection_entries[] = { "system", 'y', 0, G_OPTION_ARG_NONE, &opt_connection_system, N_("Connect to the system bus"), NULL}, { "session", 'e', 0, G_OPTION_ARG_NONE, &opt_connection_session, N_("Connect to the session bus"), NULL}, { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_connection_address, N_("Connect to given D-Bus address"), NULL}, - { NULL } + G_OPTION_ENTRY_NULL }; static GOptionGroup * @@ -593,7 +593,7 @@ static const GOptionEntry emit_entries[] = { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_emit_dest, N_("Optional destination for signal (unique name)"), NULL}, { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_emit_object_path, N_("Object path to emit signal on"), NULL}, { "signal", 's', 0, G_OPTION_ARG_STRING, &opt_emit_signal, N_("Signal and interface name"), NULL}, - { NULL } + G_OPTION_ENTRY_NULL }; static gboolean @@ -894,7 +894,7 @@ static const GOptionEntry call_entries[] = { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_call_object_path, N_("Object path to invoke method on"), NULL}, { "method", 'm', 0, G_OPTION_ARG_STRING, &opt_call_method, N_("Method and interface name"), NULL}, { "timeout", 't', 0, G_OPTION_ARG_INT, &opt_call_timeout, N_("Timeout in seconds"), NULL}, - { NULL } + G_OPTION_ENTRY_NULL }; static gboolean @@ -1688,7 +1688,7 @@ static const GOptionEntry introspect_entries[] = { "xml", 'x', 0, G_OPTION_ARG_NONE, &opt_introspect_xml, N_("Print XML"), NULL}, { "recurse", 'r', 0, G_OPTION_ARG_NONE, &opt_introspect_recurse, N_("Introspect children"), NULL}, { "only-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_introspect_only_properties, N_("Only print properties"), NULL}, - { NULL } + G_OPTION_ENTRY_NULL }; static gboolean @@ -1984,7 +1984,7 @@ static const GOptionEntry monitor_entries[] = { { "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_monitor_dest, N_("Destination name to monitor"), NULL}, { "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_monitor_object_path, N_("Object path to monitor"), NULL}, - { NULL } + G_OPTION_ENTRY_NULL }; static gboolean @@ -2195,7 +2195,7 @@ static const GOptionEntry wait_entries[] = { "timeout", 't', 0, G_OPTION_ARG_INT64, &opt_wait_timeout_secs, N_("Timeout to wait for before exiting with an error (seconds); 0 for " "no timeout (default)"), "SECS" }, - { NULL } + G_OPTION_ENTRY_NULL }; static void diff --git a/gio/gdbusaddress.c b/gio/gdbusaddress.c index a341023df..f873be282 100644 --- a/gio/gdbusaddress.c +++ b/gio/gdbusaddress.c @@ -1082,7 +1082,7 @@ get_session_address_dbus_launch (GError **error) gchar *command_line; gchar *launch_stdout; gchar *launch_stderr; - gint exit_status; + gint wait_status; gchar *old_dbus_verbose; gboolean restore_dbus_verbose; @@ -1146,13 +1146,13 @@ get_session_address_dbus_launch (GError **error) if (!g_spawn_command_line_sync (command_line, &launch_stdout, &launch_stderr, - &exit_status, + &wait_status, error)) { goto out; } - if (!g_spawn_check_exit_status (exit_status, error)) + if (!g_spawn_check_wait_status (wait_status, error)) { g_prefix_error (error, _("Error spawning command line “%s”: "), command_line); goto out; diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c index c430f0cf0..74c178dbf 100644 --- a/gio/gdbusauth.c +++ b/gio/gdbusauth.c @@ -960,7 +960,7 @@ _g_dbus_auth_run_server (GDBusAuth *auth, g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "The given guid '%s' is not valid", + "The given GUID '%s' is not valid", guid); goto out; } @@ -1007,6 +1007,7 @@ _g_dbus_auth_run_server (GDBusAuth *auth, g_propagate_error (error, local_error); goto out; } + g_clear_error (&local_error); } else { diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c index a37611275..8ce70a93d 100644 --- a/gio/gdbusconnection.c +++ b/gio/gdbusconnection.c @@ -166,22 +166,22 @@ * ## An example D-Bus server # {#gdbus-server} * * Here is an example for a D-Bus server: - * [gdbus-example-server.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-server.c) + * [gdbus-example-server.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-server.c) * * ## An example for exporting a subtree # {#gdbus-subtree-server} * * Here is an example for exporting a subtree: - * [gdbus-example-subtree.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-subtree.c) + * [gdbus-example-subtree.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-subtree.c) * * ## An example for file descriptor passing # {#gdbus-unix-fd-client} * * Here is an example for passing UNIX file descriptors: - * [gdbus-unix-fd-client.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-unix-fd-client.c) + * [gdbus-unix-fd-client.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-unix-fd-client.c) * * ## An example for exporting a GObject # {#gdbus-export} * * Here is an example for exporting a #GObject: - * [gdbus-example-export.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-export.c) + * [gdbus-example-export.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-export.c) */ /* ---------------------------------------------------------------------------------------------------- */ @@ -386,7 +386,7 @@ struct _GDBusConnection */ gchar *bus_unique_name; - /* The GUID returned by the other side if we authenticed as a client or + /* The GUID returned by the other side if we authenticated as a client or * the GUID to use if authenticating as a server. * Read-only after initable_init(), so it may be read if you either * hold @init_lock or check for initialization first. @@ -902,6 +902,15 @@ g_dbus_connection_class_init (GDBusConnectionClass *klass) * of the other peer here after the connection has been successfully * initialized. * + * Note that the + * [D-Bus specification](https://dbus.freedesktop.org/doc/dbus-specification.html#addresses) + * uses the term ‘UUID’ to refer to this, whereas GLib consistently uses the + * term ‘GUID’ for historical reasons. + * + * Despite its name, the format of #GDBusConnection:guid does not follow + * [RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122) or the Microsoft + * GUID format. + * * Since: 2.26 */ g_object_class_install_property (gobject_class, @@ -1610,7 +1619,6 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection, guchar *blob; gsize blob_size; guint32 serial_to_use; - gboolean ret; CONNECTION_ENSURE_LOCK (connection); @@ -1619,9 +1627,6 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection, /* TODO: check all necessary headers are present */ - ret = FALSE; - blob = NULL; - if (out_serial != NULL) *out_serial = 0; @@ -1633,14 +1638,14 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection, if (!check_unclosed (connection, (flags & SEND_MESSAGE_FLAGS_INITIALIZING) ? MAY_BE_UNINITIALIZED : 0, error)) - goto out; + return FALSE; blob = g_dbus_message_to_blob (message, &blob_size, connection->capabilities, error); if (blob == NULL) - goto out; + return FALSE; if (flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL) serial_to_use = g_dbus_message_get_serial (message); @@ -1686,18 +1691,13 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection, g_dbus_message_set_serial (message, serial_to_use); g_dbus_message_lock (message); + _g_dbus_worker_send_message (connection->worker, message, - (gchar*) blob, + (gchar*) blob, /* transfer ownership */ blob_size); - blob = NULL; /* since _g_dbus_worker_send_message() steals the blob */ - - ret = TRUE; - out: - g_free (blob); - - return ret; + return TRUE; } /** @@ -2202,6 +2202,24 @@ typedef struct GMainContext *context; } FilterData; +static void +filter_data_destroy (FilterData *filter, gboolean notify_sync) +{ + if (notify_sync) + { + if (filter->user_data_free_func != NULL) + filter->user_data_free_func (filter->user_data); + } + else + { + call_destroy_notify (filter->context, + filter->user_data_free_func, + filter->user_data); + } + g_main_context_unref (filter->context); + g_free (filter); +} + /* requires CONNECTION_LOCK */ static FilterData ** copy_filter_list (GPtrArray *filters) @@ -2230,13 +2248,7 @@ free_filter_list (FilterData **filters) { filters[n]->ref_count--; if (filters[n]->ref_count == 0) - { - call_destroy_notify (filters[n]->context, - filters[n]->user_data_free_func, - filters[n]->user_data); - g_main_context_unref (filters[n]->context); - g_free (filters[n]); - } + filter_data_destroy (filters[n], FALSE); } g_free (filters); } @@ -3179,16 +3191,9 @@ static void purge_all_filters (GDBusConnection *connection) { guint n; - for (n = 0; n < connection->filters->len; n++) - { - FilterData *data = connection->filters->pdata[n]; - call_destroy_notify (data->context, - data->user_data_free_func, - data->user_data); - g_main_context_unref (data->context); - g_free (data); - } + for (n = 0; n < connection->filters->len; n++) + filter_data_destroy (connection->filters->pdata[n], FALSE); } /** @@ -3238,12 +3243,7 @@ g_dbus_connection_remove_filter (GDBusConnection *connection, /* do free without holding lock */ if (to_destroy != NULL) - { - if (to_destroy->user_data_free_func != NULL) - to_destroy->user_data_free_func (to_destroy->user_data); - g_main_context_unref (to_destroy->context); - g_free (to_destroy); - } + filter_data_destroy (to_destroy, TRUE); else if (!found) { g_warning ("g_dbus_connection_remove_filter: No filter found for filter_id %d", filter_id); @@ -3724,6 +3724,9 @@ unsubscribe_id_internal (GDBusConnection *connection, * g_dbus_connection_signal_subscribe() is called, in order to avoid memory * leaks through callbacks queued on the #GMainContext after it’s stopped being * iterated. + * Alternatively, any idle source with a priority lower than %G_PRIORITY_DEFAULT + * that was scheduled after unsubscription, also indicates that all resources + * of this subscription are released. * * Since: 2.26 */ @@ -5058,7 +5061,8 @@ validate_and_maybe_schedule_method_call (GDBusConnection *connection, static gboolean obj_message_func (GDBusConnection *connection, ExportedObject *eo, - GDBusMessage *message) + GDBusMessage *message, + gboolean *object_found) { const gchar *interface_name; const gchar *member; @@ -5094,6 +5098,10 @@ obj_message_func (GDBusConnection *connection, ei->user_data); goto out; } + else + { + *object_found = TRUE; + } } if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Introspectable") == 0 && @@ -7119,6 +7127,7 @@ distribute_method_call (GDBusConnection *connection, const gchar *path; gchar *subtree_path; gchar *needle; + gboolean object_found = FALSE; g_assert (g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL); @@ -7160,7 +7169,7 @@ distribute_method_call (GDBusConnection *connection, eo = g_hash_table_lookup (connection->map_object_path_to_eo, object_path); if (eo != NULL) { - if (obj_message_func (connection, eo, message)) + if (obj_message_func (connection, eo, message, &object_found)) goto out; } @@ -7185,11 +7194,22 @@ distribute_method_call (GDBusConnection *connection, goto out; /* if we end up here, the message has not been not handled - so return an error saying this */ - reply = g_dbus_message_new_method_error (message, + if (object_found == TRUE) + { + reply = g_dbus_message_new_method_error (message, + "org.freedesktop.DBus.Error.UnknownMethod", + _("No such interface “%s” on object at path %s"), + interface_name, + object_path); + } + else + { + reply = g_dbus_message_new_method_error (message, "org.freedesktop.DBus.Error.UnknownMethod", - _("No such interface “%s” on object at path %s"), - interface_name, + _("Object does not exist at path “%s”"), object_path); + } + g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (reply); diff --git a/gio/gdbusintrospection.c b/gio/gdbusintrospection.c index f35b2fb44..d6aa445d5 100644 --- a/gio/gdbusintrospection.c +++ b/gio/gdbusintrospection.c @@ -98,7 +98,7 @@ typedef struct * If @info is statically allocated does nothing. Otherwise increases * the reference count. * - * Returns: The same @info. + * Returns: (not nullable): The same @info. * * Since: 2.26 */ @@ -118,7 +118,7 @@ g_dbus_node_info_ref (GDBusNodeInfo *info) * If @info is statically allocated does nothing. Otherwise increases * the reference count. * - * Returns: The same @info. + * Returns: (not nullable): The same @info. * * Since: 2.26 */ @@ -138,7 +138,7 @@ g_dbus_interface_info_ref (GDBusInterfaceInfo *info) * If @info is statically allocated does nothing. Otherwise increases * the reference count. * - * Returns: The same @info. + * Returns: (not nullable): The same @info. * * Since: 2.26 */ @@ -158,7 +158,7 @@ g_dbus_method_info_ref (GDBusMethodInfo *info) * If @info is statically allocated does nothing. Otherwise increases * the reference count. * - * Returns: The same @info. + * Returns: (not nullable): The same @info. * * Since: 2.26 */ @@ -178,7 +178,7 @@ g_dbus_signal_info_ref (GDBusSignalInfo *info) * If @info is statically allocated does nothing. Otherwise increases * the reference count. * - * Returns: The same @info. + * Returns: (not nullable): The same @info. * * Since: 2.26 */ @@ -198,7 +198,7 @@ g_dbus_property_info_ref (GDBusPropertyInfo *info) * If @info is statically allocated does nothing. Otherwise increases * the reference count. * - * Returns: The same @info. + * Returns: (not nullable): The same @info. * * Since: 2.26 */ @@ -218,7 +218,7 @@ g_dbus_arg_info_ref (GDBusArgInfo *info) * If @info is statically allocated does nothing. Otherwise increases * the reference count. * - * Returns: The same @info. + * Returns: (not nullable): The same @info. * * Since: 2.26 */ diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c index bc9386ee7..cdc0b83e8 100644 --- a/gio/gdbusmessage.c +++ b/gio/gdbusmessage.c @@ -3204,7 +3204,7 @@ g_dbus_message_set_error_name (GDBusMessage *message, const gchar *value) { g_return_if_fail (G_IS_DBUS_MESSAGE (message)); - g_return_if_fail (value == NULL || g_dbus_is_interface_name (value)); + g_return_if_fail (value == NULL || g_dbus_is_error_name (value)); set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value); } @@ -3216,7 +3216,9 @@ g_dbus_message_set_error_name (GDBusMessage *message, * * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field. * - * Returns: The value. + * This will always be non-%NULL, but may be an empty string. + * + * Returns: (not nullable): The value. * * Since: 2.26 */ @@ -3488,7 +3490,7 @@ _sort_keys_func (gconstpointer a, * fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635 * ]| * - * Returns: A string that should be freed with g_free(). + * Returns: (not nullable): A string that should be freed with g_free(). * * Since: 2.26 */ diff --git a/gio/gdbusnameowning.c b/gio/gdbusnameowning.c index 1130d6789..328354be4 100644 --- a/gio/gdbusnameowning.c +++ b/gio/gdbusnameowning.c @@ -39,7 +39,7 @@ * Convenience API for owning bus names. * * A simple example for owning a name can be found in - * [gdbus-example-own-name.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-own-name.c) + * [gdbus-example-own-name.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-own-name.c) */ G_LOCK_DEFINE_STATIC (lock); diff --git a/gio/gdbusnamewatching.c b/gio/gdbusnamewatching.c index 8d24700c5..40aee5a3c 100644 --- a/gio/gdbusnamewatching.c +++ b/gio/gdbusnamewatching.c @@ -40,7 +40,7 @@ * Convenience API for watching bus names. * * A simple example for watching a name can be found in - * [gdbus-example-watch-name.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-watch-name.c) + * [gdbus-example-watch-name.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-watch-name.c) */ G_LOCK_DEFINE_STATIC (lock); diff --git a/gio/gdbusobjectmanager.c b/gio/gdbusobjectmanager.c index 87634cd83..169e7d16f 100644 --- a/gio/gdbusobjectmanager.c +++ b/gio/gdbusobjectmanager.c @@ -213,7 +213,7 @@ g_dbus_object_manager_get_objects (GDBusObjectManager *manager) * * Gets the #GDBusObjectProxy at @object_path, if any. * - * Returns: (transfer full): A #GDBusObject or %NULL. Free with + * Returns: (transfer full) (nullable): A #GDBusObject or %NULL. Free with * g_object_unref(). * * Since: 2.30 @@ -236,7 +236,7 @@ g_dbus_object_manager_get_object (GDBusObjectManager *manager, * Gets the interface proxy for @interface_name at @object_path, if * any. * - * Returns: (transfer full): A #GDBusInterface instance or %NULL. Free + * Returns: (transfer full) (nullable): A #GDBusInterface instance or %NULL. Free * with g_object_unref(). * * Since: 2.30 diff --git a/gio/gdbusobjectmanagerclient.c b/gio/gdbusobjectmanagerclient.c index 88fcff4fa..04c55995d 100644 --- a/gio/gdbusobjectmanagerclient.c +++ b/gio/gdbusobjectmanagerclient.c @@ -20,11 +20,13 @@ #include "config.h" +#include "gcancellable.h" #include "gdbusobjectmanager.h" #include "gdbusobjectmanagerclient.h" #include "gdbusobject.h" #include "gdbusprivate.h" #include "gioenumtypes.h" +#include "gioerror.h" #include "ginitable.h" #include "gasyncresult.h" #include "gasyncinitable.h" @@ -144,6 +146,7 @@ struct _GDBusObjectManagerClientPrivate gulong name_owner_signal_id; gulong signal_signal_id; + GCancellable *cancel; }; enum @@ -192,6 +195,20 @@ static void process_get_all_result (GDBusObjectManagerClient *manager, const gchar *name_owner); static void +g_dbus_object_manager_client_dispose (GObject *object) +{ + GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (object); + + if (manager->priv->cancel != NULL) + { + g_cancellable_cancel (manager->priv->cancel); + g_clear_object (&manager->priv->cancel); + } + + G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->dispose (object); +} + +static void g_dbus_object_manager_client_finalize (GObject *object) { GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (object); @@ -327,6 +344,7 @@ g_dbus_object_manager_client_class_init (GDBusObjectManagerClientClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + gobject_class->dispose = g_dbus_object_manager_client_dispose; gobject_class->finalize = g_dbus_object_manager_client_finalize; gobject_class->set_property = g_dbus_object_manager_client_set_property; gobject_class->get_property = g_dbus_object_manager_client_get_property; @@ -589,6 +607,7 @@ g_dbus_object_manager_client_init (GDBusObjectManagerClient *manager) g_str_equal, g_free, (GDestroyNotify) g_object_unref); + manager->priv->cancel = g_cancellable_new (); } /* ---------------------------------------------------------------------------------------------------- */ @@ -1244,6 +1263,75 @@ maybe_unsubscribe_signals (GDBusObjectManagerClient *manager) /* ---------------------------------------------------------------------------------------------------- */ +static GWeakRef * +weak_ref_new (GObject *object) +{ + GWeakRef *weak_ref = g_new0 (GWeakRef, 1); + g_weak_ref_init (weak_ref, object); + return g_steal_pointer (&weak_ref); +} + +static void +weak_ref_free (GWeakRef *weak_ref) +{ + g_weak_ref_clear (weak_ref); + g_free (weak_ref); +} + +static void +on_get_managed_objects_finish (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + + GDBusProxy *proxy = G_DBUS_PROXY (source); + GWeakRef *manager_weak = user_data; + GDBusObjectManagerClient *manager; + GError *error = NULL; + GVariant *value = NULL; + gchar *new_name_owner = NULL; + + value = g_dbus_proxy_call_finish (proxy, result, &error); + + manager = G_DBUS_OBJECT_MANAGER_CLIENT (g_weak_ref_get (manager_weak)); + /* Manager got disposed, nothing to do */ + if (manager == NULL) + { + goto out; + } + + new_name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy); + if (value == NULL) + { + maybe_unsubscribe_signals (manager); + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + { + g_warning ("Error calling GetManagedObjects() when name owner %s for name %s came back: %s", + new_name_owner, + manager->priv->name, + error->message); + } + } + else + { + process_get_all_result (manager, value, new_name_owner); + } + + /* do the :name-owner notify *AFTER* emitting ::object-proxy-added signals - this + * way the user knows that the signals were emitted because the name owner came back + */ + g_mutex_lock (&manager->priv->lock); + manager->priv->name_owner = g_steal_pointer (&new_name_owner); + g_mutex_unlock (&manager->priv->lock); + g_object_notify (G_OBJECT (manager), "name-owner"); + + g_object_unref (manager); + out: + g_clear_error (&error); + g_clear_pointer (&value, g_variant_unref); + weak_ref_free (manager_weak); +} + static void on_notify_g_name_owner (GObject *object, GParamSpec *pspec, @@ -1298,65 +1386,24 @@ on_notify_g_name_owner (GObject *object, if (new_name_owner != NULL) { - GError *error; - GVariant *value; - //g_debug ("repopulating for %s", new_name_owner); - /* TODO: do this async! */ subscribe_signals (manager, new_name_owner); - error = NULL; - value = g_dbus_proxy_call_sync (manager->priv->control_proxy, - "GetManagedObjects", - NULL, /* parameters */ - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error); - if (value == NULL) - { - maybe_unsubscribe_signals (manager); - g_warning ("Error calling GetManagedObjects() when name owner %s for name %s came back: %s", - new_name_owner, - manager->priv->name, - error->message); - g_error_free (error); - } - else - { - process_get_all_result (manager, value, new_name_owner); - g_variant_unref (value); - } - - /* do the :name-owner notify *AFTER* emitting ::object-proxy-added signals - this - * way the user knows that the signals were emitted because the name owner came back - */ - g_mutex_lock (&manager->priv->lock); - manager->priv->name_owner = new_name_owner; - g_mutex_unlock (&manager->priv->lock); - g_object_notify (G_OBJECT (manager), "name-owner"); - + g_dbus_proxy_call (manager->priv->control_proxy, + "GetManagedObjects", + NULL, /* parameters */ + G_DBUS_CALL_FLAGS_NONE, + -1, + manager->priv->cancel, + on_get_managed_objects_finish, + weak_ref_new (G_OBJECT (manager))); } + g_free (new_name_owner); g_free (old_name_owner); g_object_unref (manager); } -static GWeakRef * -weak_ref_new (GObject *object) -{ - GWeakRef *weak_ref = g_new0 (GWeakRef, 1); - g_weak_ref_init (weak_ref, object); - return g_steal_pointer (&weak_ref); -} - -static void -weak_ref_free (GWeakRef *weak_ref) -{ - g_weak_ref_clear (weak_ref); - g_free (weak_ref); -} - static gboolean initable_init (GInitable *initable, GCancellable *cancellable, diff --git a/gio/gdbusobjectmanagerserver.c b/gio/gdbusobjectmanagerserver.c index 39f4ed500..a68594765 100644 --- a/gio/gdbusobjectmanagerserver.c +++ b/gio/gdbusobjectmanagerserver.c @@ -318,7 +318,7 @@ g_dbus_object_manager_server_set_connection (GDBusObjectManagerServer *manager, * * Gets the #GDBusConnection used by @manager. * - * Returns: (transfer full): A #GDBusConnection object or %NULL if + * Returns: (transfer full) (nullable): A #GDBusConnection object or %NULL if * @manager isn't exported on a connection. The returned object should * be freed with g_object_unref(). * @@ -565,12 +565,12 @@ void g_dbus_object_manager_server_export_uniquely (GDBusObjectManagerServer *manager, GDBusObjectSkeleton *object) { - gchar *orig_object_path; + const gchar *orig_object_path; gchar *object_path; guint count; gboolean modified; - orig_object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (object))); + orig_object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object)); g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_SERVER (manager)); g_return_if_fail (G_IS_DBUS_OBJECT (object)); @@ -602,7 +602,6 @@ g_dbus_object_manager_server_export_uniquely (GDBusObjectManagerServer *manager, g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (object), object_path); g_free (object_path); - g_free (orig_object_path); } diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c index 282678f3b..7e62fa89e 100644 --- a/gio/gdbusprivate.c +++ b/gio/gdbusprivate.c @@ -2292,7 +2292,7 @@ turn_off_the_starting_cursor (void) } } -__declspec(dllexport) void __stdcall +void __stdcall g_win32_run_session_bus (void* hwnd, void* hinst, const char* cmdline, int cmdshow) { GDBusDaemon *daemon; diff --git a/gio/gdbusprivate.h b/gio/gdbusprivate.h index 8f8a93ba7..72d2c32a9 100644 --- a/gio/gdbusprivate.h +++ b/gio/gdbusprivate.h @@ -117,7 +117,7 @@ gchar *_g_dbus_win32_get_user_sid (void); * Initially this function was introduces for usage with rundll, * so the signature is kept rundll-compatible, though parameters aren't used. */ -__declspec(dllexport) void __stdcall +_GLIB_EXTERN void __stdcall g_win32_run_session_bus (void* hwnd, void* hinst, const char* cmdline, int cmdshow); gchar *_g_dbus_win32_get_session_address_dbus_launch (GError **error); #endif diff --git a/gio/gdbusproxy.c b/gio/gdbusproxy.c index 45fa99a17..7a2289bd4 100644 --- a/gio/gdbusproxy.c +++ b/gio/gdbusproxy.c @@ -71,6 +71,13 @@ * the message bus launching an owner (unless * %G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START is set). * + * If the proxy is for a stateless D-Bus service, where the name owner may + * be started and stopped between calls, the #GDBusProxy:g-name-owner tracking + * of #GDBusProxy will cause the proxy to drop signal and property changes from + * the service after it has restarted for the first time. When interacting + * with a stateless D-Bus service, do not use #GDBusProxy — use direct D-Bus + * method calls and signal connections. + * * The generic #GDBusProxy::g-properties-changed and * #GDBusProxy::g-signal signals are not very convenient to work with. * Therefore, the recommended way of working with proxies is to subclass @@ -85,7 +92,7 @@ * of the thread where the instance was constructed. * * An example using a proxy for a well-known name can be found in - * [gdbus-example-watch-proxy.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-watch-proxy.c) + * [gdbus-example-watch-proxy.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-watch-proxy.c) */ /* lock protecting the mutable properties: name_owner, timeout_msec, @@ -2239,7 +2246,7 @@ g_dbus_proxy_new_for_bus_sync (GBusType bus_type, * * Gets the connection @proxy is for. * - * Returns: (transfer none): A #GDBusConnection owned by @proxy. Do not free. + * Returns: (transfer none) (not nullable): A #GDBusConnection owned by @proxy. Do not free. * * Since: 2.26 */ @@ -2273,7 +2280,11 @@ g_dbus_proxy_get_flags (GDBusProxy *proxy) * * Gets the name that @proxy was constructed for. * - * Returns: A string owned by @proxy. Do not free. + * When connected to a message bus, this will usually be non-%NULL. + * However, it may be %NULL for a proxy that communicates using a peer-to-peer + * pattern. + * + * Returns: (nullable): A string owned by @proxy. Do not free. * * Since: 2.26 */ @@ -2317,7 +2328,7 @@ g_dbus_proxy_get_name_owner (GDBusProxy *proxy) * * Gets the object path @proxy is for. * - * Returns: A string owned by @proxy. Do not free. + * Returns: (not nullable): A string owned by @proxy. Do not free. * * Since: 2.26 */ @@ -2334,7 +2345,7 @@ g_dbus_proxy_get_object_path (GDBusProxy *proxy) * * Gets the D-Bus interface name @proxy is for. * - * Returns: A string owned by @proxy. Do not free. + * Returns: (not nullable): A string owned by @proxy. Do not free. * * Since: 2.26 */ diff --git a/gio/gdbusserver.c b/gio/gdbusserver.c index 3cf98587b..3fdded58a 100644 --- a/gio/gdbusserver.c +++ b/gio/gdbusserver.c @@ -77,7 +77,7 @@ * session or system bus, you should instead use g_bus_own_name(). * * An example of peer-to-peer communication with GDBus can be found - * in [gdbus-example-peer.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-peer.c). + * in [gdbus-example-peer.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-example-peer.c). * * Note that a minimal #GDBusServer will accept connections from any * peer. In many use-cases it will be necessary to add a #GDBusAuthObserver @@ -320,7 +320,9 @@ g_dbus_server_class_init (GDBusServerClass *klass) /** * GDBusServer:guid: * - * The guid of the server. + * The GUID of the server. + * + * See #GDBusConnection:guid for more details. * * Since: 2.26 */ @@ -542,7 +544,9 @@ g_dbus_server_new_sync (const gchar *address, * [D-Bus address](https://dbus.freedesktop.org/doc/dbus-specification.html#addresses) * string that can be used by clients to connect to @server. * - * Returns: A D-Bus address string. Do not free, the string is owned + * This is valid and non-empty if initializing the #GDBusServer succeeded. + * + * Returns: (not nullable): A D-Bus address string. Do not free, the string is owned * by @server. * * Since: 2.26 @@ -558,9 +562,9 @@ g_dbus_server_get_client_address (GDBusServer *server) * g_dbus_server_get_guid: * @server: A #GDBusServer. * - * Gets the GUID for @server. + * Gets the GUID for @server, as provided to g_dbus_server_new_sync(). * - * Returns: A D-Bus GUID. Do not free this string, it is owned by @server. + * Returns: (not nullable): A D-Bus GUID. Do not free this string, it is owned by @server. * * Since: 2.26 */ diff --git a/gio/gdbusutils.c b/gio/gdbusutils.c index bb34e2d58..f12e86204 100644 --- a/gio/gdbusutils.c +++ b/gio/gdbusutils.c @@ -268,6 +268,28 @@ g_dbus_is_interface_name (const gchar *string) return ret; } +/** + * g_dbus_is_error_name: + * @string: The string to check. + * + * Check whether @string is a valid D-Bus error name. + * + * This function returns the same result as g_dbus_is_interface_name(), + * because D-Bus error names are defined to have exactly the + * same syntax as interface names. + * + * Returns: %TRUE if valid, %FALSE otherwise. + * + * Since: 2.70 + */ +gboolean +g_dbus_is_error_name (const gchar *string) +{ + /* Error names are the same syntax as interface names. + * See https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-error */ + return g_dbus_is_interface_name (string); +} + /* ---------------------------------------------------------------------------------------------------- */ /* TODO: maybe move to glib? if so, it should conform to http://en.wikipedia.org/wiki/Guid and/or @@ -280,8 +302,14 @@ g_dbus_is_interface_name (const gchar *string) * Generate a D-Bus GUID that can be used with * e.g. g_dbus_connection_new(). * - * See the D-Bus specification regarding what strings are valid D-Bus - * GUID (for example, D-Bus GUIDs are not RFC-4122 compliant). + * See the + * [D-Bus specification](https://dbus.freedesktop.org/doc/dbus-specification.html#uuids) + * regarding what strings are valid D-Bus GUIDs. The specification refers to + * these as ‘UUIDs’ whereas GLib (for historical reasons) refers to them as + * ‘GUIDs’. The terms are interchangeable. + * + * Note that D-Bus GUIDs do not follow + * [RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122). * * Returns: A valid D-Bus GUID. Free with g_free(). * @@ -317,10 +345,10 @@ g_dbus_generate_guid (void) * * Checks if @string is a D-Bus GUID. * - * See the D-Bus specification regarding what strings are valid D-Bus - * GUID (for example, D-Bus GUIDs are not RFC-4122 compliant). + * See the documentation for g_dbus_generate_guid() for more information about + * the format of a GUID. * - * Returns: %TRUE if @string is a guid, %FALSE otherwise. + * Returns: %TRUE if @string is a GUID, %FALSE otherwise. * * Since: 2.26 */ diff --git a/gio/gdbusutils.h b/gio/gdbusutils.h index fd7358fcf..da8e42280 100644 --- a/gio/gdbusutils.h +++ b/gio/gdbusutils.h @@ -42,6 +42,8 @@ GLIB_AVAILABLE_IN_ALL gboolean g_dbus_is_member_name (const gchar *string); GLIB_AVAILABLE_IN_ALL gboolean g_dbus_is_interface_name (const gchar *string); +GLIB_AVAILABLE_IN_2_70 +gboolean g_dbus_is_error_name (const gchar *string); GLIB_AVAILABLE_IN_ALL void g_dbus_gvariant_to_gvalue (GVariant *value, diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c index 1a4b97918..63ef0c045 100644 --- a/gio/gdesktopappinfo.c +++ b/gio/gdesktopappinfo.c @@ -3734,7 +3734,7 @@ update_program_done (GPid pid, gpointer data) { /* Did the application exit correctly */ - if (g_spawn_check_exit_status (status, NULL)) + if (g_spawn_check_wait_status (status, NULL)) { /* Here we could clean out any caches in use */ } diff --git a/gio/gdtlsconnection.c b/gio/gdtlsconnection.c index 4bbc88d7a..880d87d2c 100644 --- a/gio/gdtlsconnection.c +++ b/gio/gdtlsconnection.c @@ -88,6 +88,8 @@ enum { PROP_CERTIFICATE, PROP_PEER_CERTIFICATE, PROP_PEER_CERTIFICATE_ERRORS, + PROP_PROTOCOL_VERSION, + PROP_CIPHERSUITE_NAME, }; static void @@ -264,6 +266,37 @@ g_dtls_connection_default_init (GDtlsConnectionInterface *iface) G_PARAM_STATIC_STRINGS)); /** + * GDtlsConnection:protocol-version: + * + * The DTLS protocol version in use. See g_dtls_connection_get_protocol_version(). + * + * Since: 2.70 + */ + g_object_interface_install_property (iface, + g_param_spec_enum ("protocol-version", + P_("Protocol Version"), + P_("DTLS protocol version negotiated for this connection"), + G_TYPE_TLS_PROTOCOL_VERSION, + G_TLS_PROTOCOL_VERSION_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * GDtlsConnection:ciphersuite-name: (nullable) + * + * The name of the DTLS ciphersuite in use. See g_dtls_connection_get_ciphersuite_name(). + * + * Since: 2.70 + */ + g_object_interface_install_property (iface, + g_param_spec_string ("ciphersuite-name", + P_("Ciphersuite Name"), + P_("Name of ciphersuite negotiated for this connection"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** * GDtlsConnection::accept-certificate: * @conn: a #GDtlsConnection * @peer_cert: the peer's #GTlsCertificate @@ -1069,7 +1102,7 @@ g_dtls_connection_get_negotiated_protocol (GDtlsConnection *conn) GDtlsConnectionInterface *iface; iface = G_DTLS_CONNECTION_GET_INTERFACE (conn); - if (iface->set_advertised_protocols == NULL) + if (iface->get_negotiated_protocol == NULL) return NULL; return iface->get_negotiated_protocol (conn); @@ -1123,3 +1156,66 @@ g_dtls_connection_get_channel_binding_data (GDtlsConnection *conn, return iface->get_binding_data (conn, type, data, error); } + +/** + * g_dtls_connection_get_protocol_version: + * @conn: a #GDTlsConnection + * + * Returns the current DTLS protocol version, which may be + * %G_TLS_PROTOCOL_VERSION_UNKNOWN if the connection has not handshaked, or + * has been closed, or if the TLS backend has implemented a protocol version + * that is not a recognized #GTlsProtocolVersion. + * + * Returns: The current DTLS protocol version + * + * Since: 2.70 + */ +GTlsProtocolVersion +g_dtls_connection_get_protocol_version (GDtlsConnection *conn) +{ + GTlsProtocolVersion protocol_version; + GEnumClass *enum_class; + GEnumValue *enum_value; + + g_return_val_if_fail (G_IS_DTLS_CONNECTION (conn), G_TLS_PROTOCOL_VERSION_UNKNOWN); + + g_object_get (G_OBJECT (conn), + "protocol-version", &protocol_version, + NULL); + + /* Convert unknown values to G_TLS_PROTOCOL_VERSION_UNKNOWN. */ + enum_class = g_type_class_peek_static (G_TYPE_TLS_PROTOCOL_VERSION); + enum_value = g_enum_get_value (enum_class, protocol_version); + return enum_value ? protocol_version : G_TLS_PROTOCOL_VERSION_UNKNOWN; +} + +/** + * g_dtls_connection_get_ciphersuite_name: + * @conn: a #GDTlsConnection + * + * Returns the name of the current DTLS ciphersuite, or %NULL if the + * connection has not handshaked or has been closed. Beware that the TLS + * backend may use any of multiple different naming conventions, because + * OpenSSL and GnuTLS have their own ciphersuite naming conventions that + * are different from each other and different from the standard, IANA- + * registered ciphersuite names. The ciphersuite name is intended to be + * displayed to the user for informative purposes only, and parsing it + * is not recommended. + * + * Returns: (nullable): The name of the current DTLS ciphersuite, or %NULL + * + * Since: 2.70 + */ +gchar * +g_dtls_connection_get_ciphersuite_name (GDtlsConnection *conn) +{ + gchar *ciphersuite_name; + + g_return_val_if_fail (G_IS_DTLS_CONNECTION (conn), NULL); + + g_object_get (G_OBJECT (conn), + "ciphersuite-name", &ciphersuite_name, + NULL); + + return g_steal_pointer (&ciphersuite_name); +} diff --git a/gio/gdtlsconnection.h b/gio/gdtlsconnection.h index e73cf1459..8a5ca2723 100644 --- a/gio/gdtlsconnection.h +++ b/gio/gdtlsconnection.h @@ -45,8 +45,9 @@ typedef struct _GDtlsConnectionInterface GDtlsConnectionInterface; * @shutdown: Shut down one or both directions of the connection. * @shutdown_async: Start an asynchronous shutdown operation. * @shutdown_finish: Finish an asynchronous shutdown operation. - * @set_advertised_protocols: Set APLN protocol list - * @get_negotiated_protocol: Retrieve ALPN-negotiated protocol + * @set_advertised_protocols: Set APLN protocol list (Since: 2.60) + * @get_negotiated_protocol: Get ALPN-negotiated protocol (Since: 2.60) + * @get_binding_data: Retrieve TLS channel binding data (Since: 2.66) * * Virtual method table for a #GDtlsConnection implementation. * @@ -216,6 +217,12 @@ gboolean g_dtls_connection_get_channel_binding_data (GDtlsConnec GError **error); G_GNUC_END_IGNORE_DEPRECATIONS +GLIB_AVAILABLE_IN_2_70 +GTlsProtocolVersion g_dtls_connection_get_protocol_version (GDtlsConnection *conn); + +GLIB_AVAILABLE_IN_2_70 +gchar * g_dtls_connection_get_ciphersuite_name (GDtlsConnection *conn); + G_END_DECLS #endif /* __G_DTLS_CONNECTION_H__ */ diff --git a/gio/gemblemedicon.c b/gio/gemblemedicon.c index 42d013dfa..46fb95fbb 100644 --- a/gio/gemblemedicon.c +++ b/gio/gemblemedicon.c @@ -431,7 +431,7 @@ g_emblemed_icon_serialize (GIcon *icon) icon_data = g_icon_serialize (node->data); if (icon_data) { - /* We know how emblems serialise, so do a tweak here to + /* We know how emblems serialize, so do a tweak here to * reduce some of the variant wrapping and redundant storage * of 'emblem' over and again... */ diff --git a/gio/gfdonotificationbackend.c b/gio/gfdonotificationbackend.c index b6fbfd2e2..4a0a557d6 100644 --- a/gio/gfdonotificationbackend.c +++ b/gio/gfdonotificationbackend.c @@ -257,6 +257,7 @@ call_notify (GDBusConnection *con, GVariantBuilder hints_builder; GIcon *icon; GVariant *parameters; + const gchar *app_name; const gchar *body; guchar urgency; @@ -322,10 +323,11 @@ call_notify (GDBusConnection *con, } } + app_name = g_get_application_name (); body = g_notification_get_body (notification); parameters = g_variant_new ("(susssasa{sv}i)", - "", /* app name */ + app_name ? app_name : "", replace_id, "", /* app icon */ g_notification_get_title (notification), diff --git a/gio/gfileenumerator.c b/gio/gfileenumerator.c index ac2e4eb98..1f9bc24eb 100644 --- a/gio/gfileenumerator.c +++ b/gio/gfileenumerator.c @@ -787,7 +787,10 @@ next_files_thread (GTask *task, } if (error) - g_task_return_error (task, error); + { + g_list_free_full (files, g_object_unref); + g_task_return_error (task, error); + } else g_task_return_pointer (task, files, (GDestroyNotify)next_async_op_free); } diff --git a/gio/gfileinfo.c b/gio/gfileinfo.c index 2a97758b2..a27c24626 100644 --- a/gio/gfileinfo.c +++ b/gio/gfileinfo.c @@ -46,6 +46,11 @@ * g_file_query_writable_namespaces() to discover the settable attributes * of a particular file at runtime. * + * The direct accessors, such as g_file_info_get_name(), are slightly more + * optimized than the generic attribute accessors, such as + * g_file_info_get_attribute_byte_string().This optimization will matter + * only if calling the API in a tight loop. + * * #GFileAttributeMatcher allows for searching through a #GFileInfo for * attributes. **/ @@ -1835,6 +1840,96 @@ g_file_info_get_modification_date_time (GFileInfo *info) } /** + * g_file_info_get_access_date_time: + * @info: a #GFileInfo. + * + * Gets the access time of the current @info and returns it as a + * #GDateTime. + * + * This requires the %G_FILE_ATTRIBUTE_TIME_ACCESS attribute. If + * %G_FILE_ATTRIBUTE_TIME_ACCESS_USEC is provided, the resulting #GDateTime + * will have microsecond precision. + * + * Returns: (transfer full) (nullable): access time, or %NULL if unknown + * Since: 2.70 + */ +GDateTime * +g_file_info_get_access_date_time (GFileInfo *info) +{ + static guint32 attr_atime = 0, attr_atime_usec; + GFileAttributeValue *value, *value_usec; + GDateTime *dt = NULL, *dt2 = NULL; + + g_return_val_if_fail (G_IS_FILE_INFO (info), NULL); + + if (attr_atime == 0) + { + attr_atime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS); + attr_atime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_USEC); + } + + value = g_file_info_find_value (info, attr_atime); + if (value == NULL) + return NULL; + + dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value)); + + value_usec = g_file_info_find_value (info, attr_atime_usec); + if (value_usec == NULL) + return g_steal_pointer (&dt); + + dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec)); + g_date_time_unref (dt); + + return g_steal_pointer (&dt2); +} + +/** + * g_file_info_get_creation_date_time: + * @info: a #GFileInfo. + * + * Gets the creation time of the current @info and returns it as a + * #GDateTime. + * + * This requires the %G_FILE_ATTRIBUTE_TIME_CREATED attribute. If + * %G_FILE_ATTRIBUTE_TIME_CREATED_USEC is provided, the resulting #GDateTime + * will have microsecond precision. + * + * Returns: (transfer full) (nullable): creation time, or %NULL if unknown + * Since: 2.70 + */ +GDateTime * +g_file_info_get_creation_date_time (GFileInfo *info) +{ + static guint32 attr_ctime = 0, attr_ctime_usec; + GFileAttributeValue *value, *value_usec; + GDateTime *dt = NULL, *dt2 = NULL; + + g_return_val_if_fail (G_IS_FILE_INFO (info), NULL); + + if (attr_ctime == 0) + { + attr_ctime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED); + attr_ctime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_USEC); + } + + value = g_file_info_find_value (info, attr_ctime); + if (value == NULL) + return NULL; + + dt = g_date_time_new_from_unix_utc (_g_file_attribute_value_get_uint64 (value)); + + value_usec = g_file_info_find_value (info, attr_ctime_usec); + if (value_usec == NULL) + return g_steal_pointer (&dt); + + dt2 = g_date_time_add (dt, _g_file_attribute_value_get_uint32 (value_usec)); + g_date_time_unref (dt); + + return g_steal_pointer (&dt2); +} + +/** * g_file_info_get_symlink_target: * @info: a #GFileInfo. * @@ -2238,6 +2333,76 @@ g_file_info_set_modification_date_time (GFileInfo *info, } /** + * g_file_info_set_access_date_time: + * @info: a #GFileInfo. + * @atime: (not nullable): a #GDateTime. + * + * Sets the %G_FILE_ATTRIBUTE_TIME_ACCESS and + * %G_FILE_ATTRIBUTE_TIME_ACCESS_USEC attributes in the file info to the + * given date/time value. + * + * Since: 2.70 + */ +void +g_file_info_set_access_date_time (GFileInfo *info, + GDateTime *atime) +{ + static guint32 attr_atime = 0, attr_atime_usec; + GFileAttributeValue *value; + + g_return_if_fail (G_IS_FILE_INFO (info)); + g_return_if_fail (atime != NULL); + + if (attr_atime == 0) + { + attr_atime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS); + attr_atime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_ACCESS_USEC); + } + + value = g_file_info_create_value (info, attr_atime); + if (value) + _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (atime)); + value = g_file_info_create_value (info, attr_atime_usec); + if (value) + _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (atime)); +} + +/** + * g_file_info_set_creation_date_time: + * @info: a #GFileInfo. + * @creation_time: (not nullable): a #GDateTime. + * + * Sets the %G_FILE_ATTRIBUTE_TIME_CREATED and + * %G_FILE_ATTRIBUTE_TIME_CREATED_USEC attributes in the file info to the + * given date/time value. + * + * Since: 2.70 + */ +void +g_file_info_set_creation_date_time (GFileInfo *info, + GDateTime *creation_time) +{ + static guint32 attr_ctime = 0, attr_ctime_usec; + GFileAttributeValue *value; + + g_return_if_fail (G_IS_FILE_INFO (info)); + g_return_if_fail (creation_time != NULL); + + if (attr_ctime == 0) + { + attr_ctime = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED); + attr_ctime_usec = lookup_attribute (G_FILE_ATTRIBUTE_TIME_CREATED_USEC); + } + + value = g_file_info_create_value (info, attr_ctime); + if (value) + _g_file_attribute_value_set_uint64 (value, g_date_time_to_unix (creation_time)); + value = g_file_info_create_value (info, attr_ctime_usec); + if (value) + _g_file_attribute_value_set_uint32 (value, g_date_time_get_microsecond (creation_time)); +} + +/** * g_file_info_set_symlink_target: * @info: a #GFileInfo. * @symlink_target: a static string containing a path to a symlink target. diff --git a/gio/gfileinfo.h b/gio/gfileinfo.h index da202e6a7..4f736e487 100644 --- a/gio/gfileinfo.h +++ b/gio/gfileinfo.h @@ -1057,6 +1057,10 @@ void g_file_info_get_modification_time (GFileInfo *info, G_GNUC_END_IGNORE_DEPRECATIONS GLIB_AVAILABLE_IN_2_62 GDateTime * g_file_info_get_modification_date_time (GFileInfo *info); +GLIB_AVAILABLE_IN_2_70 +GDateTime * g_file_info_get_access_date_time (GFileInfo *info); +GLIB_AVAILABLE_IN_2_70 +GDateTime * g_file_info_get_creation_date_time (GFileInfo *info); GLIB_AVAILABLE_IN_ALL const char * g_file_info_get_symlink_target (GFileInfo *info); GLIB_AVAILABLE_IN_ALL @@ -1109,6 +1113,12 @@ G_GNUC_END_IGNORE_DEPRECATIONS GLIB_AVAILABLE_IN_2_62 void g_file_info_set_modification_date_time (GFileInfo *info, GDateTime *mtime); +GLIB_AVAILABLE_IN_2_70 +void g_file_info_set_access_date_time (GFileInfo *info, + GDateTime *atime); +GLIB_AVAILABLE_IN_2_70 +void g_file_info_set_creation_date_time (GFileInfo *info, + GDateTime *creation_time); GLIB_AVAILABLE_IN_ALL void g_file_info_set_symlink_target (GFileInfo *info, const char *symlink_target); diff --git a/gio/ginputstream.c b/gio/ginputstream.c index 383495162..a40c7d9c4 100644 --- a/gio/ginputstream.c +++ b/gio/ginputstream.c @@ -129,7 +129,7 @@ g_input_stream_init (GInputStream *stream) * @stream: a #GInputStream. * @buffer: (array length=count) (element-type guint8) (out caller-allocates): * a buffer to read data into (which should be at least count bytes long). - * @count: the number of bytes that will be read from the stream + * @count: (in): the number of bytes that will be read from the stream * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. * @error: location to store the error occurring, or %NULL to ignore * @@ -210,7 +210,7 @@ g_input_stream_read (GInputStream *stream, * @stream: a #GInputStream. * @buffer: (array length=count) (element-type guint8) (out caller-allocates): * a buffer to read data into (which should be at least count bytes long). - * @count: the number of bytes that will be read from the stream + * @count: (in): the number of bytes that will be read from the stream * @bytes_read: (out): location to store the number of bytes that was read from the stream * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. * @error: location to store the error occurring, or %NULL to ignore @@ -427,8 +427,10 @@ g_input_stream_real_skip (GInputStream *stream, NULL)) { end = g_seekable_tell (seekable); + g_assert (start >= 0); g_assert (end >= start); - if (start > G_MAXSIZE - count || start + count > end) + if ((guint64) start > (G_MAXSIZE - count) || + (start + count) > (guint64) end) { stream->priv->pending = TRUE; return end - start; @@ -581,7 +583,7 @@ async_ready_close_callback_wrapper (GObject *source_object, * @stream: A #GInputStream. * @buffer: (array length=count) (element-type guint8) (out caller-allocates): * a buffer to read data into (which should be at least count bytes long). - * @count: the number of bytes that will be read from the stream + * @count: (in): the number of bytes that will be read from the stream * @io_priority: the [I/O priority][io-priority] * of the request. * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. @@ -773,7 +775,7 @@ read_all_async_thread (GTask *task, * @stream: A #GInputStream * @buffer: (array length=count) (element-type guint8) (out caller-allocates): * a buffer to read data into (which should be at least count bytes long) - * @count: the number of bytes that will be read from the stream + * @count: (in): the number of bytes that will be read from the stream * @io_priority: the [I/O priority][io-priority] of the request * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore * @callback: (scope async): callback to call when the request is satisfied diff --git a/gio/gio-tool-cat.c b/gio/gio-tool-cat.c index 66841dd3e..bb0c928f5 100644 --- a/gio/gio-tool-cat.c +++ b/gio/gio-tool-cat.c @@ -39,7 +39,7 @@ static const GOptionEntry entries[] = { - { NULL } + G_OPTION_ENTRY_NULL }; /* 256k minus malloc overhead */ diff --git a/gio/gio-tool-copy.c b/gio/gio-tool-copy.c index 0083eba08..cbae0dc6c 100644 --- a/gio/gio-tool-copy.c +++ b/gio/gio-tool-copy.c @@ -47,7 +47,7 @@ static const GOptionEntry entries[] = { { "backup", 'b', 0, G_OPTION_ARG_NONE, &backup, N_("Backup existing destination files"), NULL }, { "no-dereference", 'P', 0, G_OPTION_ARG_NONE, &no_dereference, N_("Never follow symbolic links"), NULL }, { "default-permissions", 0, 0, G_OPTION_ARG_NONE, &default_permissions, N_("Use default permissions for the destination"), NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; static gint64 start_time; diff --git a/gio/gio-tool-info.c b/gio/gio-tool-info.c index a06263545..336da64e2 100644 --- a/gio/gio-tool-info.c +++ b/gio/gio-tool-info.c @@ -38,7 +38,7 @@ static const GOptionEntry entries[] = { { "filesystem", 'f', 0, G_OPTION_ARG_NONE, &filesystem, N_("Get file system info"), NULL }, { "attributes", 'a', 0, G_OPTION_ARG_STRING, &attributes, N_("The attributes to get"), N_("ATTRIBUTES") }, { "nofollow-symlinks", 'n', 0, G_OPTION_ARG_NONE, &nofollow_symlinks, N_("Don’t follow symbolic links"), NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; static char * diff --git a/gio/gio-tool-launch.c b/gio/gio-tool-launch.c index 08c91c68a..edc2cf226 100644 --- a/gio/gio-tool-launch.c +++ b/gio/gio-tool-launch.c @@ -30,7 +30,7 @@ #include "gio-tool.h" static const GOptionEntry entries[] = { - { NULL } + G_OPTION_ENTRY_NULL }; int diff --git a/gio/gio-tool-list.c b/gio/gio-tool-list.c index 9f52d158d..8e9409f10 100644 --- a/gio/gio-tool-list.c +++ b/gio/gio-tool-list.c @@ -39,7 +39,7 @@ static const GOptionEntry entries[] = { { "nofollow-symlinks", 'n', 0, G_OPTION_ARG_NONE, &nofollow_symlinks, N_("Don’t follow symbolic links"), NULL}, { "print-display-names", 'd', 0, G_OPTION_ARG_NONE, &print_display_names, N_("Print display names"), NULL }, { "print-uris", 'u', 0, G_OPTION_ARG_NONE, &print_uris, N_("Print full URIs"), NULL}, - { NULL } + G_OPTION_ENTRY_NULL }; static void diff --git a/gio/gio-tool-mime.c b/gio/gio-tool-mime.c index f564b1fd9..be8a4a9bd 100644 --- a/gio/gio-tool-mime.c +++ b/gio/gio-tool-mime.c @@ -30,7 +30,7 @@ #include "gio-tool.h" static const GOptionEntry entries[] = { - { NULL } + G_OPTION_ENTRY_NULL }; static GAppInfo * diff --git a/gio/gio-tool-mkdir.c b/gio/gio-tool-mkdir.c index 66bf85894..49cb0c328 100644 --- a/gio/gio-tool-mkdir.c +++ b/gio/gio-tool-mkdir.c @@ -29,7 +29,7 @@ static gboolean parent = FALSE; static const GOptionEntry entries[] = { { "parent", 'p', 0, G_OPTION_ARG_NONE, &parent, N_("Create parent directories"), NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; int diff --git a/gio/gio-tool-monitor.c b/gio/gio-tool-monitor.c index 73ee1b12e..9eacfbf69 100644 --- a/gio/gio-tool-monitor.c +++ b/gio/gio-tool-monitor.c @@ -47,7 +47,7 @@ static const GOptionEntry entries[] = { N_("Watch for mount events"), NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &watch_default, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; static void diff --git a/gio/gio-tool-mount.c b/gio/gio-tool-mount.c index 67278bb5c..c62426828 100644 --- a/gio/gio-tool-mount.c +++ b/gio/gio-tool-mount.c @@ -75,7 +75,7 @@ static const GOptionEntry entries[] = { "tcrypt-pim", 0, 0, G_OPTION_ARG_INT, &tcrypt_pim, N_("The numeric PIM when unlocking a VeraCrypt volume"), N_("PIM")}, { "tcrypt-hidden", 0, 0, G_OPTION_ARG_NONE, &tcrypt_hidden, N_("Mount a TCRYPT hidden volume"), NULL}, { "tcrypt-system", 0, 0, G_OPTION_ARG_NONE, &tcrypt_system, N_("Mount a TCRYPT system volume"), NULL}, - { NULL } + G_OPTION_ENTRY_NULL }; static char * diff --git a/gio/gio-tool-move.c b/gio/gio-tool-move.c index 5755f59d4..9be51bcd8 100644 --- a/gio/gio-tool-move.c +++ b/gio/gio-tool-move.c @@ -40,7 +40,7 @@ static const GOptionEntry entries[] = { { "interactive", 'i', 0, G_OPTION_ARG_NONE, &interactive, N_("Prompt before overwrite"), NULL }, { "backup", 'b', 0, G_OPTION_ARG_NONE, &backup, N_("Backup existing destination files"), NULL }, { "no-copy-fallback", 'C', 0, G_OPTION_ARG_NONE, &no_copy_fallback, N_("Don’t use copy and delete fallback"), NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; static gint64 start_time; diff --git a/gio/gio-tool-open.c b/gio/gio-tool-open.c index ac6764a97..f55057bd2 100644 --- a/gio/gio-tool-open.c +++ b/gio/gio-tool-open.c @@ -33,7 +33,7 @@ static int n_outstanding = 0; static gboolean success = TRUE; static const GOptionEntry entries[] = { - { NULL } + G_OPTION_ENTRY_NULL }; static void diff --git a/gio/gio-tool-remove.c b/gio/gio-tool-remove.c index 8748b4629..fb995bfff 100644 --- a/gio/gio-tool-remove.c +++ b/gio/gio-tool-remove.c @@ -29,7 +29,7 @@ static gboolean force = FALSE; static const GOptionEntry entries[] = { {"force", 'f', 0, G_OPTION_ARG_NONE, &force, N_("Ignore nonexistent files, never prompt"), NULL}, - { NULL } + G_OPTION_ENTRY_NULL }; int diff --git a/gio/gio-tool-rename.c b/gio/gio-tool-rename.c index 36e4a8e20..0070b6c60 100644 --- a/gio/gio-tool-rename.c +++ b/gio/gio-tool-rename.c @@ -26,7 +26,7 @@ static const GOptionEntry entries[] = { - { NULL } + G_OPTION_ENTRY_NULL }; int diff --git a/gio/gio-tool-save.c b/gio/gio-tool-save.c index 4969b8b9d..30fb3f91e 100644 --- a/gio/gio-tool-save.c +++ b/gio/gio-tool-save.c @@ -55,7 +55,7 @@ static const GOptionEntry entries[] = { "print-etag", 'v', 0, G_OPTION_ARG_NONE, &print_etag, N_("Print new etag at end"), NULL }, /* Translators: The "etag" is a token allowing to verify whether a file has been modified */ { "etag", 'e', 0, G_OPTION_ARG_STRING, &etag, N_("The etag of the file being overwritten"), N_("ETAG") }, - { NULL } + G_OPTION_ENTRY_NULL }; /* 256k minus malloc overhead */ diff --git a/gio/gio-tool-set.c b/gio/gio-tool-set.c index ab3ac1544..4dbe1214f 100644 --- a/gio/gio-tool-set.c +++ b/gio/gio-tool-set.c @@ -32,7 +32,7 @@ static gboolean nofollow_symlinks = FALSE; static const GOptionEntry entries[] = { { "type", 't', 0, G_OPTION_ARG_STRING, &attr_type, N_("Type of the attribute"), N_("TYPE") }, { "nofollow-symlinks", 'n', 0, G_OPTION_ARG_NONE, &nofollow_symlinks, N_("Don’t follow symbolic links"), NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; static char * diff --git a/gio/gio-tool-trash.c b/gio/gio-tool-trash.c index fc17b4cba..449fa9577 100644 --- a/gio/gio-tool-trash.c +++ b/gio/gio-tool-trash.c @@ -35,7 +35,7 @@ static const GOptionEntry entries[] = { { "list", 0, 0, G_OPTION_ARG_NONE, &list, N_("List files in the trash with their original locations"), NULL }, { "restore", 0, 0, G_OPTION_ARG_NONE, &restore, N_("Restore a file from trash to its original location (possibly " "recreating the directory)"), NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; static void diff --git a/gio/gio-tool-tree.c b/gio/gio-tool-tree.c index 2327c4549..c572afc37 100644 --- a/gio/gio-tool-tree.c +++ b/gio/gio-tool-tree.c @@ -31,7 +31,7 @@ static gboolean follow_symlinks = FALSE; static const GOptionEntry entries[] = { { "hidden", 'h', 0, G_OPTION_ARG_NONE, &show_hidden, N_("Show hidden files"), NULL }, { "follow-symlinks", 'l', 0, G_OPTION_ARG_NONE, &follow_symlinks, N_("Follow symbolic links, mounts and shortcuts"), NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; static gint diff --git a/gio/gioenums.h b/gio/gioenums.h index f2f66c875..d81ada416 100644 --- a/gio/gioenums.h +++ b/gio/gioenums.h @@ -1703,6 +1703,12 @@ typedef enum { * wrong many times, and the user may not have many chances left. * @G_TLS_PASSWORD_FINAL_TRY: Hint to the user that this is the last try to get * this password right. + * @G_TLS_PASSWORD_PKCS11_USER: For PKCS #11, the user PIN is required. + * Since: 2.70. + * @G_TLS_PASSWORD_PKCS11_SECURITY_OFFICER: For PKCS #11, the security officer + * PIN is required. Since: 2.70. + * @G_TLS_PASSWORD_PKCS11_CONTEXT_SPECIFIC: For PKCS #11, the context-specific + * PIN is required. Since: 2.70. * * Various flags for the password. * @@ -1714,7 +1720,10 @@ typedef enum _GTlsPasswordFlags G_TLS_PASSWORD_NONE = 0, G_TLS_PASSWORD_RETRY = 1 << 1, G_TLS_PASSWORD_MANY_TRIES = 1 << 2, - G_TLS_PASSWORD_FINAL_TRY = 1 << 3 + G_TLS_PASSWORD_FINAL_TRY = 1 << 3, + G_TLS_PASSWORD_PKCS11_USER = 1 << 4, + G_TLS_PASSWORD_PKCS11_SECURITY_OFFICER = 1 << 5, + G_TLS_PASSWORD_PKCS11_CONTEXT_SPECIFIC = 1 << 6 } GTlsPasswordFlags; /** @@ -1817,6 +1826,40 @@ typedef enum { } GTlsCertificateRequestFlags; /** + * GTlsProtocolVersion: + * @G_TLS_PROTOCOL_VERSION_UNKNOWN: No protocol version or unknown protocol version + * @G_TLS_PROTOCOL_VERSION_SSL_3_0: SSL 3.0, which is insecure and should not be used + * @G_TLS_PROTOCOL_VERSION_TLS_1_0: TLS 1.0, which is insecure and should not be used + * @G_TLS_PROTOCOL_VERSION_TLS_1_1: TLS 1.1, which is insecure and should not be used + * @G_TLS_PROTOCOL_VERSION_TLS_1_2: TLS 1.2, defined by [RFC 5246](https://datatracker.ietf.org/doc/html/rfc5246) + * @G_TLS_PROTOCOL_VERSION_TLS_1_3: TLS 1.3, defined by [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446) + * @G_TLS_PROTOCOL_VERSION_DTLS_1_0: DTLS 1.0, which is insecure and should not be used + * @G_TLS_PROTOCOL_VERSION_DTLS_1_2: DTLS 1.2, defined by [RFC 6347](https://datatracker.ietf.org/doc/html/rfc6347) + * + * The TLS or DTLS protocol version used by a #GTlsConnection or + * #GDtlsConnection. The integer values of these versions are sequential + * to ensure newer known protocol versions compare greater than older + * known versions. Any known DTLS protocol version will compare greater + * than any SSL or TLS protocol version. The protocol version may be + * %G_TLS_PROTOCOL_VERSION_UNKNOWN if the TLS backend supports a newer + * protocol version that GLib does not yet know about. This means that + * it's possible for an unknown DTLS protocol version to compare less + * than the TLS protocol versions. + * + * Since: 2.70 + */ +typedef enum { + G_TLS_PROTOCOL_VERSION_UNKNOWN = 0, + G_TLS_PROTOCOL_VERSION_SSL_3_0 = 1, + G_TLS_PROTOCOL_VERSION_TLS_1_0 = 2, + G_TLS_PROTOCOL_VERSION_TLS_1_1 = 3, + G_TLS_PROTOCOL_VERSION_TLS_1_2 = 4, + G_TLS_PROTOCOL_VERSION_TLS_1_3 = 5, + G_TLS_PROTOCOL_VERSION_DTLS_1_0 = 201, + G_TLS_PROTOCOL_VERSION_DTLS_1_2 = 202, +} GTlsProtocolVersion; + +/** * GIOModuleScopeFlags: * @G_IO_MODULE_SCOPE_NONE: No module scan flags * @G_IO_MODULE_SCOPE_BLOCK_DUPLICATES: When using this scope to load or diff --git a/gio/giomodule.c b/gio/giomodule.c index a2909a8ef..d3b5e482a 100644 --- a/gio/giomodule.c +++ b/gio/giomodule.c @@ -731,7 +731,7 @@ print_help (const char *envvar, { GList *l; GIOExtension *extension; - int width = 0; + gsize width = 0; for (l = g_io_extension_point_get_extensions (ep); l; l = l->next) { @@ -743,7 +743,9 @@ print_help (const char *envvar, { extension = l->data; - g_print (" %*s - %d\n", width, g_io_extension_get_name (extension), g_io_extension_get_priority (extension)); + g_print (" %*s - %d\n", (int) MIN (width, G_MAXINT), + g_io_extension_get_name (extension), + g_io_extension_get_priority (extension)); } } } diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c index 094be3f91..9319491d5 100644 --- a/gio/gkeyfilesettingsbackend.c +++ b/gio/gkeyfilesettingsbackend.c @@ -66,9 +66,9 @@ typedef struct GHashTable *system_locks; /* Used as a set, owning the strings it contains */ gchar *prefix; - gint prefix_len; + gsize prefix_len; gchar *root_group; - gint root_group_len; + gsize root_group_len; GFile *file; GFileMonitor *file_monitor; @@ -173,7 +173,9 @@ convert_path (GKeyfileSettingsBackend *kfsb, /* if a root_group was specified, make sure the user hasn't given * a path that ghosts that group name */ - if (last_slash != NULL && (last_slash - key) == kfsb->root_group_len && memcmp (key, kfsb->root_group, last_slash - key) == 0) + if (last_slash != NULL && last_slash - key >= 0 && + (gsize) (last_slash - key) == kfsb->root_group_len && + memcmp (key, kfsb->root_group, last_slash - key) == 0) return FALSE; } else diff --git a/gio/glib-compile-resources.c b/gio/glib-compile-resources.c index 74373e5b0..db621a7b6 100644 --- a/gio/glib-compile-resources.c +++ b/gio/glib-compile-resources.c @@ -747,7 +747,7 @@ main (int argc, char **argv) { "internal", 0, 0, G_OPTION_ARG_NONE, &internal, N_("Don’t export functions; declare them G_GNUC_INTERNAL"), NULL }, { "external-data", 0, 0, G_OPTION_ARG_NONE, &external_data, N_("Don’t embed resource data in the C file; assume it's linked externally instead"), NULL }, { "c-name", 0, 0, G_OPTION_ARG_STRING, &c_name, N_("C identifier name used for the generated source code"), NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; #ifdef G_OS_WIN32 diff --git a/gio/glib-compile-schemas.c b/gio/glib-compile-schemas.c index cfea042f8..7e1152f6b 100644 --- a/gio/glib-compile-schemas.c +++ b/gio/glib-compile-schemas.c @@ -2178,7 +2178,7 @@ main (int argc, char **argv) /* These options are only for use in the gschema-compile tests */ { "schema-file", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME_ARRAY, &schema_files, NULL, NULL }, { "override-file", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME_ARRAY, &override_files, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; #ifdef G_OS_WIN32 diff --git a/gio/glocalfile.c b/gio/glocalfile.c index 51a94e51c..873aa911f 100644 --- a/gio/glocalfile.c +++ b/gio/glocalfile.c @@ -609,6 +609,8 @@ get_fs_type (long f_type) return "efivarfs"; case 0x00414A53: return "efs"; + case 0x2011BAB0UL: + return "exfat"; case 0x137D: return "ext"; case 0xEF51: @@ -2068,7 +2070,6 @@ g_local_file_trash (GFile *file, (global_stat.st_mode & S_ISVTX) != 0) { trashdir = g_build_filename (globaldir, uid_str, NULL); - success = TRUE; if (g_lstat (trashdir, &trash_stat) == 0) { @@ -2078,14 +2079,12 @@ g_local_file_trash (GFile *file, /* Not a directory or not owned by user, ignore */ g_free (trashdir); trashdir = NULL; - success = FALSE; } } else if (g_mkdir (trashdir, 0700) == -1) { g_free (trashdir); trashdir = NULL; - success = FALSE; } } g_free (globaldir); diff --git a/gio/gnotification.c b/gio/gnotification.c index 27efed3f4..aa7df7f7b 100644 --- a/gio/gnotification.c +++ b/gio/gnotification.c @@ -43,6 +43,29 @@ * not running, applications using #GNotification should be able to be * started as a D-Bus service, using #GApplication. * + * In order for #GNotification to work, the application must have installed + * a `.desktop` file. For example: + * |[ + * [Desktop Entry] + * Name=Test Application + * Comment=Description of what Test Application does + * Exec=gnome-test-application + * Icon=org.gnome.TestApplication + * Terminal=false + * Type=Application + * Categories=GNOME;GTK;TestApplication Category; + * StartupNotify=true + * DBusActivatable=true + * X-GNOME-UsesNotifications=true + * ]| + * + * The `X-GNOME-UsesNotifications` key indicates to GNOME Control Center + * that this application uses notifications, so it can be listed in the + * Control Center’s ‘Notifications’ panel. + * + * The `.desktop` file must be named as `org.gnome.TestApplication.desktop`, + * where `org.gnome.TestApplication` is the ID passed to g_application_new(). + * * User interaction with a notification (either the default action, or * buttons) must be associated with actions on the application (ie: * "app." actions). It is not possible to route user interaction diff --git a/gio/gpollableinputstream.c b/gio/gpollableinputstream.c index 6a13f34b6..d04019339 100644 --- a/gio/gpollableinputstream.c +++ b/gio/gpollableinputstream.c @@ -159,9 +159,9 @@ g_pollable_input_stream_default_read_nonblocking (GPollableInputStream *stream, /** * g_pollable_input_stream_read_nonblocking: * @stream: a #GPollableInputStream - * @buffer: (array length=count) (element-type guint8): a buffer to - * read data into (which should be at least @count bytes long). - * @count: the number of bytes you want to read + * @buffer: (array length=count) (element-type guint8) (out caller-allocates): a + * buffer to read data into (which should be at least @count bytes long). + * @count: (in): the number of bytes you want to read * @cancellable: (nullable): a #GCancellable, or %NULL * @error: #GError for error reporting, or %NULL to ignore. * diff --git a/gio/gresource-tool.c b/gio/gresource-tool.c index 1914c5228..aa718974e 100644 --- a/gio/gresource-tool.c +++ b/gio/gresource-tool.c @@ -180,17 +180,18 @@ elf_foreach_resource_section (Elf *elf, SectionCallback callback, gpointer data) { + int ret; size_t shstrndx, shnum; size_t scnidx; Elf_Scn *scn; GElf_Shdr *shdr, shdr_mem; const gchar *section_name; - elf_getshdrstrndx (elf, &shstrndx); - g_assert (shstrndx >= 0); + ret = elf_getshdrstrndx (elf, &shstrndx); + g_assert (ret == 0); - elf_getshdrnum (elf, &shnum); - g_assert (shnum >= 0); + ret = elf_getshdrnum (elf, &shnum); + g_assert (ret == 0); for (scnidx = 1; scnidx < shnum; scnidx++) { diff --git a/gio/gseekable.c b/gio/gseekable.c index 28e815703..9689a77b6 100644 --- a/gio/gseekable.c +++ b/gio/gseekable.c @@ -59,7 +59,8 @@ g_seekable_default_init (GSeekableInterface *iface) * * Tells the current position within the stream. * - * Returns: the offset from the beginning of the buffer. + * Returns: the (positive or zero) offset from the beginning of the + * buffer, zero if the target is not seekable. **/ goffset g_seekable_tell (GSeekable *seekable) diff --git a/gio/gsettings-tool.c b/gio/gsettings-tool.c index 3096f9d9b..7559a6b1b 100644 --- a/gio/gsettings-tool.c +++ b/gio/gsettings-tool.c @@ -191,13 +191,16 @@ static void gsettings_list_children (void) { gchar **children; - gint max = 0; + gsize max = 0; gint i; children = g_settings_list_children (global_settings); for (i = 0; children[i]; i++) - if (strlen (children[i]) > max) - max = strlen (children[i]); + { + gsize len = strlen (children[i]); + if (len > max) + max = len; + } for (i = 0; children[i]; i++) { @@ -212,9 +215,11 @@ gsettings_list_children (void) NULL); if (g_settings_schema_get_path (schema) != NULL) - g_print ("%-*s %s\n", max, children[i], g_settings_schema_get_id (schema)); + g_print ("%-*s %s\n", (int) MIN (max, G_MAXINT), children[i], + g_settings_schema_get_id (schema)); else - g_print ("%-*s %s:%s\n", max, children[i], g_settings_schema_get_id (schema), path); + g_print ("%-*s %s:%s\n", (int) MIN (max, G_MAXINT), children[i], + g_settings_schema_get_id (schema), path); g_object_unref (child); g_settings_schema_unref (schema); diff --git a/gio/gsettings.c b/gio/gsettings.c index 9a04a8630..f7d39c77e 100644 --- a/gio/gsettings.c +++ b/gio/gsettings.c @@ -121,7 +121,7 @@ * utility. The input is a schema description in an XML format. * * A DTD for the gschema XML format can be found here: - * [gschema.dtd](https://git.gnome.org/browse/glib/tree/gio/gschema.dtd) + * [gschema.dtd](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/gschema.dtd) * * The [glib-compile-schemas][glib-compile-schemas] tool expects schema * files to have the extension `.gschema.xml`. @@ -2434,28 +2434,24 @@ GSettings * g_settings_get_child (GSettings *settings, const gchar *name) { - const gchar *child_schema; + GSettingsSchema *child_schema; gchar *child_path; - gchar *child_name; GSettings *child; g_return_val_if_fail (G_IS_SETTINGS (settings), NULL); - child_name = g_strconcat (name, "/", NULL); - child_schema = g_settings_schema_get_string (settings->priv->schema, - child_name); + child_schema = g_settings_schema_get_child_schema (settings->priv->schema, + name); if (child_schema == NULL) - g_error ("Schema '%s' has no child '%s'", + g_error ("Schema '%s' has no child '%s' or child schema not found", g_settings_schema_get_id (settings->priv->schema), name); - child_path = g_strconcat (settings->priv->path, child_name, NULL); - child = g_object_new (G_TYPE_SETTINGS, - "backend", settings->priv->backend, - "schema-id", child_schema, - "path", child_path, - NULL); + child_path = g_strconcat (settings->priv->path, name, "/", NULL); + child = g_settings_new_full (child_schema, + settings->priv->backend, + child_path); + g_settings_schema_unref (child_schema); g_free (child_path); - g_free (child_name); return child; } diff --git a/gio/gsettingsschema-internal.h b/gio/gsettingsschema-internal.h index 5f996b4bc..416cf2d8c 100644 --- a/gio/gsettingsschema-internal.h +++ b/gio/gsettingsschema-internal.h @@ -50,6 +50,9 @@ const GQuark * g_settings_schema_list (GSettin const gchar * g_settings_schema_get_string (GSettingsSchema *schema, const gchar *key); +GSettingsSchema * g_settings_schema_get_child_schema (GSettingsSchema *schema, + const gchar *name); + void g_settings_schema_key_init (GSettingsSchemaKey *key, GSettingsSchema *schema, const gchar *name); diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c index a46d5056f..ec0caf655 100644 --- a/gio/gsettingsschema.c +++ b/gio/gsettingsschema.c @@ -968,6 +968,24 @@ g_settings_schema_get_string (GSettingsSchema *schema, return result; } +GSettingsSchema * +g_settings_schema_get_child_schema (GSettingsSchema *schema, + const gchar *name) +{ + const gchar *child_id; + gchar *child_name; + + child_name = g_strconcat (name, "/", NULL); + child_id = g_settings_schema_get_string (schema, child_name); + + g_free (child_name); + + if (child_id == NULL) + return NULL; + + return g_settings_schema_source_lookup (schema->source, child_id, TRUE); +} + GVariantIter * g_settings_schema_get_value (GSettingsSchema *schema, const gchar *key) diff --git a/gio/gsocket.c b/gio/gsocket.c index f39a568b3..a7ba27d0c 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -4795,9 +4795,7 @@ g_socket_send_message (GSocket *socket, if (num_vectors != -1) { - gint i; - - for (i = 0; i < num_vectors; i++) + for (gint i = 0; i < num_vectors; i++) { /* No wrap-around for vectors_size */ if (vectors_size > vectors_size + vectors[i].size) @@ -4813,9 +4811,7 @@ g_socket_send_message (GSocket *socket, } else { - gsize i; - - for (i = 0; vectors[i].buffer != NULL; i++) + for (gsize i = 0; vectors[i].buffer != NULL; i++) { /* No wrap-around for vectors_size */ if (vectors_size > vectors_size + vectors[i].size) diff --git a/gio/gsocketcontrolmessage.c b/gio/gsocketcontrolmessage.c index 255610c46..198ddeca3 100644 --- a/gio/gsocketcontrolmessage.c +++ b/gio/gsocketcontrolmessage.c @@ -204,7 +204,7 @@ g_socket_control_message_deserialize (int level, * example, the control message may be be discarded if it is deemed * empty, see e.g. * - * http://git.gnome.org/browse/glib/commit/?id=ec91ed00f14c70cca9749347b8ebc19d72d9885b + * https://gitlab.gnome.org/GNOME/glib/commit/ec91ed00f14c70cca9749347b8ebc19d72d9885b * * Therefore, it's not appropriate to print a warning about not * being able to deserialize the message. diff --git a/gio/gsocketlistener.c b/gio/gsocketlistener.c index bdf1608dc..9baa609bc 100644 --- a/gio/gsocketlistener.c +++ b/gio/gsocketlistener.c @@ -913,7 +913,7 @@ g_socket_listener_accept_socket_finish (GSocketListener *listener, * This is the asynchronous version of g_socket_listener_accept(). * * When the operation is finished @callback will be - * called. You can then call g_socket_listener_accept_socket() + * called. You can then call g_socket_listener_accept_finish() * to get the result of the operation. * * Since: 2.22 diff --git a/gio/gsubprocess.c b/gio/gsubprocess.c index 77a23efc3..c0f4f8db6 100644 --- a/gio/gsubprocess.c +++ b/gio/gsubprocess.c @@ -883,7 +883,7 @@ g_subprocess_wait (GSubprocess *subprocess, * @cancellable: a #GCancellable * @error: a #GError * - * Combines g_subprocess_wait() with g_spawn_check_exit_status(). + * Combines g_subprocess_wait() with g_spawn_check_wait_status(). * * Returns: %TRUE on success, %FALSE if process exited abnormally, or * @cancellable was cancelled @@ -896,7 +896,7 @@ g_subprocess_wait_check (GSubprocess *subprocess, GError **error) { return g_subprocess_wait (subprocess, cancellable, error) && - g_spawn_check_exit_status (subprocess->status, error); + g_spawn_check_wait_status (subprocess->status, error); } /** @@ -906,7 +906,7 @@ g_subprocess_wait_check (GSubprocess *subprocess, * @callback: a #GAsyncReadyCallback to call when the operation is complete * @user_data: user_data for @callback * - * Combines g_subprocess_wait_async() with g_spawn_check_exit_status(). + * Combines g_subprocess_wait_async() with g_spawn_check_wait_status(). * * This is the asynchronous version of g_subprocess_wait_check(). * @@ -940,7 +940,7 @@ g_subprocess_wait_check_finish (GSubprocess *subprocess, GError **error) { return g_subprocess_wait_finish (subprocess, result, error) && - g_spawn_check_exit_status (subprocess->status, error); + g_spawn_check_wait_status (subprocess->status, error); } #ifdef G_OS_UNIX @@ -1053,7 +1053,7 @@ g_subprocess_force_exit (GSubprocess *subprocess) * * This value has no particular meaning, but it can be used with the * macros defined by the system headers such as WIFEXITED. It can also - * be used with g_spawn_check_exit_status(). + * be used with g_spawn_check_wait_status(). * * It is more likely that you want to use g_subprocess_get_if_exited() * followed by g_subprocess_get_exit_status(). diff --git a/gio/gtask.c b/gio/gtask.c index 2b4720de8..b533a18cf 100644 --- a/gio/gtask.c +++ b/gio/gtask.c @@ -1528,9 +1528,9 @@ g_task_start_task_thread (GTask *task, * * Although GLib currently rate-limits the tasks queued via * g_task_run_in_thread(), you should not assume that it will always - * do this. If you have a very large number of tasks to run, but don't - * want them to all run at once, you should only queue a limited - * number of them at a time. + * do this. If you have a very large number of tasks to run (several tens of + * tasks), but don't want them to all run at once, you should only queue a + * limited number of them (around ten) at a time. * * Since: 2.36 */ diff --git a/gio/gtestdbus.c b/gio/gtestdbus.c index d362f9478..703a0b3a5 100644 --- a/gio/gtestdbus.c +++ b/gio/gtestdbus.c @@ -380,7 +380,7 @@ _g_test_watcher_remove_pid (GPid pid) * * An example of a test fixture for D-Bus services can be found * here: - * [gdbus-test-fixture.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-test-fixture.c) + * [gdbus-test-fixture.c](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/gio/tests/gdbus-test-fixture.c) * * Note that these examples only deal with isolating the D-Bus aspect of your * service. To successfully run isolated unit tests on your service you may need diff --git a/gio/gtlscertificate.c b/gio/gtlscertificate.c index b246e0c87..308a0a7ed 100644 --- a/gio/gtlscertificate.c +++ b/gio/gtlscertificate.c @@ -63,6 +63,12 @@ enum PROP_ISSUER, PROP_PKCS11_URI, PROP_PRIVATE_KEY_PKCS11_URI, + PROP_NOT_VALID_BEFORE, + PROP_NOT_VALID_AFTER, + PROP_SUBJECT_NAME, + PROP_ISSUER_NAME, + PROP_DNS_NAMES, + PROP_IP_ADDRESSES, }; static void @@ -78,6 +84,8 @@ g_tls_certificate_get_property (GObject *object, { switch (prop_id) { + case PROP_PRIVATE_KEY: + case PROP_PRIVATE_KEY_PEM: case PROP_PKCS11_URI: case PROP_PRIVATE_KEY_PKCS11_URI: /* Subclasses must override this property but this allows older backends to not fatally error */ @@ -148,17 +156,25 @@ g_tls_certificate_class_init (GTlsCertificateClass *class) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); /** - * GTlsCertificate:private-key: + * GTlsCertificate:private-key: (nullable) * * The DER (binary) encoded representation of the certificate's - * private key, in either PKCS#1 format or unencrypted PKCS#8 - * format. This property (or the #GTlsCertificate:private-key-pem - * property) can be set when constructing a key (eg, from a file), - * but cannot be read. + * private key, in either [PKCS \#1 format](https://datatracker.ietf.org/doc/html/rfc8017) + * or unencrypted [PKCS \#8 format.](https://datatracker.ietf.org/doc/html/rfc5208) + * PKCS \#8 format is supported since 2.32; earlier releases only + * support PKCS \#1. You can use the `openssl rsa` tool to convert + * PKCS \#8 keys to PKCS \#1. * - * PKCS#8 format is supported since 2.32; earlier releases only - * support PKCS#1. You can use the `openssl rsa` - * tool to convert PKCS#8 keys to PKCS#1. + * This property (or the #GTlsCertificate:private-key-pem property) + * can be set when constructing a key (for example, from a file). + * Since GLib 2.70, it is now also readable; however, be aware that if + * the private key is backed by a PKCS \#11 URI – for example, if it + * is stored on a smartcard – then this property will be %NULL. If so, + * the private key must be referenced via its PKCS \#11 URI, + * #GTlsCertificate:private-key-pkcs11-uri. You must check both + * properties to see if the certificate really has a private key. + * When this property is read, the output format will be unencrypted + * PKCS \#8. * * Since: 2.28 */ @@ -167,22 +183,30 @@ g_tls_certificate_class_init (GTlsCertificateClass *class) P_("Private key"), P_("The DER representation of the certificate’s private key"), G_TYPE_BYTE_ARRAY, - G_PARAM_WRITABLE | + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); /** - * GTlsCertificate:private-key-pem: + * GTlsCertificate:private-key-pem: (nullable) * * The PEM (ASCII) encoded representation of the certificate's - * private key in either PKCS#1 format ("`BEGIN RSA PRIVATE - * KEY`") or unencrypted PKCS#8 format ("`BEGIN - * PRIVATE KEY`"). This property (or the - * #GTlsCertificate:private-key property) can be set when - * constructing a key (eg, from a file), but cannot be read. + * private key in either [PKCS \#1 format](https://datatracker.ietf.org/doc/html/rfc8017) + * ("`BEGIN RSA PRIVATE KEY`") or unencrypted + * [PKCS \#8 format](https://datatracker.ietf.org/doc/html/rfc5208) + * ("`BEGIN PRIVATE KEY`"). PKCS \#8 format is supported since 2.32; + * earlier releases only support PKCS \#1. You can use the `openssl rsa` + * tool to convert PKCS \#8 keys to PKCS \#1. * - * PKCS#8 format is supported since 2.32; earlier releases only - * support PKCS#1. You can use the `openssl rsa` - * tool to convert PKCS#8 keys to PKCS#1. + * This property (or the #GTlsCertificate:private-key property) + * can be set when constructing a key (for example, from a file). + * Since GLib 2.70, it is now also readable; however, be aware that if + * the private key is backed by a PKCS \#11 URI - for example, if it + * is stored on a smartcard - then this property will be %NULL. If so, + * the private key must be referenced via its PKCS \#11 URI, + * #GTlsCertificate:private-key-pkcs11-uri. You must check both + * properties to see if the certificate really has a private key. + * When this property is read, the output format will be unencrypted + * PKCS \#8. * * Since: 2.28 */ @@ -191,7 +215,7 @@ g_tls_certificate_class_init (GTlsCertificateClass *class) P_("Private key (PEM)"), P_("The PEM representation of the certificate’s private key"), NULL, - G_PARAM_WRITABLE | + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); /** @@ -216,10 +240,10 @@ g_tls_certificate_class_init (GTlsCertificateClass *class) /** * GTlsCertificate:pkcs11-uri: (nullable) * - * A URI referencing the PKCS \#11 objects containing an X.509 certificate - * and optionally a private key. + * A URI referencing the [PKCS \#11](https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/os/pkcs11-base-v3.0-os.html) + * objects containing an X.509 certificate and optionally a private key. * - * If %NULL the certificate is either not backed by PKCS \#11 or the + * If %NULL, the certificate is either not backed by PKCS \#11 or the * #GTlsBackend does not support PKCS \#11. * * Since: 2.68 @@ -236,7 +260,8 @@ g_tls_certificate_class_init (GTlsCertificateClass *class) /** * GTlsCertificate:private-key-pkcs11-uri: (nullable) * - * A URI referencing a PKCS \#11 object containing a private key. + * A URI referencing a [PKCS \#11](https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/os/pkcs11-base-v3.0-os.html) + * object containing a private key. * * Since: 2.68 */ @@ -248,6 +273,101 @@ g_tls_certificate_class_init (GTlsCertificateClass *class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /** + * GTlsCertificate:not-valid-before: (nullable) + * + * The time at which this cert is considered to be valid, + * %NULL if unavailable. + * + * Since: 2.70 + */ + g_object_class_install_property (gobject_class, PROP_NOT_VALID_BEFORE, + g_param_spec_boxed ("not-valid-before", + P_("Not Valid Before"), + P_("Cert should not be considered valid before this time."), + G_TYPE_DATE_TIME, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * GTlsCertificate:not-valid-after: (nullable) + * + * The time at which this cert is no longer valid, + * %NULL if unavailable. + * + * Since: 2.70 + */ + g_object_class_install_property (gobject_class, PROP_NOT_VALID_AFTER, + g_param_spec_boxed ("not-valid-after", + P_("Not Valid after"), + P_("Cert should not be considered valid after this time."), + G_TYPE_DATE_TIME, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * GTlsCertificate:subject-name: (nullable) + * + * The subject from the cert, + * %NULL if unavailable. + * + * Since: 2.70 + */ + g_object_class_install_property (gobject_class, PROP_SUBJECT_NAME, + g_param_spec_string ("subject-name", + P_("Subject Name"), + P_("The subject name from the certificate."), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + /** + * GTlsCertificate:issuer-name: (nullable) + * + * The issuer from the certificate, + * %NULL if unavailable. + * + * Since: 2.70 + */ + g_object_class_install_property (gobject_class, PROP_ISSUER_NAME, + g_param_spec_string ("issuer-name", + P_("Issuer Name"), + P_("The issuer from the certificate."), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * GTlsCertificate:dns-names: (nullable) (element-type GBytes) (transfer container) + * + * The DNS names from the certificate's Subject Alternative Names (SANs), + * %NULL if unavailable. + * + * Since: 2.70 + */ + g_object_class_install_property (gobject_class, PROP_DNS_NAMES, + g_param_spec_boxed ("dns-names", + P_("DNS Names"), + P_("DNS Names listed on the cert."), + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * GTlsCertificate:ip-addresses: (nullable) (element-type GInetAddress) (transfer container) + * + * The IP addresses from the certificate's Subject Alternative Names (SANs), + * %NULL if unavailable. + * + * Since: 2.70 + */ + g_object_class_install_property (gobject_class, PROP_IP_ADDRESSES, + g_param_spec_boxed ("ip-addresses", + P_("IP Addresses"), + P_("IP Addresses listed on the cert."), + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); } static GTlsCertificate * @@ -653,13 +773,14 @@ g_tls_certificate_new_from_files (const gchar *cert_file, * @private_key_pkcs11_uri: (nullable): A PKCS \#11 URI * @error: #GError for error reporting, or %NULL to ignore. * - * Creates a #GTlsCertificate from a PKCS \#11 URI. + * Creates a #GTlsCertificate from a + * [PKCS \#11](https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/os/pkcs11-base-v3.0-os.html) URI. * * An example @pkcs11_uri would be `pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01` * * Where the token’s layout is: * - * ``` + * |[ * Object 0: * URL: pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01;object=private%20key;type=private * Type: Private key (RSA-2048) @@ -669,7 +790,7 @@ g_tls_certificate_new_from_files (const gchar *cert_file, * URL: pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01;object=Certificate%20for%20Authentication;type=cert * Type: X.509 Certificate (RSA-2048) * ID: 01 - * ``` + * ]| * * In this case the certificate and private key would both be detected and used as expected. * @pkcs_uri may also just reference an X.509 certificate object and then optionally @@ -877,3 +998,138 @@ g_tls_certificate_is_same (GTlsCertificate *cert_one, return equal; } + + +/** + * g_tls_certificate_get_not_valid_before: + * @cert: a #GTlsCertificate + * + * Returns the time at which the certificate became or will become valid. + * + * Returns: (nullable) (transfer full): The not-valid-before date, or %NULL if it's not available. + * + * Since: 2.70 + */ +GDateTime * +g_tls_certificate_get_not_valid_before (GTlsCertificate *cert) +{ + GDateTime *not_valid_before = NULL; + + g_return_val_if_fail (G_IS_TLS_CERTIFICATE (cert), NULL); + + g_object_get (G_OBJECT (cert), "not-valid-before", ¬_valid_before, NULL); + + return g_steal_pointer (¬_valid_before); +} + +/** + * g_tls_certificate_get_not_valid_after: + * @cert: a #GTlsCertificate + * + * Returns the time at which the certificate became or will become invalid. + * + * Returns: (nullable) (transfer full): The not-valid-after date, or %NULL if it's not available. + * + * Since: 2.70 + */ +GDateTime * +g_tls_certificate_get_not_valid_after (GTlsCertificate *cert) +{ + GDateTime *not_valid_after = NULL; + + g_return_val_if_fail (G_IS_TLS_CERTIFICATE (cert), NULL); + + g_object_get (G_OBJECT (cert), "not-valid-after", ¬_valid_after, NULL); + + return g_steal_pointer (¬_valid_after); +} + +/** + * g_tls_certificate_get_subject_name: + * @cert: a #GTlsCertificate + * + * Returns the subject name from the certificate. + * + * Returns: (nullable) (transfer full): The subject name, or %NULL if it's not available. + * + * Since: 2.70 + */ +gchar * +g_tls_certificate_get_subject_name (GTlsCertificate *cert) +{ + gchar *subject_name = NULL; + + g_return_val_if_fail (G_IS_TLS_CERTIFICATE (cert), NULL); + + g_object_get (G_OBJECT (cert), "subject-name", &subject_name, NULL); + + return g_steal_pointer (&subject_name); +} + +/** + * g_tls_certificate_get_issuer_name: + * @cert: a #GTlsCertificate + * + * Returns the issuer name from the certificate. + * + * Returns: (nullable) (transfer full): The issuer name, or %NULL if it's not available. + * + * Since: 2.70 + */ +gchar * +g_tls_certificate_get_issuer_name (GTlsCertificate *cert) +{ + gchar *issuer_name = NULL; + + g_return_val_if_fail (G_IS_TLS_CERTIFICATE (cert), NULL); + + g_object_get (G_OBJECT (cert), "issuer-name", &issuer_name, NULL); + + return g_steal_pointer (&issuer_name); +} + +/** + * g_tls_certificate_get_dns_names: + * @cert: a #GTlsCertificate + * + * Gets the value of #GTlsCertificate:dns-names. + * + * Returns: (nullable) (element-type GBytes) (transfer container): A #GPtrArray of + * #GBytes elements, or %NULL if it's not available. + * + * Since: 2.70 + */ +GPtrArray * +g_tls_certificate_get_dns_names (GTlsCertificate *cert) +{ + GPtrArray *dns_names = NULL; + + g_return_val_if_fail (G_IS_TLS_CERTIFICATE (cert), NULL); + + g_object_get (G_OBJECT (cert), "dns-names", &dns_names, NULL); + + return g_steal_pointer (&dns_names); +} + +/** + * g_tls_certificate_get_ip_addresses: + * @cert: a #GTlsCertificate + * + * Gets the value of #GTlsCertificate:ip-addresses. + * + * Returns: (nullable) (element-type GInetAddress) (transfer container): A #GPtrArray + * of #GInetAddress elements, or %NULL if it's not available. + * + * Since: 2.70 + */ +GPtrArray * +g_tls_certificate_get_ip_addresses (GTlsCertificate *cert) +{ + GPtrArray *ip_addresses = NULL; + + g_return_val_if_fail (G_IS_TLS_CERTIFICATE (cert), NULL); + + g_object_get (G_OBJECT (cert), "ip-addresses", &ip_addresses, NULL); + + return g_steal_pointer (&ip_addresses); +} diff --git a/gio/gtlscertificate.h b/gio/gtlscertificate.h index ead4f015e..3b92b97fc 100644 --- a/gio/gtlscertificate.h +++ b/gio/gtlscertificate.h @@ -92,6 +92,24 @@ GLIB_AVAILABLE_IN_2_34 gboolean g_tls_certificate_is_same (GTlsCertificate *cert_one, GTlsCertificate *cert_two); +GLIB_AVAILABLE_IN_2_70 +GDateTime *g_tls_certificate_get_not_valid_before (GTlsCertificate *cert); + +GLIB_AVAILABLE_IN_2_70 +GDateTime *g_tls_certificate_get_not_valid_after (GTlsCertificate *cert); + +GLIB_AVAILABLE_IN_2_70 +gchar *g_tls_certificate_get_subject_name (GTlsCertificate *cert); + +GLIB_AVAILABLE_IN_2_70 +gchar *g_tls_certificate_get_issuer_name (GTlsCertificate *cert); + +GLIB_AVAILABLE_IN_2_70 +GPtrArray *g_tls_certificate_get_dns_names (GTlsCertificate *cert); + +GLIB_AVAILABLE_IN_2_70 +GPtrArray *g_tls_certificate_get_ip_addresses (GTlsCertificate *cert); + G_END_DECLS #endif /* __G_TLS_CERTIFICATE_H__ */ diff --git a/gio/gtlsconnection.c b/gio/gtlsconnection.c index 5654ca9ee..0239489b7 100644 --- a/gio/gtlsconnection.c +++ b/gio/gtlsconnection.c @@ -55,12 +55,7 @@ * Since: 2.28 */ -struct _GTlsConnectionPrivate -{ - gchar *negotiated_protocol; -}; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GTlsConnection, g_tls_connection, G_TYPE_IO_STREAM) +G_DEFINE_ABSTRACT_TYPE (GTlsConnection, g_tls_connection, G_TYPE_IO_STREAM) static void g_tls_connection_get_property (GObject *object, guint prop_id, @@ -70,7 +65,6 @@ static void g_tls_connection_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); -static void g_tls_connection_finalize (GObject *object); enum { ACCEPT_CERTIFICATE, @@ -93,6 +87,8 @@ enum { PROP_PEER_CERTIFICATE_ERRORS, PROP_ADVERTISED_PROTOCOLS, PROP_NEGOTIATED_PROTOCOL, + PROP_PROTOCOL_VERSION, + PROP_CIPHERSUITE_NAME, }; static void @@ -102,7 +98,6 @@ g_tls_connection_class_init (GTlsConnectionClass *klass) gobject_class->get_property = g_tls_connection_get_property; gobject_class->set_property = g_tls_connection_set_property; - gobject_class->finalize = g_tls_connection_finalize; /** * GTlsConnection:base-io-stream: @@ -296,6 +291,37 @@ g_tls_connection_class_init (GTlsConnectionClass *klass) G_PARAM_STATIC_STRINGS)); /** + * GTlsConnection:protocol-version: + * + * The TLS protocol version in use. See g_tls_connection_get_protocol_version(). + * + * Since: 2.70 + */ + g_object_class_install_property (gobject_class, PROP_PROTOCOL_VERSION, + g_param_spec_enum ("protocol-version", + P_("Protocol Version"), + P_("TLS protocol version negotiated for this connection"), + G_TYPE_TLS_PROTOCOL_VERSION, + G_TLS_PROTOCOL_VERSION_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * GTlsConnection:ciphersuite-name: (nullable) + * + * The name of the TLS ciphersuite in use. See g_tls_connection_get_ciphersuite_name(). + * + * Since: 2.70 + */ + g_object_class_install_property (gobject_class, PROP_CIPHERSUITE_NAME, + g_param_spec_string ("ciphersuite-name", + P_("Ciphersuite Name"), + P_("Name of ciphersuite negotiated for this connection"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** * GTlsConnection::accept-certificate: * @conn: a #GTlsConnection * @peer_cert: the peer's #GTlsCertificate @@ -380,17 +406,6 @@ g_tls_connection_set_property (GObject *object, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } -static void -g_tls_connection_finalize (GObject *object) -{ - GTlsConnection *conn = G_TLS_CONNECTION(object); - GTlsConnectionPrivate *priv = g_tls_connection_get_instance_private (conn); - - g_clear_pointer (&priv->negotiated_protocol, g_free); - - G_OBJECT_CLASS (g_tls_connection_parent_class)->finalize (object); -} - /** * g_tls_connection_set_use_system_certdb: * @conn: a #GTlsConnection @@ -838,31 +853,15 @@ g_tls_connection_set_advertised_protocols (GTlsConnection *conn, const gchar * g_tls_connection_get_negotiated_protocol (GTlsConnection *conn) { - GTlsConnectionPrivate *priv; - gchar *protocol; + GTlsConnectionClass *class; g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), NULL); - g_object_get (G_OBJECT (conn), - "negotiated-protocol", &protocol, - NULL); - - /* - * Cache the property internally so we can return a `const` pointer - * to the caller. - */ - priv = g_tls_connection_get_instance_private (conn); - if (g_strcmp0 (priv->negotiated_protocol, protocol) != 0) - { - g_free (priv->negotiated_protocol); - priv->negotiated_protocol = protocol; - } - else - { - g_free (protocol); - } + class = G_TLS_CONNECTION_GET_CLASS (conn); + if (class->get_negotiated_protocol == NULL) + return NULL; - return priv->negotiated_protocol; + return class->get_negotiated_protocol (conn); } /** @@ -1029,6 +1028,69 @@ g_tls_connection_handshake_finish (GTlsConnection *conn, } /** + * g_tls_connection_get_protocol_version: + * @conn: a #GTlsConnection + * + * Returns the current TLS protocol version, which may be + * %G_TLS_PROTOCOL_VERSION_UNKNOWN if the connection has not handshaked, or + * has been closed, or if the TLS backend has implemented a protocol version + * that is not a recognized #GTlsProtocolVersion. + * + * Returns: The current TLS protocol version + * + * Since: 2.70 + */ +GTlsProtocolVersion +g_tls_connection_get_protocol_version (GTlsConnection *conn) +{ + GTlsProtocolVersion protocol_version; + GEnumClass *enum_class; + GEnumValue *enum_value; + + g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), G_TLS_PROTOCOL_VERSION_UNKNOWN); + + g_object_get (G_OBJECT (conn), + "protocol-version", &protocol_version, + NULL); + + /* Convert unknown values to G_TLS_PROTOCOL_VERSION_UNKNOWN. */ + enum_class = g_type_class_peek_static (G_TYPE_TLS_PROTOCOL_VERSION); + enum_value = g_enum_get_value (enum_class, protocol_version); + return enum_value ? protocol_version : G_TLS_PROTOCOL_VERSION_UNKNOWN; +} + +/** + * g_tls_connection_get_ciphersuite_name: + * @conn: a #GTlsConnection + * + * Returns the name of the current TLS ciphersuite, or %NULL if the + * connection has not handshaked or has been closed. Beware that the TLS + * backend may use any of multiple different naming conventions, because + * OpenSSL and GnuTLS have their own ciphersuite naming conventions that + * are different from each other and different from the standard, IANA- + * registered ciphersuite names. The ciphersuite name is intended to be + * displayed to the user for informative purposes only, and parsing it + * is not recommended. + * + * Returns: (nullable): The name of the current TLS ciphersuite, or %NULL + * + * Since: 2.70 + */ +gchar * +g_tls_connection_get_ciphersuite_name (GTlsConnection *conn) +{ + gchar *ciphersuite_name; + + g_return_val_if_fail (G_IS_TLS_CONNECTION (conn), NULL); + + g_object_get (G_OBJECT (conn), + "ciphersuite-name", &ciphersuite_name, + NULL); + + return g_steal_pointer (&ciphersuite_name); +} + +/** * g_tls_error_quark: * * Gets the TLS error quark. diff --git a/gio/gtlsconnection.h b/gio/gtlsconnection.h index 037222733..526eb60b5 100644 --- a/gio/gtlsconnection.h +++ b/gio/gtlsconnection.h @@ -43,6 +43,20 @@ struct _GTlsConnection { GTlsConnectionPrivate *priv; }; +/** + * GTlsConnectionClass: + * @parent_class: The parent class. + * @accept_certificate: Check whether to accept a certificate. + * @handshake: Perform a handshake operation. + * @handshake_async: Start an asynchronous handshake operation. + * @handshake_finish: Finish an asynchronous handshake operation. + * @get_binding_data: Retrieve TLS channel binding data (Since: 2.66) + * @get_negotiated_protocol: Get ALPN-negotiated protocol (Since: 2.70) + * + * The class structure for the #GTlsConnection type. + * + * Since: 2.28 + */ struct _GTlsConnectionClass { GIOStreamClass parent_class; @@ -73,9 +87,11 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS GError **error); G_GNUC_END_IGNORE_DEPRECATIONS + const gchar *(*get_negotiated_protocol) (GTlsConnection *conn); + /*< private >*/ /* Padding for future expansion */ - gpointer padding[7]; + gpointer padding[6]; }; GLIB_AVAILABLE_IN_ALL @@ -155,6 +171,12 @@ gboolean g_tls_connection_handshake_finish (GTlsConnecti GAsyncResult *result, GError **error); +GLIB_AVAILABLE_IN_2_70 +GTlsProtocolVersion g_tls_connection_get_protocol_version (GTlsConnection *conn); + +GLIB_AVAILABLE_IN_2_70 +gchar * g_tls_connection_get_ciphersuite_name (GTlsConnection *conn); + /** * G_TLS_ERROR: * diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c index 948e812df..f705bcb3f 100644 --- a/gio/gtlspassword.c +++ b/gio/gtlspassword.c @@ -241,9 +241,9 @@ g_tls_password_new (GTlsPasswordFlags flags, } /** - * g_tls_password_get_value: + * g_tls_password_get_value: (virtual get_value) * @password: a #GTlsPassword object - * @length: (nullable): location to place the length of the password. + * @length: (optional): location to place the length of the password. * * Get the password value. If @length is not %NULL then it will be * filled in with the length of the password value. (Note that the @@ -251,7 +251,7 @@ g_tls_password_new (GTlsPasswordFlags flags, * for @length in contexts where you know the password will have a * certain fixed length.) * - * Returns: The password value (owned by the password object). + * Returns: (array length=length): The password value (owned by the password object). * * Since: 2.30 */ diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c index 32b936259..46a41fc41 100644 --- a/gio/gunixmounts.c +++ b/gio/gunixmounts.c @@ -1593,7 +1593,9 @@ g_unix_mounts_get (guint64 *time_read) * If more mounts have the same mount path, the last matching mount * is returned. * - * Returns: (transfer full): a #GUnixMountEntry. + * This will return %NULL if there is no mount point at @mount_path. + * + * Returns: (transfer full) (nullable): a #GUnixMountEntry. **/ GUnixMountEntry * g_unix_mount_at (const char *mount_path, @@ -1636,7 +1638,10 @@ g_unix_mount_at (const char *mount_path, * If more mounts have the same mount path, the last matching mount * is returned. * - * Returns: (transfer full): a #GUnixMountEntry. + * This will return %NULL if looking up the mount entry fails, if + * @file_path doesn’t exist or there is an I/O error. + * + * Returns: (transfer full) (nullable): a #GUnixMountEntry. * * Since: 2.52 **/ diff --git a/gio/gunixsocketaddress.c b/gio/gunixsocketaddress.c index 0ab1a62e9..69204e9b9 100644 --- a/gio/gunixsocketaddress.c +++ b/gio/gunixsocketaddress.c @@ -214,7 +214,8 @@ g_unix_socket_address_to_native (GSocketAddress *address, gssize socklen; socklen = g_unix_socket_address_get_native_size (address); - if (destlen < socklen) + g_assert (socklen >= 0); + if (destlen < (gsize) socklen) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE, _("Not enough space for socket address")); diff --git a/gio/gwin32appinfo.c b/gio/gwin32appinfo.c index 3468dfee0..5403225e2 100644 --- a/gio/gwin32appinfo.c +++ b/gio/gwin32appinfo.c @@ -1629,7 +1629,6 @@ process_uwp_verbs (GList *verbs, continue; } - acid = NULL; got_value = g_win32_registry_key_get_value_w (key, g_win32_registry_get_os_dirs_w (), TRUE, @@ -3635,7 +3634,6 @@ grab_registry_string (GWin32RegistryKey *handler_appkey, if (*destination != NULL) return; - value = NULL; if (g_win32_registry_key_get_value_w (handler_appkey, NULL, TRUE, @@ -3830,9 +3828,6 @@ update_registry_data (void) return; } -static void -watch_keys (void); - /* This function is called when any of our registry watchers detect * changes in the registry. */ @@ -3840,7 +3835,6 @@ static void keys_updated (GWin32RegistryKey *key, gpointer user_data) { - watch_keys (); /* Indicate the tree as not up-to-date, push a new job for the AppInfo thread */ g_atomic_int_inc (&gio_win32_appinfo_update_counter); /* We don't use the data pointer, but it must be non-NULL */ @@ -4035,6 +4029,7 @@ gio_win32_appinfo_init (gboolean do_wait) g_mutex_lock (&gio_win32_appinfo_mutex); while (g_atomic_int_get (&gio_win32_appinfo_update_counter) > 0) g_cond_wait (&gio_win32_appinfo_cond, &gio_win32_appinfo_mutex); + watch_keys (); g_mutex_unlock (&gio_win32_appinfo_mutex); } } diff --git a/gio/gwin32mount.c b/gio/gwin32mount.c index 83d8695a1..f5be8adfa 100644 --- a/gio/gwin32mount.c +++ b/gio/gwin32mount.c @@ -25,7 +25,47 @@ #include <string.h> #define WIN32_MEAN_AND_LEAN +#define COBJMACROS #include <windows.h> +#include <shlobj.h> +#include <shlwapi.h> + +/* At the moment of writing IExtractIconW interface in Mingw-w64 + * is missing IUnknown members in its vtable. Use our own + * fixed declaration for now. + */ +#undef INTERFACE +#define INTERFACE IMyExtractIconW +DECLARE_INTERFACE_(IMyExtractIconW,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IMyExtractIconW methods ***/ + STDMETHOD(GetIconLocation)(THIS_ UINT uFlags, LPWSTR pszIconFile, UINT cchMax, int *piIndex, PUINT pwFlags) PURE; + STDMETHOD(Extract)(THIS_ LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) PURE; +}; +#undef INTERFACE + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IMyExtractIconW_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IMyExtractIconW_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IMyExtractIconW_Release(p) (p)->lpVtbl->Release(p) +/*** IMyExtractIconW methods ***/ +#define IMyExtractIconW_GetIconLocation(p,a,b,c,d,e) (p)->lpVtbl->GetIconLocation(p,a,b,c,d,e) +#define IMyExtractIconW_Extract(p,a,b,c,d,e) (p)->lpVtbl->Extract(p,a,b,c,d,e) +#else +/*** IUnknown methods ***/ +#define IMyExtractIconW_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IMyExtractIconW_AddRef(p) (p)->AddRef() +#define IMyExtractIconW_Release(p) (p)->Release() +/*** IMyExtractIconW methods ***/ +#define IMyExtractIconW_GetIconLocation(p,a,b,c,d,e) (p)->GetIconLocation(p,a,b,c,d,e) +#define IMyExtractIconW_Extract(p,a,b,c,d,e) (p)->Extract(p,a,b,c,d,e) +#endif + #include <glib.h> #include "gwin32volumemonitor.h" @@ -103,14 +143,52 @@ g_win32_mount_init (GWin32Mount *win32_mount) { } +/* wdrive doesn't need to end with a path separator. + wdrive must use backslashes as path separators, not slashes. + IShellFolder::ParseDisplayName() takes non-const string as input, + so wdrive can't be a const string. + Returns the name on success (free with g_free), + NULL otherwise. + */ +static gchar * +get_mount_display_name (gunichar2 *wdrive) +{ + IShellFolder *desktop; + PIDLIST_RELATIVE volume; + STRRET volume_name; + gchar *result = NULL; + + /* Get the desktop folder object reference */ + if (!SUCCEEDED (SHGetDesktopFolder (&desktop))) + return result; + + if (SUCCEEDED (IShellFolder_ParseDisplayName (desktop, NULL, NULL, wdrive, NULL, &volume, NULL))) + { + volume_name.uType = STRRET_WSTR; + + if (SUCCEEDED (IShellFolder_GetDisplayNameOf (desktop, volume, SHGDN_FORADDRESSBAR, &volume_name))) + { + wchar_t *volume_name_wchar; + + if (SUCCEEDED (StrRetToStrW (&volume_name, volume, &volume_name_wchar))) + { + result = g_utf16_to_utf8 (volume_name_wchar, -1, NULL, NULL, NULL); + CoTaskMemFree (volume_name_wchar); + } + } + CoTaskMemFree (volume); + } + + IShellFolder_Release (desktop); + + return result; +} + static gchar * _win32_get_displayname (const char *drive) { gunichar2 *wdrive = g_utf8_to_utf16 (drive, -1, NULL, NULL, NULL); - gchar *name = NULL; - SHFILEINFOW sfi; - if (SHGetFileInfoW(wdrive, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME)) - name = g_utf16_to_utf8 (sfi.szDisplayName, -1, NULL, NULL, NULL); + gchar *name = get_mount_display_name (wdrive); g_free (wdrive); return name ? name : g_strdup (drive); @@ -210,6 +288,92 @@ _win32_drive_type_to_icon (int type, gboolean use_symbolic) } } +/* mount_path doesn't need to end with a path separator. + mount_path must use backslashes as path separators, not slashes. + IShellFolder::ParseDisplayName() takes non-const string as input, + so mount_path can't be a const string. + result_name and result_index must not be NULL. + Returns TRUE when result_name is set (free with g_free), + FALSE otherwise. + */ +static gboolean +get_icon_name_index (wchar_t *mount_path, + wchar_t **result_name, + int *result_index) +{ + IShellFolder *desktop; + PIDLIST_RELATIVE volume; + IShellFolder *volume_parent; + PCUITEMID_CHILD volume_relative; + IMyExtractIconW *eicon; + int icon_index; + UINT icon_flags; + wchar_t *name_buffer; + gsize name_buffer_size; + gsize arbitrary_reasonable_limit = 5000; + gboolean result = FALSE; + + *result_name = NULL; + + /* Get the desktop folder object reference */ + if (!SUCCEEDED (SHGetDesktopFolder (&desktop))) + return FALSE; + + /* Construct the volume IDList relative to desktop */ + if (SUCCEEDED (IShellFolder_ParseDisplayName (desktop, NULL, NULL, mount_path, NULL, &volume, NULL))) + { + /* Get the parent of the volume (transfer-full) and the IDList relative to parent (transfer-none) */ + if (SUCCEEDED (SHBindToParent (volume, &IID_IShellFolder, (void **) &volume_parent, &volume_relative))) + { + /* Get a reference to IExtractIcon object for the volume */ + if (SUCCEEDED (IShellFolder_GetUIObjectOf (volume_parent, NULL, 1, (LPCITEMIDLIST *) &volume_relative, &IID_IExtractIconW, NULL, (void **) &eicon))) + { + gboolean keep_going = TRUE; + name_buffer = NULL; + name_buffer_size = MAX_PATH / 2; + while (keep_going) + { + name_buffer_size *= 2; + name_buffer = g_renew (wchar_t, name_buffer, name_buffer_size); + name_buffer[name_buffer_size - 1] = 0x1; /* sentinel */ + keep_going = FALSE; + + /* Try to get the icon location */ + if (SUCCEEDED (IMyExtractIconW_GetIconLocation (eicon, GIL_FORSHELL, name_buffer, name_buffer_size, &icon_index, &icon_flags))) + { + if (name_buffer[name_buffer_size - 1] != 0x1) + { + if (name_buffer_size < arbitrary_reasonable_limit) + { + /* Buffer was too small, keep going */ + keep_going = TRUE; + continue; + } + /* Else stop trying */ + } + /* name_buffer might not contain a name */ + else if ((icon_flags & GIL_NOTFILENAME) != GIL_NOTFILENAME) + { + *result_name = g_steal_pointer (&name_buffer); + *result_index = icon_index; + result = TRUE; + } + } + } + + g_free (name_buffer); + IMyExtractIconW_Release (eicon); + } + IShellFolder_Release (volume_parent); + } + CoTaskMemFree (volume); + } + + IShellFolder_Release (desktop); + + return result; +} + static GIcon * g_win32_mount_get_icon (GMount *mount) { @@ -220,15 +384,20 @@ g_win32_mount_get_icon (GMount *mount) /* lazy creation */ if (!win32_mount->icon) { - SHFILEINFOW shfi; + wchar_t *icon_path; + int icon_index; + wchar_t *p; wchar_t *wfn = g_utf8_to_utf16 (win32_mount->mount_path, -1, NULL, NULL, NULL); - if (SHGetFileInfoW (wfn, 0, &shfi, sizeof (shfi), SHGFI_ICONLOCATION)) + for (p = wfn; p != NULL && *p != 0; p++) + if (*p == L'/') + *p = L'\\'; + + if (get_icon_name_index (wfn, &icon_path, &icon_index)) { - gchar *name = g_utf16_to_utf8 (shfi.szDisplayName, -1, NULL, NULL, NULL); - gchar *id = g_strdup_printf ("%s,%i", name, shfi.iIcon); + gchar *id = g_strdup_printf ("%S,%i", icon_path, icon_index); + g_free (icon_path); win32_mount->icon = g_themed_icon_new (id); - g_free (name); g_free (id); } else diff --git a/gio/gwin32packageparser.c b/gio/gwin32packageparser.c index ee05bb1dd..ad5302270 100755 --- a/gio/gwin32packageparser.c +++ b/gio/gwin32packageparser.c @@ -390,7 +390,7 @@ g_win32_package_parser_enum_packages (GWin32PackageParserCallback callback, wcs_path = LoadedWindowsGetStringRawBuffer (path, NULL); manifest_filename_size = wcslen (wcs_path) + wcslen (bslash_appmanifest); manifest_filename = g_new (wchar_t, manifest_filename_size + 1); - memcpy (manifest_filename, wcs_path, wcslen (wcs_path) * sizeof (wchar_t)); + memcpy (manifest_filename, wcs_path, manifest_filename_size * sizeof (wchar_t)); memcpy (&manifest_filename[wcslen (wcs_path)], bslash_appmanifest, (wcslen (bslash_appmanifest) + 1) * sizeof (wchar_t)); memset (sax, 0, sizeof (*sax)); diff --git a/gio/gwin32registrykey.c b/gio/gwin32registrykey.c index 5e2b006dd..398d8f45b 100644 --- a/gio/gwin32registrykey.c +++ b/gio/gwin32registrykey.c @@ -2425,20 +2425,17 @@ key_changed (PVOID closure, ULONG reserved) { GWin32RegistryKey *key = G_WIN32_REGISTRY_KEY (closure); - gpointer user_data; - GWin32RegistryKeyWatchCallbackFunc callback; - - callback = g_steal_pointer (&key->priv->callback); - user_data = g_steal_pointer (&key->priv->user_data); g_free (status_block); g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_CHANGED); g_atomic_int_set (&key->priv->watch_indicator, G_WIN32_KEY_UNWATCHED); key->priv->update_flags = G_WIN32_REGISTRY_UPDATED_NOTHING; - if (callback) - callback (key, user_data); + if (key->priv->callback) + key->priv->callback (key, key->priv->user_data); + key->priv->callback = NULL; + key->priv->user_data = NULL; g_object_unref (key); } @@ -2553,7 +2550,9 @@ g_win32_registry_key_watch (GWin32RegistryKey *key, 0, TRUE); - if (status == STATUS_PENDING || status == STATUS_SUCCESS) + g_assert (status != STATUS_SUCCESS); + + if (status == STATUS_PENDING) return TRUE; g_atomic_int_set (&key->priv->change_indicator, G_WIN32_KEY_UNKNOWN); diff --git a/gio/tests/actions.c b/gio/tests/actions.c index c183c7aa1..91fc08074 100644 --- a/gio/tests/actions.c +++ b/gio/tests/actions.c @@ -151,7 +151,7 @@ strv_strv_cmp (gchar **a, gchar **b) static gboolean strv_set_equal (gchar **strv, ...) { - gint count; + guint count; va_list list; const gchar *str; gboolean res; @@ -372,10 +372,10 @@ static void test_entries (void) { const GActionEntry entries[] = { - { "foo", activate_foo }, - { "bar", activate_bar, "s" }, - { "toggle", NULL, NULL, "false" }, - { "volume", NULL, NULL, "0", change_volume_state } + { "foo", activate_foo, NULL, NULL, NULL, { 0 } }, + { "bar", activate_bar, "s", NULL, NULL, { 0 } }, + { "toggle", NULL, NULL, "false", NULL, { 0 } }, + { "volume", NULL, NULL, "0", change_volume_state, { 0 } }, }; GSimpleActionGroup *actions; GVariant *state; @@ -399,10 +399,10 @@ test_entries (void) if (g_test_undefined ()) { const GActionEntry bad_type = { - "bad-type", NULL, "ss" + "bad-type", NULL, "ss", NULL, NULL, { 0 } }; const GActionEntry bad_state = { - "bad-state", NULL, NULL, "flse" + "bad-state", NULL, NULL, "flse", NULL, { 0 } }; g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, @@ -468,7 +468,7 @@ test_parse_detailed (void) { "abc(42, 4)", "abc", "(42, 4)", "expected end of input", NULL }, { "abc(42,)", "abc", "(42,)", "expected end of input", NULL } }; - gint i; + gsize i; for (i = 0; i < G_N_ELEMENTS (testcases); i++) { @@ -638,13 +638,13 @@ stop_loop (gpointer data) } static GActionEntry exported_entries[] = { - { "undo", activate_action, NULL, NULL, NULL }, - { "redo", activate_action, NULL, NULL, NULL }, - { "cut", activate_action, NULL, NULL, NULL }, - { "copy", activate_action, NULL, NULL, NULL }, - { "paste", activate_action, NULL, NULL, NULL }, - { "bold", activate_toggle, NULL, "true", NULL }, - { "lang", activate_radio, "s", "'latin'", NULL }, + { "undo", activate_action, NULL, NULL, NULL, { 0 } }, + { "redo", activate_action, NULL, NULL, NULL, { 0 } }, + { "cut", activate_action, NULL, NULL, NULL, { 0 } }, + { "copy", activate_action, NULL, NULL, NULL, { 0 } }, + { "paste", activate_action, NULL, NULL, NULL, { 0 } }, + { "bold", activate_toggle, NULL, "true", NULL, { 0 } }, + { "lang", activate_radio, "s", "'latin'", NULL, { 0 } }, }; static void @@ -920,8 +920,8 @@ test_dbus_threaded (void) GSimpleActionGroup *group[10]; GThread *export[10]; static GActionEntry entries[] = { - { "a", activate_action, NULL, NULL, NULL }, - { "b", activate_action, NULL, NULL, NULL }, + { "a", activate_action, NULL, NULL, NULL, { 0 } }, + { "b", activate_action, NULL, NULL, NULL, { 0 } }, }; gint i; diff --git a/gio/tests/appinfo.c b/gio/tests/appinfo.c index 2f0f43074..bd76729c4 100644 --- a/gio/tests/appinfo.c +++ b/gio/tests/appinfo.c @@ -104,7 +104,7 @@ test_launch_no_app_id (void) "Exec=%s/appinfo-test --option %%u %%i --name %%c --filename %%k %%m %%%%", g_test_get_dir (G_TEST_BUILT)); - g_test_bug ("791337"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=791337"); for (i = 0; i < G_N_ELEMENTS (exec_line_variants); i++) { @@ -581,7 +581,6 @@ main (int argc, char *argv[]) g_setenv ("XDG_CURRENT_DESKTOP", "GNOME", TRUE); g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL); - g_test_bug_base ("https://bugzilla.gnome.org/show_bug.cgi?id="); g_test_add_func ("/appinfo/basic", test_basic); g_test_add_func ("/appinfo/text", test_text); diff --git a/gio/tests/async-close-output-stream.c b/gio/tests/async-close-output-stream.c index 00e068766..a14c413c2 100644 --- a/gio/tests/async-close-output-stream.c +++ b/gio/tests/async-close-output-stream.c @@ -164,7 +164,7 @@ test_without_flush (SetupData *data, { prepare_data (data, FALSE); - g_test_bug ("617937"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=617937"); /* just close asynchronously */ g_output_stream_close_async (data->conv_stream, @@ -181,7 +181,7 @@ test_with_flush (SetupData *data, gconstpointer user_data) { GError *error = NULL; - g_test_bug ("617937"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=617937"); prepare_data (data, TRUE); @@ -222,7 +222,7 @@ static void test_with_async_flush (SetupData *data, gconstpointer user_data) { - g_test_bug ("617937"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=617937"); prepare_data (data, TRUE); @@ -244,8 +244,6 @@ main (int argc, g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); - data = g_slice_new (SetupData); /* test closing asynchronously without flushing manually */ diff --git a/gio/tests/basic-application.c b/gio/tests/basic-application.c index 94100eb5f..362b2fd51 100644 --- a/gio/tests/basic-application.c +++ b/gio/tests/basic-application.c @@ -54,10 +54,10 @@ static void startup (GApplication *app) { static GActionEntry actions[] = { - { "new", new_activated, NULL, NULL, NULL }, - { "quit", quit_activated, NULL, NULL, NULL }, - { "action1", action1_activated, NULL, NULL, NULL }, - { "action2", action2_activated, "b", "false", change_action2 } + { "new", new_activated, NULL, NULL, NULL, { 0 } }, + { "quit", quit_activated, NULL, NULL, NULL, { 0 } }, + { "action1", action1_activated, NULL, NULL, NULL, { 0 } }, + { "action2", action2_activated, "b", "false", change_action2, { 0 } } }; g_action_map_add_action_entries (G_ACTION_MAP (app), diff --git a/gio/tests/buffered-input-stream.c b/gio/tests/buffered-input-stream.c index ef865fc45..ee084b3b7 100644 --- a/gio/tests/buffered-input-stream.c +++ b/gio/tests/buffered-input-stream.c @@ -126,7 +126,7 @@ test_read_byte (void) GInputStream *in; GError *error; - g_test_bug ("562393"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=562393"); base = g_memory_input_stream_new_from_data ("abcdefgh", -1, NULL); in = g_buffered_input_stream_new (base); @@ -536,7 +536,6 @@ main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ("/buffered-input-stream/peek", test_peek); g_test_add_func ("/buffered-input-stream/peek-buffer", test_peek_buffer); diff --git a/gio/tests/contenttype.c b/gio/tests/contenttype.c index 71e8b0df6..db34f1da8 100644 --- a/gio/tests/contenttype.c +++ b/gio/tests/contenttype.c @@ -363,7 +363,7 @@ test_tree (void) const gchar *path; GFile *file; gchar **types; - gint i; + gsize i; #ifdef __APPLE__ g_test_skip ("The OSX backend does not implement g_content_type_guess_for_tree()"); @@ -390,7 +390,7 @@ test_type_is_a_special_case (void) #else gboolean res; - g_test_bug ("782311"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=782311"); /* Everything but the inode type is application/octet-stream */ res = g_content_type_is_a ("inode/directory", "application/octet-stream"); @@ -463,8 +463,6 @@ main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); - g_test_add_func ("/contenttype/guess", test_guess); g_test_add_func ("/contenttype/guess_svg_from_data", test_guess_svg_from_data); g_test_add_func ("/contenttype/mime_from_content", test_mime_from_content); diff --git a/gio/tests/contexts.c b/gio/tests/contexts.c index c6dc26111..3b64c7622 100644 --- a/gio/tests/contexts.c +++ b/gio/tests/contexts.c @@ -360,7 +360,8 @@ test_context_specific_emit (void) { GThread *threads[N_THREADS]; gboolean exited = FALSE; - guint i, n; + gsize i; + gint k, n; for (i = 0; i < N_THREADS; i++) threads[i] = g_thread_new ("test", test_emit_thread, &observed_values[i]); @@ -368,7 +369,7 @@ test_context_specific_emit (void) /* make changes and ensure that they are observed */ for (n = 0; n < 1000; n++) { - guint64 expiry; + gint64 expiry; /* don't burn CPU forever */ expiry = g_get_monotonic_time () + 10 * G_TIME_SPAN_SECOND; @@ -376,7 +377,7 @@ test_context_specific_emit (void) g_atomic_int_set (¤t_value, n); /* wake them to notice */ - for (i = 0; i < g_test_rand_int_range (1, 5); i++) + for (k = 0; k < g_test_rand_int_range (1, 5); k++) g_context_specific_group_emit (&group, g_signal_lookup ("changed", per_thread_thing_get_type ())); for (i = 0; i < N_THREADS; i++) diff --git a/gio/tests/converter-stream.c b/gio/tests/converter-stream.c index 8bec95c76..cf1853ba0 100644 --- a/gio/tests/converter-stream.c +++ b/gio/tests/converter-stream.c @@ -94,7 +94,7 @@ g_expander_converter_convert (GConverter *converter, { const guint8 *in, *in_end; guint8 v, *out; - int i; + gsize i; gsize block_size; in = inbuf; @@ -210,7 +210,7 @@ g_compressor_converter_convert (GConverter *converter, { const guint8 *in, *in_end; guint8 v, *out; - int i; + gsize i; gsize block_size; in = inbuf; @@ -231,7 +231,7 @@ g_compressor_converter_convert (GConverter *converter, block_size = v * 1000; /* Not enough data */ - if (in_end - in < block_size) + if ((gsize) (in_end - in) < block_size) { if (*bytes_read > 0) break; @@ -254,7 +254,7 @@ g_compressor_converter_convert (GConverter *converter, } } - if (v == 0 && in_end - in == block_size && (flags & G_CONVERTER_INPUT_AT_END) == 0) + if (v == 0 && (gsize) (in_end - in) == block_size && (flags & G_CONVERTER_INPUT_AT_END) == 0) { if (*bytes_read > 0) break; @@ -297,7 +297,7 @@ test_expander (void) GConverter *expander; GConverter *converter; GError *error; - int i; + gsize i; expander = g_expander_converter_new (); @@ -393,7 +393,7 @@ test_compressor (void) GOutputStream *mem_out, *cstream_out; GConverter *expander, *compressor; GError *error; - int i; + gsize i; expander = g_expander_converter_new (); expanded = g_malloc (100*1000); /* Large enough */ @@ -748,7 +748,7 @@ test_roundtrip (gconstpointer data) GFileInfo *info; GFileInfo *info2; - g_test_bug ("619945"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=619945"); data0 = g_malloc (DATA_LENGTH * sizeof (guint32)); for (i = 0; i < DATA_LENGTH; i++) @@ -972,7 +972,7 @@ test_converter_pollable (void) GPollableOutputStream *pollable_out; GConverter *expander, *compressor; GError *error; - int i; + gsize i; expander = g_expander_converter_new (); expanded = g_malloc (100*1000); /* Large enough */ @@ -1207,12 +1207,10 @@ main (int argc, { "/converter-input-stream/charset/fallbacks", "UTF-8", "Some characters just don't fit into latin1: πא", "ISO-8859-1", "Some characters just don't fit into latin1: \\CF\\80\\D7\\90", 4 }, }; - gint i; + gsize i; g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); - g_test_add_func ("/converter/basics", test_converter_basics); g_test_add_func ("/converter-input-stream/expander", test_expander); g_test_add_func ("/converter-input-stream/compressor", test_compressor); diff --git a/gio/tests/dbus-appinfo.c b/gio/tests/dbus-appinfo.c index 7e2fc4d79..86bdfebee 100644 --- a/gio/tests/dbus-appinfo.c +++ b/gio/tests/dbus-appinfo.c @@ -174,10 +174,10 @@ test_application_quit (GSimpleAction *action, } static const GActionEntry app_actions[] = { - { "frob", test_application_frob }, - { "tweak", test_application_tweak }, - { "twiddle", test_application_twiddle }, - { "quit", test_application_quit } + { "frob", test_application_frob, NULL, NULL, NULL, { 0 } }, + { "tweak", test_application_tweak, NULL, NULL, NULL, { 0 } }, + { "twiddle", test_application_twiddle, NULL, NULL, NULL, { 0 } }, + { "quit", test_application_quit, NULL, NULL, NULL, { 0 } } }; static void diff --git a/gio/tests/echo-server.c b/gio/tests/echo-server.c index 7634b5bb0..83d1d32db 100644 --- a/gio/tests/echo-server.c +++ b/gio/tests/echo-server.c @@ -7,7 +7,7 @@ int port = 7777; static GOptionEntry cmd_entries[] = { {"port", 'p', 0, G_OPTION_ARG_INT, &port, "Local port to bind to", NULL}, - {NULL} + G_OPTION_ENTRY_NULL }; diff --git a/gio/tests/fake-service-name.c b/gio/tests/fake-service-name.c index 1a601a50c..c3a61180c 100644 --- a/gio/tests/fake-service-name.c +++ b/gio/tests/fake-service-name.c @@ -51,7 +51,8 @@ incoming_method_call (GDBusConnection *connection, static const GDBusInterfaceVTable interface_vtable = { incoming_method_call, NULL, - NULL + NULL, + { 0 } }; static void diff --git a/gio/tests/file.c b/gio/tests/file.c index c8bbed151..2f1b7b310 100644 --- a/gio/tests/file.c +++ b/gio/tests/file.c @@ -1,3 +1,4 @@ +#include <locale.h> #include <string.h> #include <stdio.h> #include <stdlib.h> @@ -174,7 +175,7 @@ typedef struct gint monitor_deleted; gint monitor_changed; gchar *monitor_path; - gint pos; + gsize pos; const gchar *data; gchar *buffer; guint timeout; @@ -3008,6 +3009,8 @@ test_build_attribute_list_for_copy (void) int main (int argc, char *argv[]) { + setlocale (LC_ALL, ""); + g_test_init (&argc, &argv, NULL); g_test_add_func ("/file/basic", test_basic); diff --git a/gio/tests/filter-cat.c b/gio/tests/filter-cat.c index 2cd02b7a2..0bc713735 100644 --- a/gio/tests/filter-cat.c +++ b/gio/tests/filter-cat.c @@ -54,7 +54,7 @@ static GOptionEntry entries[] = { {"to-charset", 0, 0, G_OPTION_ARG_STRING, &to_charset, "to charset", NULL}, {"fallback", 0, 0, G_OPTION_ARG_NONE, &fallback, "use fallback", NULL}, {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &locations, "locations", NULL}, - {NULL} + G_OPTION_ENTRY_NULL }; static void diff --git a/gio/tests/filter-streams.c b/gio/tests/filter-streams.c index e3e67ea18..1f94dc222 100644 --- a/gio/tests/filter-streams.c +++ b/gio/tests/filter-streams.c @@ -68,7 +68,7 @@ test_input_filter (void) gchar buf[1024]; GError *error = NULL; - g_test_bug ("568394"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=568394"); base = g_memory_input_stream_new_from_data ("abcdefghijk", -1, NULL); f1 = g_object_new (TEST_TYPE_FILTER_INPUT_STREAM, "base-stream", base, @@ -381,7 +381,6 @@ int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ("/filter-stream/input", test_input_filter); g_test_add_func ("/filter-stream/output", test_output_filter); diff --git a/gio/tests/g-file-info-filesystem-readonly.c b/gio/tests/g-file-info-filesystem-readonly.c index 16fa83e33..9b94c3220 100644 --- a/gio/tests/g-file-info-filesystem-readonly.c +++ b/gio/tests/g-file-info-filesystem-readonly.c @@ -225,8 +225,7 @@ main (int argc, char *argv[]) g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); - g_test_bug ("787731"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=787731"); g_test_add_data_func ("/g-file-info-filesystem-readonly/test-fs-ro", GINT_TO_POINTER (FALSE), test_filesystem_readonly); diff --git a/gio/tests/g-file-info.c b/gio/tests/g-file-info.c index 1a02b5e0e..c11c50462 100644 --- a/gio/tests/g-file-info.c +++ b/gio/tests/g-file-info.c @@ -201,6 +201,153 @@ test_g_file_info_modification_time (void) g_date_time_unref (dt_new_usecs); } +static void +test_g_file_info_access_time (void) +{ + GFile *file = NULL; + GFileIOStream *io_stream = NULL; + GFileInfo *info = NULL; + GDateTime *dt = NULL, *dt_usecs = NULL, *dt_new = NULL, *dt_new_usecs = NULL, + *dt_before_epoch = NULL, *dt_before_epoch_returned = NULL; + GTimeSpan ts; + GError *error = NULL; + + g_test_summary ("Test that getting the access time of a file works."); + + file = g_file_new_tmp ("g-file-info-test-XXXXXX", &io_stream, &error); + g_assert_no_error (error); + + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_TIME_ACCESS, + G_FILE_QUERY_INFO_NONE, + NULL, &error); + g_assert_no_error (error); + + /* Check the access time is retrievable. */ + dt = g_file_info_get_access_date_time (info); + g_assert_nonnull (dt); + + /* Try again with microsecond precision. */ + g_clear_object (&info); + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_TIME_ACCESS "," G_FILE_ATTRIBUTE_TIME_ACCESS_USEC, + G_FILE_QUERY_INFO_NONE, + NULL, &error); + g_assert_no_error (error); + + dt_usecs = g_file_info_get_access_date_time (info); + g_assert_nonnull (dt_usecs); + + ts = g_date_time_difference (dt_usecs, dt); + g_assert_cmpint (ts, >, 0); + g_assert_cmpint (ts, <, G_USEC_PER_SEC); + + /* Try round-tripping the access time. */ + dt_new = g_date_time_add (dt_usecs, G_USEC_PER_SEC + 50); + g_file_info_set_access_date_time (info, dt_new); + + dt_new_usecs = g_file_info_get_access_date_time (info); + ts = g_date_time_difference (dt_new_usecs, dt_new); + g_assert_cmpint (ts, ==, 0); + + // try with a negative timestamp + dt_before_epoch = g_date_time_new_from_unix_utc (-10000); + g_file_info_set_access_date_time (info, dt_before_epoch); + dt_before_epoch_returned = g_file_info_get_access_date_time (info); + ts = g_date_time_difference (dt_before_epoch, dt_before_epoch_returned); + g_assert_cmpint (ts, ==, 0); + + /* Clean up. */ + g_clear_object (&io_stream); + g_file_delete (file, NULL, NULL); + g_clear_object (&file); + + g_clear_object (&info); + g_date_time_unref (dt); + g_date_time_unref (dt_usecs); + g_date_time_unref (dt_new); + g_date_time_unref (dt_new_usecs); + g_date_time_unref (dt_before_epoch); + g_date_time_unref (dt_before_epoch_returned); +} + +static void +test_g_file_info_creation_time (void) +{ + GFile *file = NULL; + GFileIOStream *io_stream = NULL; + GFileInfo *info = NULL; + GDateTime *dt = NULL, *dt_usecs = NULL, *dt_new = NULL, *dt_new_usecs = NULL, + *dt_before_epoch = NULL, *dt_before_epoch_returned = NULL; + GTimeSpan ts; + GError *error = NULL; + + g_test_summary ("Test that getting the creation time of a file works."); + + file = g_file_new_tmp ("g-file-info-test-XXXXXX", &io_stream, &error); + g_assert_no_error (error); + + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_TIME_CREATED, + G_FILE_QUERY_INFO_NONE, + NULL, &error); + g_assert_no_error (error); + + /* Check the creation time is retrievable. */ + dt = g_file_info_get_creation_date_time (info); + if (!dt) + { + g_test_skip ("Skipping testing creation time as it’s not supported by the kernel"); + g_file_delete (file, NULL, NULL); + g_clear_object (&file); + g_clear_object (&info); + return; + } + + /* Try again with microsecond precision. */ + g_clear_object (&info); + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_TIME_CREATED "," G_FILE_ATTRIBUTE_TIME_CREATED_USEC, + G_FILE_QUERY_INFO_NONE, + NULL, &error); + g_assert_no_error (error); + + dt_usecs = g_file_info_get_creation_date_time (info); + g_assert_nonnull (dt_usecs); + + ts = g_date_time_difference (dt_usecs, dt); + g_assert_cmpint (ts, >, 0); + g_assert_cmpint (ts, <, G_USEC_PER_SEC); + + /* Try round-tripping the creation time. */ + dt_new = g_date_time_add (dt_usecs, G_USEC_PER_SEC + 50); + g_file_info_set_creation_date_time (info, dt_new); + + dt_new_usecs = g_file_info_get_creation_date_time (info); + ts = g_date_time_difference (dt_new_usecs, dt_new); + g_assert_cmpint (ts, ==, 0); + + // try with a negative timestamp + dt_before_epoch = g_date_time_new_from_unix_utc (-10000); + g_file_info_set_creation_date_time (info, dt_before_epoch); + dt_before_epoch_returned = g_file_info_get_creation_date_time (info); + ts = g_date_time_difference (dt_before_epoch, dt_before_epoch_returned); + g_assert_cmpint (ts, ==, 0); + + /* Clean up. */ + g_clear_object (&io_stream); + g_file_delete (file, NULL, NULL); + g_clear_object (&file); + + g_clear_object (&info); + g_date_time_unref (dt); + g_date_time_unref (dt_usecs); + g_date_time_unref (dt_new); + g_date_time_unref (dt_new_usecs); + g_date_time_unref (dt_before_epoch); + g_date_time_unref (dt_before_epoch_returned); +} + #ifdef G_OS_WIN32 static void test_internal_enhanced_stdio (void) @@ -746,6 +893,8 @@ main (int argc, g_test_add_func ("/g-file-info/test_g_file_info", test_g_file_info); g_test_add_func ("/g-file-info/test_g_file_info/modification-time", test_g_file_info_modification_time); + g_test_add_func ("/g-file-info/test_g_file_info/access-time", test_g_file_info_access_time); + g_test_add_func ("/g-file-info/test_g_file_info/creation-time", test_g_file_info_creation_time); #ifdef G_OS_WIN32 g_test_add_func ("/g-file-info/internal-enhanced-stdio", test_internal_enhanced_stdio); #endif diff --git a/gio/tests/g-file.c b/gio/tests/g-file.c index f87c1b1d8..8669e3aaf 100644 --- a/gio/tests/g-file.c +++ b/gio/tests/g-file.c @@ -111,21 +111,21 @@ test_g_file_new_for_path (void) { const struct TestPathsWithOper cmp_paths[] = { - {"/", TRUE, 0, "/./"}, - {"//", TRUE, 0, "//"}, - {"//", TRUE, 0, "//./"}, - {"/", TRUE, 0, "/.//"}, - {"/", TRUE, 0, "/././"}, - {"/tmp", TRUE, 0, "/tmp/d/../"}, - {"/", TRUE, 0, "/somedir/../"}, - {"/", FALSE, 0, "/somedir/.../"}, - {"//tmp/dir1", TRUE, 0, "//tmp/dir1"}, - {"/tmp/dir1", TRUE, 0, "///tmp/dir1"}, - {"/tmp/dir1", TRUE, 0, "////tmp/dir1"}, - {"/tmp/dir1", TRUE, 0, "/tmp/./dir1"}, - {"/tmp/dir1", TRUE, 0, "/tmp//dir1"}, - {"/tmp/dir1", TRUE, 0, "/tmp///dir1///"}, - {"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", TRUE, 0, "/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88/"} + {"/", TRUE, 0, "/./", NULL }, + {"//", TRUE, 0, "//", NULL }, + {"//", TRUE, 0, "//./", NULL }, + {"/", TRUE, 0, "/.//", NULL }, + {"/", TRUE, 0, "/././", NULL }, + {"/tmp", TRUE, 0, "/tmp/d/../", NULL }, + {"/", TRUE, 0, "/somedir/../", NULL }, + {"/", FALSE, 0, "/somedir/.../", NULL }, + {"//tmp/dir1", TRUE, 0, "//tmp/dir1", NULL }, + {"/tmp/dir1", TRUE, 0, "///tmp/dir1", NULL }, + {"/tmp/dir1", TRUE, 0, "////tmp/dir1", NULL }, + {"/tmp/dir1", TRUE, 0, "/tmp/./dir1", NULL }, + {"/tmp/dir1", TRUE, 0, "/tmp//dir1", NULL }, + {"/tmp/dir1", TRUE, 0, "/tmp///dir1///", NULL }, + {"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", TRUE, 0, "/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88/", NULL } }; guint i; @@ -142,19 +142,19 @@ static void test_g_file_new_for_uri (void) { const struct TestPathsWithOper cmp_uris[] = { - {"file:///", TRUE, 0, "file:///./"}, - {"file:////", TRUE, 0, "file:////"}, - {"file:////", TRUE, 0, "file:////./"}, - {"file:///", TRUE, 0, "file:///.//"}, - {"file:///", TRUE, 0, "file:///././"}, - {"file:///tmp", TRUE, 0, "file:///tmp/d/../"}, - {"file:///", TRUE, 0, "file:///somedir/../"}, - {"file:///", FALSE, 0, "file:///somedir/.../"}, - {"file:////tmp/dir1", TRUE, 0, "file:////tmp/dir1"}, - {"file:///tmp/dir1", TRUE, 0, "file:///tmp/./dir1"}, - {"file:///tmp/dir1", TRUE, 0, "file:///tmp//dir1"}, - {"file:///tmp/dir1", TRUE, 0, "file:///tmp///dir1///"}, - {"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88", TRUE, 0, "file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/"} + {"file:///", TRUE, 0, "file:///./", NULL }, + {"file:////", TRUE, 0, "file:////", NULL }, + {"file:////", TRUE, 0, "file:////./", NULL }, + {"file:///", TRUE, 0, "file:///.//", NULL }, + {"file:///", TRUE, 0, "file:///././", NULL }, + {"file:///tmp", TRUE, 0, "file:///tmp/d/../", NULL }, + {"file:///", TRUE, 0, "file:///somedir/../", NULL }, + {"file:///", FALSE, 0, "file:///somedir/.../", NULL }, + {"file:////tmp/dir1", TRUE, 0, "file:////tmp/dir1", NULL }, + {"file:///tmp/dir1", TRUE, 0, "file:///tmp/./dir1", NULL }, + {"file:///tmp/dir1", TRUE, 0, "file:///tmp//dir1", NULL }, + {"file:///tmp/dir1", TRUE, 0, "file:///tmp///dir1///", NULL }, + {"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88", TRUE, 0, "file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", NULL } }; guint i; @@ -198,11 +198,11 @@ test_g_file_dup (void) { const struct TestPathsWithOper dup_paths[] = { - {"/", 0, FALSE, ""}, - {"file:///", 0, TRUE, ""}, - {"totalnonsense", 0, FALSE, ""}, - {"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 0, FALSE, ""}, - {"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88", 0, TRUE, ""}, + {"/", 0, FALSE, "", NULL }, + {"file:///", 0, TRUE, "", NULL }, + {"totalnonsense", 0, FALSE, "", NULL }, + {"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 0, FALSE, "", NULL }, + {"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88", 0, TRUE, "", NULL }, }; guint i; @@ -261,11 +261,11 @@ test_g_file_get_parse_name_utf8 (void) { const struct TestPathsWithOper strings[] = { - {G_DIR_SEPARATOR_S, 0, FALSE, G_DIR_SEPARATOR_S}, - {"file:///", 0, TRUE, G_DIR_SEPARATOR_S}, - {"totalnonsense", 0, FALSE, NULL}, - {"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 0, FALSE, NULL /* Depends on local file encoding */}, - {"file:///invalid%08/UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", 0, TRUE, "file:///invalid%08/UTF-8%20p\xc5\x99\xc3\xadli\xc5\xa1%20\xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd%20k\xc5\xaf\xc5\x88"}, + {G_DIR_SEPARATOR_S, 0, FALSE, G_DIR_SEPARATOR_S, NULL }, + {"file:///", 0, TRUE, G_DIR_SEPARATOR_S, NULL }, + {"totalnonsense", 0, FALSE, NULL, NULL }, + {"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 0, FALSE, NULL, NULL /* Depends on local file encoding */}, + {"file:///invalid%08/UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", 0, TRUE, "file:///invalid%08/UTF-8%20p\xc5\x99\xc3\xadli\xc5\xa1%20\xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd%20k\xc5\xaf\xc5\x88", NULL }, }; guint i; @@ -315,14 +315,14 @@ test_g_file_new_for_commandline_arg (void) /* TestPathsWithOper.use_uri represents IsURIOnly here */ const struct TestPathsWithOper arg_data[] = { - {"./", 0, FALSE, "file"}, - {"../", 0, FALSE, "file"}, - {"/tmp", 0, FALSE, "file"}, - {"//UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 0, FALSE, "file"}, - {"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", 0, FALSE, "file"}, + {"./", 0, FALSE, "file", NULL }, + {"../", 0, FALSE, "file", NULL }, + {"/tmp", 0, FALSE, "file", NULL }, + {"//UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", 0, FALSE, "file", NULL }, + {"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", 0, FALSE, "file", NULL }, #if 0 - {"http://www.gtk.org/", 0, TRUE, "http"}, - {"ftp://user:pass@ftp.gimp.org/", 0, TRUE, "ftp"}, + {"http://www.gtk.org/", 0, TRUE, "http", NULL }, + {"ftp://user:pass@ftp.gimp.org/", 0, TRUE, "ftp", NULL }, #endif }; GFile *file; @@ -486,15 +486,15 @@ test_g_file_get_parent_child (void) const struct TestPathsWithOper paths[] = { /* path root_desc uri dir_holder */ - {"/dir1/dir", FALSE, FALSE, "dir"}, - {"/dir", FALSE, FALSE, "dir"}, - {"/", TRUE, FALSE, "dir"}, - {"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88/", FALSE, FALSE, "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88"}, - {"file:///dir1/dir", FALSE, TRUE, "dir"}, - {"file:///dir", FALSE, TRUE, "dir"}, - {"file:///", TRUE, TRUE, "dir"}, - {"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", FALSE, TRUE, "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88"}, - {"dav://www.gtk.org/plan/meetings", FALSE, TRUE, "meetings"}, + {"/dir1/dir", FALSE, FALSE, "dir", NULL }, + {"/dir", FALSE, FALSE, "dir", NULL }, + {"/", TRUE, FALSE, "dir", NULL }, + {"/UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88/", FALSE, FALSE, "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", NULL }, + {"file:///dir1/dir", FALSE, TRUE, "dir", NULL }, + {"file:///dir", FALSE, TRUE, "dir", NULL }, + {"file:///", TRUE, TRUE, "dir", NULL }, + {"file:///UTF-8%20p%C5%99%C3%ADli%C5%A1%20%C5%BElu%C5%A5ou%C4%8Dk%C3%BD%20k%C5%AF%C5%88/", FALSE, TRUE, "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88", NULL }, + {"dav://www.gtk.org/plan/meetings", FALSE, TRUE, "meetings", NULL }, }; guint i; diff --git a/gio/tests/gapplication-example-cmdline3.c b/gio/tests/gapplication-example-cmdline3.c index b95e0cbc8..eecdc6578 100644 --- a/gio/tests/gapplication-example-cmdline3.c +++ b/gio/tests/gapplication-example-cmdline3.c @@ -17,7 +17,7 @@ my_cmdline_handler (gpointer data) { "arg1", 0, 0, G_OPTION_ARG_INT, &arg1, NULL, NULL }, { "arg2", 0, 0, G_OPTION_ARG_NONE, &arg2, NULL, NULL }, { "help", '?', 0, G_OPTION_ARG_NONE, &help, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; GError *error; gint i; diff --git a/gio/tests/gapplication-example-cmdline4.c b/gio/tests/gapplication-example-cmdline4.c index 112006212..ece2ee528 100644 --- a/gio/tests/gapplication-example-cmdline4.c +++ b/gio/tests/gapplication-example-cmdline4.c @@ -53,7 +53,7 @@ main (int argc, char **argv) /* A dummy flag option, to be handled in primary */ { "flag", 'f', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, "A flag argument", NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; app = g_application_new ("org.gtk.TestApplication", diff --git a/gio/tests/gapplication.c b/gio/tests/gapplication.c index 900e7ac97..6f1a27e0f 100644 --- a/gio/tests/gapplication.c +++ b/gio/tests/gapplication.c @@ -576,6 +576,81 @@ test_quit (void) g_free (binpath); } +typedef struct +{ + gboolean shutdown; + GParamSpec *notify_spec; /* (owned) (nullable) */ +} RegisteredData; + +static void +on_registered_shutdown (GApplication *app, + gpointer user_data) +{ + RegisteredData *registered_data = user_data; + + registered_data->shutdown = TRUE; +} + +static void +on_registered_notify (GApplication *app, + GParamSpec *spec, + gpointer user_data) +{ + RegisteredData *registered_data = user_data; + registered_data->notify_spec = g_param_spec_ref (spec); + + if (g_application_get_is_registered (app)) + g_assert_false (registered_data->shutdown); + else + g_assert_true (registered_data->shutdown); +} + +static void +test_registered (void) +{ + char *binpath = g_test_build_filename (G_TEST_BUILT, "unimportant", NULL); + gchar *argv[] = { binpath, NULL }; + RegisteredData registered_data = { FALSE, NULL }; + GApplication *app; + + app = g_application_new (NULL, G_APPLICATION_FLAGS_NONE); + g_signal_connect (app, "activate", G_CALLBACK (noappid_activate), NULL); + g_signal_connect (app, "shutdown", G_CALLBACK (on_registered_shutdown), ®istered_data); + g_signal_connect (app, "notify::is-registered", G_CALLBACK (on_registered_notify), ®istered_data); + + g_assert_null (registered_data.notify_spec); + + g_assert_true (g_application_register (app, NULL, NULL)); + g_assert_true (g_application_get_is_registered (app)); + + g_assert_nonnull (registered_data.notify_spec); + g_assert_cmpstr (registered_data.notify_spec->name, ==, "is-registered"); + g_clear_pointer (®istered_data.notify_spec, g_param_spec_unref); + + g_assert_false (registered_data.shutdown); + + g_application_run (app, 1, argv); + + g_assert_true (registered_data.shutdown); + g_assert_false (g_application_get_is_registered (app)); + g_assert_nonnull (registered_data.notify_spec); + g_assert_cmpstr (registered_data.notify_spec->name, ==, "is-registered"); + g_clear_pointer (®istered_data.notify_spec, g_param_spec_unref); + + /* Register it again */ + registered_data.shutdown = FALSE; + g_assert_true (g_application_register (app, NULL, NULL)); + g_assert_true (g_application_get_is_registered (app)); + g_assert_nonnull (registered_data.notify_spec); + g_assert_cmpstr (registered_data.notify_spec->name, ==, "is-registered"); + g_clear_pointer (®istered_data.notify_spec, g_param_spec_unref); + g_assert_false (registered_data.shutdown); + + g_object_unref (app); + + g_free (binpath); +} + static void on_activate (GApplication *app) { @@ -1136,6 +1211,7 @@ main (int argc, char **argv) g_test_add_func ("/gapplication/properties", properties); g_test_add_func ("/gapplication/app-id", appid); g_test_add_func ("/gapplication/quit", test_quit); + g_test_add_func ("/gapplication/registered", test_registered); g_test_add_func ("/gapplication/local-actions", test_local_actions); /* g_test_add_func ("/gapplication/remote-actions", test_remote_actions); */ g_test_add_func ("/gapplication/local-command-line", test_local_command_line); diff --git a/gio/tests/gdbus-connection-slow.c b/gio/tests/gdbus-connection-slow.c index 7819e669a..3339e703d 100644 --- a/gio/tests/gdbus-connection-slow.c +++ b/gio/tests/gdbus-connection-slow.c @@ -84,7 +84,7 @@ test_connection_flush (void) for (n = 0; n < 50; n++) { gboolean ret; - gint exit_status; + gint wait_status; guint timeout_mainloop_id; gchar *flush_helper_stdout = NULL; gchar *flush_helper_stderr = NULL; @@ -93,9 +93,9 @@ test_connection_flush (void) ret = g_spawn_command_line_sync (flush_helper, &flush_helper_stdout, &flush_helper_stderr, - &exit_status, + &wait_status, &error) && - g_spawn_check_exit_status (exit_status, &error); + g_spawn_check_wait_status (wait_status, &error); if (!ret) g_test_message ("Child process ‘%s’ failed. stdout:\n%s\nstderr:\n%s", flush_helper, flush_helper_stdout, flush_helper_stderr); diff --git a/gio/tests/gdbus-connection.c b/gio/tests/gdbus-connection.c index 51dd27f7e..0410a880a 100644 --- a/gio/tests/gdbus-connection.c +++ b/gio/tests/gdbus-connection.c @@ -86,7 +86,8 @@ static const GDBusInterfaceVTable boo_vtable = { NULL, /* _method_call */ NULL, /* _get_property */ - NULL /* _set_property */ + NULL, /* _set_property */ + { 0 } }; /* Runs in a worker thread. */ diff --git a/gio/tests/gdbus-daemon.c b/gio/tests/gdbus-daemon.c index a33269916..6c2b81c2c 100644 --- a/gio/tests/gdbus-daemon.c +++ b/gio/tests/gdbus-daemon.c @@ -19,7 +19,7 @@ main (int argc, char *argv[]) { "config-file", 0, 0, G_OPTION_ARG_STRING, &config_file, N_("Ignored, for compat with GTestDbus"), NULL }, { "print-address", 0, 0, G_OPTION_ARG_NONE, &print_address, N_("Print address"), NULL }, { "print-env", 0, 0, G_OPTION_ARG_NONE, &print_env, N_("Print address in shell mode"), NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; context = g_option_context_new (""); diff --git a/gio/tests/gdbus-example-export.c b/gio/tests/gdbus-example-export.c index f712d88f0..182305068 100644 --- a/gio/tests/gdbus-example-export.c +++ b/gio/tests/gdbus-example-export.c @@ -225,7 +225,8 @@ static const GDBusInterfaceVTable interface_vtable = { handle_method_call, handle_get_property, - handle_set_property + handle_set_property, + { 0 } }; static void diff --git a/gio/tests/gdbus-example-own-name.c b/gio/tests/gdbus-example-own-name.c index 74d39208f..6c83f12fe 100644 --- a/gio/tests/gdbus-example-own-name.c +++ b/gio/tests/gdbus-example-own-name.c @@ -40,7 +40,7 @@ main (int argc, char *argv[]) { "replace", 'r', 0, G_OPTION_ARG_NONE, &opt_replace, "Replace existing name if possible", NULL }, { "allow-replacement", 'a', 0, G_OPTION_ARG_NONE, &opt_allow_replacement, "Allow replacement", NULL }, { "name", 'n', 0, G_OPTION_ARG_STRING, &opt_name, "Name to acquire", NULL }, - { NULL} + G_OPTION_ENTRY_NULL }; error = NULL; diff --git a/gio/tests/gdbus-example-peer.c b/gio/tests/gdbus-example-peer.c index 9d5de32a6..f57d36832 100755 --- a/gio/tests/gdbus-example-peer.c +++ b/gio/tests/gdbus-example-peer.c @@ -117,6 +117,7 @@ static const GDBusInterfaceVTable interface_vtable = handle_method_call, NULL, NULL, + { 0 } }; /* ---------------------------------------------------------------------------------------------------- */ @@ -251,7 +252,7 @@ main (int argc, char *argv[]) { "server", 's', 0, G_OPTION_ARG_NONE, &opt_server, "Start a server instead of a client", NULL }, { "address", 'a', 0, G_OPTION_ARG_STRING, &opt_address, "D-Bus address to use", NULL }, { "allow-anonymous", 'n', 0, G_OPTION_ARG_NONE, &opt_allow_anonymous, "Allow anonymous authentication", NULL }, - { NULL} + G_OPTION_ENTRY_NULL }; ret = 1; diff --git a/gio/tests/gdbus-example-server.c b/gio/tests/gdbus-example-server.c index 00e482724..b19f6505d 100644 --- a/gio/tests/gdbus-example-server.c +++ b/gio/tests/gdbus-example-server.c @@ -276,7 +276,8 @@ static const GDBusInterfaceVTable interface_vtable = { handle_method_call, handle_get_property, - handle_set_property + handle_set_property, + { 0 } }; /* ---------------------------------------------------------------------------------------------------- */ diff --git a/gio/tests/gdbus-example-subtree.c b/gio/tests/gdbus-example-subtree.c index 714bbe612..3254a27cd 100644 --- a/gio/tests/gdbus-example-subtree.c +++ b/gio/tests/gdbus-example-subtree.c @@ -72,7 +72,8 @@ const GDBusInterfaceVTable manager_vtable = { manager_method_call, NULL, /* get_property */ - NULL /* set_property */ + NULL, /* set_property */ + { 0 } }; /* ---------------------------------------------------------------------------------------------------- */ @@ -187,6 +188,7 @@ const GDBusInterfaceVTable block_vtable = block_method_call, block_get_property, block_set_property, + { 0 } }; /* ---------------------------------------------------------------------------------------------------- */ @@ -223,8 +225,9 @@ partition_method_call (GDBusConnection *connection, const GDBusInterfaceVTable partition_vtable = { partition_method_call, - //partition_get_property, - //partition_set_property + NULL, + NULL, + { 0 } }; /* ---------------------------------------------------------------------------------------------------- */ @@ -321,7 +324,8 @@ const GDBusSubtreeVTable subtree_vtable = { subtree_enumerate, subtree_introspect, - subtree_dispatch + subtree_dispatch, + { 0 } }; /* ---------------------------------------------------------------------------------------------------- */ diff --git a/gio/tests/gdbus-example-watch-name.c b/gio/tests/gdbus-example-watch-name.c index caec6ec08..27cc3f387 100644 --- a/gio/tests/gdbus-example-watch-name.c +++ b/gio/tests/gdbus-example-watch-name.c @@ -9,7 +9,7 @@ static GOptionEntry opt_entries[] = { "name", 'n', 0, G_OPTION_ARG_STRING, &opt_name, "Name to watch", NULL }, { "system-bus", 's', 0, G_OPTION_ARG_NONE, &opt_system_bus, "Use the system-bus instead of the session-bus", NULL }, { "auto-start", 'a', 0, G_OPTION_ARG_NONE, &opt_auto_start, "Instruct the bus to launch an owner for the name", NULL}, - { NULL} + G_OPTION_ENTRY_NULL }; static void diff --git a/gio/tests/gdbus-example-watch-proxy.c b/gio/tests/gdbus-example-watch-proxy.c index 51132e385..8cce90c0d 100644 --- a/gio/tests/gdbus-example-watch-proxy.c +++ b/gio/tests/gdbus-example-watch-proxy.c @@ -15,7 +15,7 @@ static GOptionEntry opt_entries[] = { "system-bus", 's', 0, G_OPTION_ARG_NONE, &opt_system_bus, "Use the system-bus instead of the session-bus", NULL }, { "no-auto-start", 'a', 0, G_OPTION_ARG_NONE, &opt_no_auto_start, "Don't instruct the bus to launch an owner for the name", NULL}, { "no-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_no_properties, "Do not load properties", NULL}, - { NULL} + G_OPTION_ENTRY_NULL }; static GMainLoop *loop = NULL; diff --git a/gio/tests/gdbus-exit-on-close.c b/gio/tests/gdbus-exit-on-close.c index 4241fc7a4..1bf0ce7dd 100644 --- a/gio/tests/gdbus-exit-on-close.c +++ b/gio/tests/gdbus-exit-on-close.c @@ -49,7 +49,7 @@ static const TestData cases[] = { { "true", NULL, EXPLICITLY_TRUE, REMOTE }, { "false", NULL, EXPLICITLY_FALSE, REMOTE }, { "we-close", "662100", EXPLICITLY_TRUE, LOCAL }, - { NULL } + { NULL, NULL, 0, 0 } }; static gboolean diff --git a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c index 61d47e90a..aec21d7d0 100644 --- a/gio/tests/gdbus-export.c +++ b/gio/tests/gdbus-export.c @@ -127,6 +127,8 @@ static const GDBusInterfaceInfo foo2_interface_info = "org.example.Foo2", (GDBusMethodInfo **) &foo_method_info_pointers, (GDBusSignalInfo **) &foo_signal_info_pointers, + NULL, + NULL }; static void @@ -198,7 +200,8 @@ static const GDBusInterfaceVTable foo_vtable = { foo_method_call, foo_get_property, - foo_set_property + foo_set_property, + { 0 }, }; /* -------------------- */ @@ -311,7 +314,8 @@ static const GDBusInterfaceVTable dyna_interface_vtable = { dyna_cyber, NULL, - NULL + NULL, + { 0 } }; /* ---------------------------------------------------------------------------------------------------- */ @@ -693,7 +697,8 @@ static const GDBusSubtreeVTable subtree_vtable = { subtree_enumerate, subtree_introspect, - subtree_dispatch + subtree_dispatch, + { 0 } }; /* -------------------- */ @@ -747,7 +752,8 @@ static const GDBusSubtreeVTable dynamic_subtree_vtable = { dynamic_subtree_enumerate, dynamic_subtree_introspect, - dynamic_subtree_dispatch + dynamic_subtree_dispatch, + { 0 } }; /* -------------------- */ @@ -1729,7 +1735,7 @@ test_async_properties (void) GError *error = NULL; guint registration_id, registration_id2; static const GDBusInterfaceVTable vtable = { - test_async_method_call, NULL, NULL + test_async_method_call, NULL, NULL, { 0 } }; c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); diff --git a/gio/tests/gdbus-names.c b/gio/tests/gdbus-names.c index 05d2015d0..8504220a9 100644 --- a/gio/tests/gdbus-names.c +++ b/gio/tests/gdbus-names.c @@ -1,6 +1,7 @@ /* GLib testing framework examples and tests * * Copyright (C) 2008-2010 Red Hat, Inc. + * Copyright (C) 2021 Frederic Martinsons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,6 +17,7 @@ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. * * Author: David Zeuthen <davidz@redhat.com> + * Author: Frederic Martinsons <frederic.martinsons@gmail.com> */ #include <gio/gio.h> @@ -495,6 +497,20 @@ typedef struct guint num_free_func; } WatchNameData; +typedef struct +{ + WatchNameData data; + GDBusConnection *connection; + GMutex cond_mutex; + GCond cond; + gboolean started; + gboolean name_acquired; + gboolean ended; + gboolean unwatch_early; + GMutex mutex; + guint watch_id; +} WatchNameThreadData; + static void watch_name_data_free_func (WatchNameData *data) { @@ -514,7 +530,7 @@ w_name_acquired_handler (GDBusConnection *connection, const gchar *name, gpointer user_data) { - WatchNameData *data = user_data; + OwnNameData *data = user_data; data->num_acquired += 1; g_main_loop_quit (loop); } @@ -524,7 +540,7 @@ w_name_lost_handler (GDBusConnection *connection, const gchar *name, gpointer user_data) { - WatchNameData *data = user_data; + OwnNameData *data = user_data; data->num_lost += 1; g_main_loop_quit (loop); } @@ -613,6 +629,7 @@ stop_service (GDBusConnection *connection, { GError *error = NULL; GDBusProxy *proxy = NULL; + GVariant *result = NULL; data->num_vanished = 0; @@ -626,15 +643,17 @@ stop_service (GDBusConnection *connection, &error); g_assert_no_error (error); - g_dbus_proxy_call_sync (proxy, - "Quit", - NULL, - G_DBUS_CALL_FLAGS_NO_AUTO_START, - 100, - NULL, - &error); + result = g_dbus_proxy_call_sync (proxy, + "Quit", + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 100, + NULL, + &error); g_assert_no_error (error); g_object_unref (proxy); + if (result) + g_variant_unref (result); while (data->num_vanished == 0) g_main_loop_run (loop); } @@ -643,6 +662,7 @@ static void test_bus_watch_name (gconstpointer d) { WatchNameData data; + OwnNameData own_data; guint id; guint owner_id; GDBusConnection *connection; @@ -685,15 +705,16 @@ test_bus_watch_name (gconstpointer d) g_assert_cmpint (data.num_appeared, ==, 0); g_assert_cmpint (data.num_vanished, ==, 1); g_assert_cmpint (data.num_free_func, ==, 1); + data.num_free_func = 0; /* * Now bring up a bus, own a name, and then start watching it. */ session_bus_up (); /* own the name */ - data.num_free_func = 0; - data.num_acquired = 0; - data.num_lost = 0; + own_data.num_free_func = 0; + own_data.num_acquired = 0; + own_data.num_lost = 0; data.expect_null_connection = FALSE; owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, name, @@ -701,11 +722,11 @@ test_bus_watch_name (gconstpointer d) w_bus_acquired_handler, w_name_acquired_handler, w_name_lost_handler, - &data, - (GDestroyNotify) watch_name_data_free_func); + &own_data, + (GDestroyNotify) own_name_data_free_func); g_main_loop_run (loop); - g_assert_cmpint (data.num_acquired, ==, 1); - g_assert_cmpint (data.num_lost, ==, 0); + g_assert_cmpint (own_data.num_acquired, ==, 1); + g_assert_cmpint (own_data.num_lost, ==, 0); connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); g_assert (connection != NULL); @@ -750,9 +771,9 @@ test_bus_watch_name (gconstpointer d) /* unown the name */ g_bus_unown_name (owner_id); g_main_loop_run (loop); - g_assert_cmpint (data.num_acquired, ==, 1); - g_assert_cmpint (data.num_free_func, ==, 2); - + g_assert_cmpint (own_data.num_acquired, ==, 1); + g_assert_cmpint (own_data.num_free_func, ==, 1); + own_data.num_free_func = 0; /* * Create a watcher and then make a name be owned. * @@ -802,21 +823,21 @@ test_bus_watch_name (gconstpointer d) if (!watch_name_test->existing_service) { /* own the name */ - data.num_acquired = 0; - data.num_lost = 0; - data.expect_null_connection = FALSE; + own_data.num_acquired = 0; + own_data.num_lost = 0; + own_data.expect_null_connection = FALSE; owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, name, G_BUS_NAME_OWNER_FLAGS_NONE, w_bus_acquired_handler, w_name_acquired_handler, w_name_lost_handler, - &data, - (GDestroyNotify) watch_name_data_free_func); - while (data.num_acquired == 0 || data.num_appeared == 0) + &own_data, + (GDestroyNotify) own_name_data_free_func); + while (own_data.num_acquired == 0 || data.num_appeared == 0) g_main_loop_run (loop); - g_assert_cmpint (data.num_acquired, ==, 1); - g_assert_cmpint (data.num_lost, ==, 0); + g_assert_cmpint (own_data.num_acquired, ==, 1); + g_assert_cmpint (own_data.num_lost, ==, 0); g_assert_cmpint (data.num_appeared, ==, 1); g_assert_cmpint (data.num_vanished, ==, 1); } @@ -835,12 +856,12 @@ test_bus_watch_name (gconstpointer d) if (!watch_name_test->existing_service) { g_main_loop_run (loop); - g_assert_cmpint (data.num_lost, ==, 1); + g_assert_cmpint (own_data.num_lost, ==, 1); g_assert_cmpint (data.num_vanished, ==, 2); } else { - g_assert_cmpint (data.num_lost, ==, 0); + g_assert_cmpint (own_data.num_lost, ==, 0); g_assert_cmpint (data.num_vanished, ==, 1); } g_bus_unwatch_name (id); @@ -850,11 +871,253 @@ test_bus_watch_name (gconstpointer d) { g_bus_unown_name (owner_id); g_main_loop_run (loop); - g_assert_cmpint (data.num_free_func, ==, 2); + g_assert_cmpint (own_data.num_free_func, ==, 1); + } + session_bus_down (); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +/* Called in the same thread as watcher_thread() */ +static void +t_watch_name_data_free_func (WatchNameThreadData *thread_data) +{ + thread_data->data.num_free_func++; +} + +/* Called in the same thread as watcher_thread() */ +static void +t_name_appeared_handler (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + WatchNameThreadData *thread_data = user_data; + thread_data->data.num_appeared += 1; +} + +/* Called in the same thread as watcher_thread() */ +static void +t_name_vanished_handler (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + WatchNameThreadData *thread_data = user_data; + thread_data->data.num_vanished += 1; +} + +/* Called in the thread which constructed the GDBusConnection */ +static void +connection_closed_cb (GDBusConnection *connection, + gboolean remote_peer_vanished, + GError *error, + gpointer user_data) +{ + WatchNameThreadData *thread_data = (WatchNameThreadData *) user_data; + if (thread_data->unwatch_early) + { + g_mutex_lock (&thread_data->mutex); + g_bus_unwatch_name (g_atomic_int_get (&thread_data->watch_id)); + g_atomic_int_set (&thread_data->watch_id, 0); + g_cond_signal (&thread_data->cond); + g_mutex_unlock (&thread_data->mutex); } +} + +static gpointer +watcher_thread (gpointer user_data) +{ + WatchNameThreadData *thread_data = user_data; + GMainContext *thread_context; + + thread_context = g_main_context_new (); + g_main_context_push_thread_default (thread_context); + + // Notify that the thread has started + g_mutex_lock (&thread_data->cond_mutex); + g_atomic_int_set (&thread_data->started, TRUE); + g_cond_signal (&thread_data->cond); + g_mutex_unlock (&thread_data->cond_mutex); + + // Wait for the main thread to own the name before watching it + g_mutex_lock (&thread_data->cond_mutex); + while (!g_atomic_int_get (&thread_data->name_acquired)) + g_cond_wait (&thread_data->cond, &thread_data->cond_mutex); + g_mutex_unlock (&thread_data->cond_mutex); + + thread_data->data.num_appeared = 0; + thread_data->data.num_vanished = 0; + thread_data->data.num_free_func = 0; + // g_signal_connect_after is important to have default handler be called before our code + g_signal_connect_after (thread_data->connection, "closed", G_CALLBACK (connection_closed_cb), thread_data); + + g_mutex_lock (&thread_data->mutex); + thread_data->watch_id = g_bus_watch_name_on_connection (thread_data->connection, + "org.gtk.GDBus.Name1", + G_BUS_NAME_WATCHER_FLAGS_NONE, + t_name_appeared_handler, + t_name_vanished_handler, + thread_data, + (GDestroyNotify) t_watch_name_data_free_func); + g_mutex_unlock (&thread_data->mutex); + + g_assert_cmpint (thread_data->data.num_appeared, ==, 0); + g_assert_cmpint (thread_data->data.num_vanished, ==, 0); + while (thread_data->data.num_appeared == 0) + g_main_context_iteration (thread_context, TRUE); + g_assert_cmpint (thread_data->data.num_appeared, ==, 1); + g_assert_cmpint (thread_data->data.num_vanished, ==, 0); + thread_data->data.num_appeared = 0; + + /* Close the connection and: + * - check that we had received a vanished event even begin in different thread + * - or check that unwatching the bus when a vanished had been scheduled + * make it correctly unscheduled (unwatch_early condition) + */ + g_dbus_connection_close_sync (thread_data->connection, NULL, NULL); + if (thread_data->unwatch_early) + { + // Wait for the main thread to iterate in order to have close connection handled + g_mutex_lock (&thread_data->mutex); + while (g_atomic_int_get (&thread_data->watch_id) != 0) + g_cond_wait (&thread_data->cond, &thread_data->mutex); + g_mutex_unlock (&thread_data->mutex); + + while (thread_data->data.num_free_func == 0) + g_main_context_iteration (thread_context, TRUE); + g_assert_cmpint (thread_data->data.num_vanished, ==, 0); + g_assert_cmpint (thread_data->data.num_appeared, ==, 0); + g_assert_cmpint (thread_data->data.num_free_func, ==, 1); + } + else + { + while (thread_data->data.num_vanished == 0) + { + /* + * Close of connection is treated in the context of the thread which + * creates the connection. We must run iteration on it (to have the 'closed' + * signal handled) and also run current thread loop to have name_vanished + * callback handled. + */ + g_main_context_iteration (thread_context, TRUE); + } + g_assert_cmpint (thread_data->data.num_vanished, ==, 1); + g_assert_cmpint (thread_data->data.num_appeared, ==, 0); + g_mutex_lock (&thread_data->mutex); + g_bus_unwatch_name (g_atomic_int_get (&thread_data->watch_id)); + g_atomic_int_set (&thread_data->watch_id, 0); + g_mutex_unlock (&thread_data->mutex); + while (thread_data->data.num_free_func == 0) + g_main_context_iteration (thread_context, TRUE); + g_assert_cmpint (thread_data->data.num_free_func, ==, 1); + } + + g_mutex_lock (&thread_data->cond_mutex); + thread_data->ended = TRUE; + g_main_context_wakeup (NULL); + g_cond_signal (&thread_data->cond); + g_mutex_unlock (&thread_data->cond_mutex); + + g_signal_handlers_disconnect_by_func (thread_data->connection, connection_closed_cb, thread_data); + g_object_unref (thread_data->connection); + g_main_context_pop_thread_default (thread_context); + g_main_context_unref (thread_context); + + g_mutex_lock (&thread_data->mutex); + g_assert_cmpint (thread_data->watch_id, ==, 0); + g_mutex_unlock (&thread_data->mutex); + return NULL; +} + +static void +watch_with_different_context (gboolean unwatch_early) +{ + OwnNameData own_data; + WatchNameThreadData thread_data; + GDBusConnection *connection; + GThread *watcher; + guint id; + + session_bus_up (); + + connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + g_assert (connection != NULL); + + g_mutex_init (&thread_data.mutex); + g_mutex_init (&thread_data.cond_mutex); + g_cond_init (&thread_data.cond); + thread_data.started = FALSE; + thread_data.name_acquired = FALSE; + thread_data.ended = FALSE; + thread_data.connection = g_object_ref (connection); + thread_data.unwatch_early = unwatch_early; + + // Create a thread which will watch a name and wait for it to be ready + g_mutex_lock (&thread_data.cond_mutex); + watcher = g_thread_new ("watcher", watcher_thread, &thread_data); + while (!g_atomic_int_get (&thread_data.started)) + g_cond_wait (&thread_data.cond, &thread_data.cond_mutex); + g_mutex_unlock (&thread_data.cond_mutex); + + own_data.num_acquired = 0; + own_data.num_lost = 0; + own_data.num_free_func = 0; + own_data.expect_null_connection = FALSE; + // Own the name to avoid direct name vanished in watcher thread + id = g_bus_own_name_on_connection (connection, + "org.gtk.GDBus.Name1", + G_BUS_NAME_OWNER_FLAGS_REPLACE, + w_name_acquired_handler, + w_name_lost_handler, + &own_data, + (GDestroyNotify) own_name_data_free_func); + while (own_data.num_acquired == 0) + g_main_context_iteration (NULL, TRUE); + g_assert_cmpint (own_data.num_acquired, ==, 1); + g_assert_cmpint (own_data.num_lost, ==, 0); + + // Wake the thread for it to begin watch + g_mutex_lock (&thread_data.cond_mutex); + g_atomic_int_set (&thread_data.name_acquired, TRUE); + g_cond_signal (&thread_data.cond); + g_mutex_unlock (&thread_data.cond_mutex); + + // Iterate the loop until thread is waking us up + while (!thread_data.ended) + g_main_context_iteration (NULL, TRUE); + + g_thread_join (watcher); + + g_bus_unown_name (id); + while (own_data.num_free_func == 0) + g_main_context_iteration (NULL, TRUE); + g_assert_cmpint (own_data.num_free_func, ==, 1); + + g_mutex_clear (&thread_data.mutex); + g_mutex_clear (&thread_data.cond_mutex); + g_cond_clear (&thread_data.cond); + + session_bus_stop (); + g_assert_true (g_dbus_connection_is_closed (connection)); + g_object_unref (connection); session_bus_down (); } +static void +test_bus_watch_different_context (void) +{ + watch_with_different_context (FALSE); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static void +test_bus_unwatch_early (void) +{ + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/604"); + watch_with_different_context (TRUE); +} + /* ---------------------------------------------------------------------------------------------------- */ static void @@ -899,9 +1162,15 @@ test_validate_names (void) g_assert (!g_dbus_is_unique_name (names[n].string)); if (names[n].interface) - g_assert (g_dbus_is_interface_name (names[n].string)); + { + g_assert (g_dbus_is_interface_name (names[n].string)); + g_assert (g_dbus_is_error_name (names[n].string)); + } else - g_assert (!g_dbus_is_interface_name (names[n].string)); + { + g_assert (!g_dbus_is_interface_name (names[n].string)); + g_assert (!g_dbus_is_error_name (names[n].string)); + } } } @@ -979,6 +1248,8 @@ main (int argc, g_test_add_data_func ("/gdbus/bus-watch-name-closures-auto-start", &watch_closures_flags_auto_start, test_bus_watch_name); + g_test_add_func ("/gdbus/bus-watch-different-context", test_bus_watch_different_context); + g_test_add_func ("/gdbus/bus-unwatch-early", test_bus_unwatch_early); g_test_add_func ("/gdbus/escape-object-path", test_escape_object_path); ret = g_test_run(); diff --git a/gio/tests/gdbus-non-socket.c b/gio/tests/gdbus-non-socket.c index 64d985a15..911aff262 100644 --- a/gio/tests/gdbus-non-socket.c +++ b/gio/tests/gdbus-non-socket.c @@ -112,7 +112,8 @@ pokee_method_call (GDBusConnection *connection, static const GDBusInterfaceVTable pokee_vtable = { pokee_method_call, NULL, /* get_property */ - NULL /* set_property */ + NULL, /* set_property */ + { 0 } }; /* Processes: diff --git a/gio/tests/gdbus-peer-object-manager.c b/gio/tests/gdbus-peer-object-manager.c index 676c9f080..f101b46bd 100644 --- a/gio/tests/gdbus-peer-object-manager.c +++ b/gio/tests/gdbus-peer-object-manager.c @@ -108,6 +108,7 @@ mock_interface_get_vtable (GDBusInterfaceSkeleton *interface) NULL, mock_interface_get_property, NULL, + { 0 } }; return &vtable; diff --git a/gio/tests/gdbus-peer.c b/gio/tests/gdbus-peer.c index 34fab5713..2f2caf77a 100644 --- a/gio/tests/gdbus-peer.c +++ b/gio/tests/gdbus-peer.c @@ -258,7 +258,8 @@ static const GDBusInterfaceVTable test_interface_vtable = { test_interface_method_call, test_interface_get_property, - NULL /* set_property */ + NULL, /* set_property */ + { 0 } }; static void @@ -1436,7 +1437,8 @@ static const GDBusInterfaceVTable dmp_interface_vtable = { dmp_on_method_call, NULL, /* get_property */ - NULL /* set_property */ + NULL, /* set_property */ + { 0 } }; diff --git a/gio/tests/gdbus-proxy.c b/gio/tests/gdbus-proxy.c index a2160dcca..7e619c2ac 100644 --- a/gio/tests/gdbus-proxy.c +++ b/gio/tests/gdbus-proxy.c @@ -132,7 +132,7 @@ test_methods (GDBusProxy *proxy) static gboolean strv_equal (gchar **strv, ...) { - gint count; + gsize count; va_list list; const gchar *str; gboolean res; diff --git a/gio/tests/gdbus-serialization.c b/gio/tests/gdbus-serialization.c index b95244c9a..a3b03c5e0 100644 --- a/gio/tests/gdbus-serialization.c +++ b/gio/tests/gdbus-serialization.c @@ -1051,7 +1051,7 @@ test_message_parse_empty_arrays_of_arrays (void) GVariant *body; GError *error = NULL; - g_test_bug ("673612"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=673612"); /* These three-element array of empty arrays were previously read back as a * two-element array of empty arrays, due to sometimes erroneously skipping * four bytes to align for the eight-byte-aligned grandchild types (x and @@ -1107,7 +1107,7 @@ test_message_serialize_double_array (void) GVariantBuilder builder; GVariant *body; - g_test_bug ("732754"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=732754"); g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad")); g_variant_builder_add (&builder, "d", (gdouble)0.0); @@ -1480,7 +1480,6 @@ main (int argc, setlocale (LC_ALL, "C"); g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugzilla.gnome.org/show_bug.cgi?id="); g_test_add_func ("/gdbus/message-serialize/basic", test_message_serialize_basic); diff --git a/gio/tests/gdbus-test-codegen.c b/gio/tests/gdbus-test-codegen.c index 36be37b72..0681e7ec8 100644 --- a/gio/tests/gdbus-test-codegen.c +++ b/gio/tests/gdbus-test-codegen.c @@ -1920,7 +1920,7 @@ check_object_manager (void) GError *error; GMainLoop *loop; OMData *om_data = NULL; - guint om_signal_id = -1; + guint om_signal_id = 0; GDBusObjectManager *pm = NULL; GList *object_proxies; GList *proxies; @@ -2356,7 +2356,7 @@ check_object_manager (void) if (loop != NULL) g_main_loop_unref (loop); - if (om_signal_id != -1) + if (om_signal_id != 0) g_dbus_connection_signal_unsubscribe (c, om_signal_id); g_clear_object (&o3); g_clear_object (&o2); diff --git a/gio/tests/gdbus-testserver.c b/gio/tests/gdbus-testserver.c index dd0d5ba5a..ae8e47b18 100644 --- a/gio/tests/gdbus-testserver.c +++ b/gio/tests/gdbus-testserver.c @@ -322,7 +322,7 @@ handle_method_call (GDBusConnection *connection, const guint64 *uint64s; const gdouble *doubles; gsize n_elts; - gint i, j; + gsize i, j; GVariantBuilder ret; g_variant_builder_init (&ret, G_VARIANT_TYPE ("(ayabanaqaiauaxatad)")); @@ -802,7 +802,8 @@ static const GDBusInterfaceVTable interface_vtable = { handle_method_call, handle_get_property, - handle_set_property + handle_set_property, + { 0 } }; static void diff --git a/gio/tests/glistmodel.c b/gio/tests/glistmodel.c index 5ecf45f79..e50969ead 100644 --- a/gio/tests/glistmodel.c +++ b/gio/tests/glistmodel.c @@ -270,7 +270,7 @@ test_store_splice_replace_middle (void) GAction *item; GPtrArray *array; - g_test_bug ("795307"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=795307"); store = g_list_store_new (G_TYPE_SIMPLE_ACTION); model = G_LIST_MODEL (store); @@ -326,7 +326,7 @@ test_store_splice_replace_all (void) GPtrArray *array; GAction *item; - g_test_bug ("795307"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=795307"); store = g_list_store_new (G_TYPE_SIMPLE_ACTION); model = G_LIST_MODEL (store); @@ -874,7 +874,6 @@ test_store_find (void) int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugzilla.gnome.org/"); g_test_add_func ("/glistmodel/store/properties", test_store_properties); g_test_add_func ("/glistmodel/store/non-gobjects", test_store_non_gobjects); diff --git a/gio/tests/gnotification-server.c b/gio/tests/gnotification-server.c index 9585b0949..c98cbf018 100644 --- a/gio/tests/gnotification-server.c +++ b/gio/tests/gnotification-server.c @@ -220,7 +220,7 @@ g_notification_server_bus_acquired (GDBusConnection *connection, gpointer user_data) { const GDBusInterfaceVTable vtable = { - org_gtk_Notifications_method_call, NULL, NULL + org_gtk_Notifications_method_call, NULL, NULL, { 0 } }; GNotificationServer *server = user_data; diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c index 9e570a1b2..42eeccd7a 100644 --- a/gio/tests/gsettings.c +++ b/gio/tests/gsettings.c @@ -2397,7 +2397,7 @@ strv_has_string (gchar **haystack, static gboolean strv_set_equal (gchar **strv, ...) { - gint count; + gsize count; va_list list; const gchar *str; gboolean res; @@ -2572,7 +2572,7 @@ test_schema_source (void) GSettingsBackend *backend; GSettingsSchema *schema; GError *error = NULL; - GSettings *settings; + GSettings *settings, *child; gboolean enabled; backend = g_settings_backend_get_default (); @@ -2628,13 +2628,18 @@ test_schema_source (void) g_assert_nonnull (schema); /* try to use it for something */ - settings = g_settings_new_full (schema, backend, g_settings_schema_get_path (schema)); + settings = g_settings_new_full (schema, backend, "/test/"); g_settings_schema_unref (schema); enabled = FALSE; g_settings_get (settings, "enabled", "b", &enabled); g_assert_true (enabled); - g_object_unref (settings); + /* Check that child schemas are resolved from the correct schema source, see glib#1884 */ + child = g_settings_get_child (settings, "child"); + g_settings_get (settings, "enabled", "b", &enabled); + + g_object_unref (child); + g_object_unref (settings); g_settings_schema_source_unref (source); /* try again, but with no parent */ diff --git a/gio/tests/gsubprocess-testprog.c b/gio/tests/gsubprocess-testprog.c index c9b06c2a2..da3cf8d00 100644 --- a/gio/tests/gsubprocess-testprog.c +++ b/gio/tests/gsubprocess-testprog.c @@ -12,7 +12,7 @@ #endif static GOptionEntry options[] = { - {NULL} + G_OPTION_ENTRY_NULL }; static void diff --git a/gio/tests/gsubprocess.c b/gio/tests/gsubprocess.c index 7e22678ec..084b77df3 100644 --- a/gio/tests/gsubprocess.c +++ b/gio/tests/gsubprocess.c @@ -233,7 +233,7 @@ test_exit1_cancel (void) GSubprocess *proc; TestExit1CancelData data = { 0 }; - g_test_bug ("786456"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=786456"); args = get_test_subprocess_args ("exit1", NULL); proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error); @@ -288,7 +288,7 @@ test_exit1_cancel_in_cb (void) GSubprocess *proc; TestExit1CancelData data = { 0 }; - g_test_bug ("786456"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=786456"); args = get_test_subprocess_args ("exit1", NULL); proc = g_subprocess_newv ((const gchar * const *) args->pdata, G_SUBPROCESS_FLAGS_NONE, error); @@ -611,7 +611,7 @@ on_subprocess_exited (GObject *object, g_propagate_error (&data->error, error); } } - g_spawn_check_exit_status (g_subprocess_get_exit_status (subprocess), &error); + g_spawn_check_wait_status (g_subprocess_get_status (subprocess), &error); g_assert_no_error (error); data->events_pending--; if (data->events_pending == 0) @@ -771,7 +771,7 @@ test_communicate_async (gconstpointer test_data) GSubprocessFlags flags = GPOINTER_TO_INT (test_data); GError *error = NULL; GPtrArray *args; - TestAsyncCommunicateData data = { flags, 0, }; + TestAsyncCommunicateData data = { flags, 0, 0, NULL }; GSubprocess *proc; GCancellable *cancellable = NULL; GBytes *input; @@ -1022,7 +1022,7 @@ test_communicate_utf8_async (gconstpointer test_data) GSubprocessFlags flags = GPOINTER_TO_INT (test_data); GError *error = NULL; GPtrArray *args; - TestAsyncCommunicateData data = { flags, 0, }; + TestAsyncCommunicateData data = { flags, 0, 0, NULL }; GSubprocess *proc; GCancellable *cancellable = NULL; @@ -1055,7 +1055,7 @@ test_communicate_utf8_cancelled_async (gconstpointer test_data) GSubprocessFlags flags = GPOINTER_TO_INT (test_data); GError *error = NULL; GPtrArray *args; - TestAsyncCommunicateData data = { flags, 0, }; + TestAsyncCommunicateData data = { flags, 0, 0, NULL }; GSubprocess *proc; GCancellable *cancellable = NULL; @@ -1199,7 +1199,7 @@ test_communicate_utf8_async_invalid (void) GSubprocessFlags flags = G_SUBPROCESS_FLAGS_STDOUT_PIPE; GError *error = NULL; GPtrArray *args; - TestAsyncCommunicateData data = { flags, 0, }; + TestAsyncCommunicateData data = { flags, 0, 0, NULL }; GSubprocess *proc; GCancellable *cancellable = NULL; @@ -1281,7 +1281,7 @@ on_request_quit_exited (GObject *object, g_assert_true (g_subprocess_get_if_signaled (subprocess)); g_assert_cmpint (g_subprocess_get_term_sig (subprocess), ==, 9); #endif - g_spawn_check_exit_status (g_subprocess_get_status (subprocess), &error); + g_spawn_check_wait_status (g_subprocess_get_status (subprocess), &error); g_assert_nonnull (error); g_clear_error (&error); @@ -1812,7 +1812,6 @@ main (int argc, char **argv) gsize i; g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugzilla.gnome.org/"); g_test_add_func ("/gsubprocess/noop", test_noop); g_test_add_func ("/gsubprocess/noop-all-to-null", test_noop_all_to_null); diff --git a/gio/tests/gtesttlsbackend.c b/gio/tests/gtesttlsbackend.c index 56d155031..6c48c2394 100644 --- a/gio/tests/gtesttlsbackend.c +++ b/gio/tests/gtesttlsbackend.c @@ -110,6 +110,12 @@ enum PROP_CERT_ISSUER, PROP_CERT_PKCS11_URI, PROP_CERT_PRIVATE_KEY_PKCS11_URI, + PROP_CERT_NOT_VALID_BEFORE, + PROP_CERT_NOT_VALID_AFTER, + PROP_CERT_SUBJECT_NAME, + PROP_CERT_ISSUER_NAME, + PROP_CERT_DNS_NAMES, + PROP_CERT_IP_ADDRESSES, }; static void g_test_tls_certificate_initable_iface_init (GInitableIface *iface); @@ -135,6 +141,8 @@ g_test_tls_certificate_get_property (GObject *object, GParamSpec *pspec) { GTestTlsCertificate *cert = (GTestTlsCertificate *) object; + GPtrArray *data = NULL; + const gchar *dns_name = "a.example.com"; switch (prop_id) { @@ -156,6 +164,28 @@ g_test_tls_certificate_get_property (GObject *object, case PROP_CERT_PRIVATE_KEY_PKCS11_URI: g_value_set_string (value, cert->private_key_pkcs11_uri); break; + case PROP_CERT_NOT_VALID_BEFORE: + g_value_take_boxed (value, g_date_time_new_from_iso8601 ("2020-10-12T17:49:44Z", NULL)); + break; + case PROP_CERT_NOT_VALID_AFTER: + g_value_take_boxed (value, g_date_time_new_from_iso8601 ("2045-10-06T17:49:44Z", NULL)); + break; + case PROP_CERT_SUBJECT_NAME: + g_value_set_string (value, "DC=COM,DC=EXAMPLE,CN=server.example.com"); + break; + case PROP_CERT_ISSUER_NAME: + g_value_set_string (value, "DC=COM,DC=EXAMPLE,OU=Certificate Authority,CN=ca.example.com,emailAddress=ca@example.com"); + break; + case PROP_CERT_DNS_NAMES: + data = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref); + g_ptr_array_add (data, g_bytes_new_static (dns_name, strlen (dns_name))); + g_value_take_boxed (value, data); + break; + case PROP_CERT_IP_ADDRESSES: + data = g_ptr_array_new_with_free_func (g_object_unref); + g_ptr_array_add (data, g_inet_address_new_from_string ("192.0.2.1")); + g_value_take_boxed (value, data); + break; default: g_assert_not_reached (); break; @@ -230,6 +260,12 @@ g_test_tls_certificate_class_init (GTestTlsCertificateClass *test_class) g_object_class_override_property (gobject_class, PROP_CERT_ISSUER, "issuer"); g_object_class_override_property (gobject_class, PROP_CERT_PKCS11_URI, "pkcs11-uri"); g_object_class_override_property (gobject_class, PROP_CERT_PRIVATE_KEY_PKCS11_URI, "private-key-pkcs11-uri"); + g_object_class_override_property (gobject_class, PROP_CERT_NOT_VALID_BEFORE, "not-valid-before"); + g_object_class_override_property (gobject_class, PROP_CERT_NOT_VALID_AFTER, "not-valid-after"); + g_object_class_override_property (gobject_class, PROP_CERT_SUBJECT_NAME, "subject-name"); + g_object_class_override_property (gobject_class, PROP_CERT_ISSUER_NAME, "issuer-name"); + g_object_class_override_property (gobject_class, PROP_CERT_DNS_NAMES, "dns-names"); + g_object_class_override_property (gobject_class, PROP_CERT_IP_ADDRESSES, "ip-addresses"); } static void @@ -371,12 +407,6 @@ g_test_tls_connection_initable_iface_init (GInitableIface *iface) iface->init = g_test_tls_connection_initable_init; } -const gchar * -g_test_tls_connection_get_private_key_pem (GTlsCertificate *cert) -{ - return ((GTestTlsCertificate *)cert)->key_pem; -} - /* Test database type */ typedef struct _GTestTlsDatabase GTestTlsDatabase; diff --git a/gio/tests/gtesttlsbackend.h b/gio/tests/gtesttlsbackend.h index 11a8bf149..07948fddc 100644 --- a/gio/tests/gtesttlsbackend.h +++ b/gio/tests/gtesttlsbackend.h @@ -39,9 +39,6 @@ struct _GTestTlsBackendClass { GType _g_test_tls_backend_get_type (void); -const gchar *g_test_tls_connection_get_private_key_pem (GTlsCertificate *cert); - - G_END_DECLS #endif /* __G_TEST_TLS_BACKEND_H__ */ diff --git a/gio/tests/httpd.c b/gio/tests/httpd.c index 9bca6c96c..6658e15f1 100644 --- a/gio/tests/httpd.c +++ b/gio/tests/httpd.c @@ -6,7 +6,7 @@ static char *root = NULL; static GOptionEntry cmd_entries[] = { {"port", 'p', 0, G_OPTION_ARG_INT, &port, "Local port to bind to", NULL}, - {NULL} + G_OPTION_ENTRY_NULL }; static void diff --git a/gio/tests/live-g-file.c b/gio/tests/live-g-file.c index 316e23c9e..9e2cc0c27 100644 --- a/gio/tests/live-g-file.c +++ b/gio/tests/live-g-file.c @@ -1371,7 +1371,7 @@ main (int argc, char *argv[]) {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL}, {"posix", 'x', 0, G_OPTION_ARG_NONE, &posix_compat, "Test POSIX-specific features (unix permissions, symlinks)", NULL}, - {NULL} + G_OPTION_ENTRY_NULL }; test_suite = FALSE; diff --git a/gio/tests/memory-output-stream.c b/gio/tests/memory-output-stream.c index 72da6263d..b448516df 100644 --- a/gio/tests/memory-output-stream.c +++ b/gio/tests/memory-output-stream.c @@ -33,7 +33,7 @@ test_truncate (void) GError *error = NULL; guint8 *data; - g_test_bug ("540423"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=540423"); mo = g_memory_output_stream_new_resizable (); g_assert (g_seekable_can_truncate (G_SEEKABLE (mo))); @@ -66,7 +66,7 @@ test_truncate (void) for (i = 1000; i < 3000; i++) g_assert_cmpuint (data[i], ==, 2); - g_test_bug ("720080"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=720080"); g_seekable_truncate (G_SEEKABLE (mo), 8192, NULL, &error); g_assert_cmpint (g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (mo)), ==, 8192); @@ -199,7 +199,7 @@ test_data_size (void) GDataOutputStream *o; int pos; - g_test_bug ("540459"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=540459"); mo = g_memory_output_stream_new_resizable (); o = g_data_output_stream_new (mo); @@ -211,7 +211,7 @@ test_data_size (void) pos = g_seekable_tell (G_SEEKABLE (mo)); g_assert_cmpint (pos, ==, 1); - g_test_bug ("540461"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=540461"); g_seekable_seek (G_SEEKABLE (mo), 0, G_SEEK_SET, NULL, NULL); pos = g_seekable_tell (G_SEEKABLE (mo)); @@ -239,7 +239,7 @@ test_properties (void) gpointer data_prop; gpointer func; - g_test_bug ("605733"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=605733"); mo = (GOutputStream*) g_object_new (G_TYPE_MEMORY_OUTPUT_STREAM, "realloc-function", g_realloc, @@ -430,7 +430,6 @@ main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ("/memory-output-stream/truncate", test_truncate); g_test_add_func ("/memory-output-stream/seek/fixed", test_seek_fixed); diff --git a/gio/tests/meson.build b/gio/tests/meson.build index a926ae01a..98d1401d0 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -675,10 +675,8 @@ if not meson.is_cross_build() or meson.has_exe_wrapper() ] # Create object file containing resource data for testing the --external-data - # option. Currently only GNU ld and GNU objcopy support the right options. - # Support for --add-symbol was added to LLVM objcopy in 2019 - # (https://reviews.llvm.org/D58234). FIXME: This test could be enabled for - # LLVM once that support is in a stable release. + # option. Currently only GNU ld and objcopy, or (as of 2019) LLVM ld and + # objcopy, support the right options. objcopy_supports_add_symbol = false objcopy = find_program('objcopy', required : false) if objcopy.found() @@ -687,7 +685,7 @@ if not meson.is_cross_build() or meson.has_exe_wrapper() ld = find_program('ld', required : false) - if build_machine.system() == 'linux' and cc.get_id() == 'gcc' and objcopy.found() and objcopy_supports_add_symbol and ld.found() + if build_machine.system() == 'linux' and objcopy.found() and objcopy_supports_add_symbol and ld.found() test_gresource_binary = custom_target('test5.gresource', input : 'test5.gresource.xml', output : 'test5.gresource', diff --git a/gio/tests/mimeapps.c b/gio/tests/mimeapps.c index 08bcce247..6d7785299 100644 --- a/gio/tests/mimeapps.c +++ b/gio/tests/mimeapps.c @@ -5,7 +5,7 @@ static gboolean strv_equal (gchar **strv, ...) { - gint count; + gsize count; va_list list; const gchar *str; gboolean res; diff --git a/gio/tests/network-address.c b/gio/tests/network-address.c index cbebb6c9f..946a8f25f 100644 --- a/gio/tests/network-address.c +++ b/gio/tests/network-address.c @@ -1011,7 +1011,7 @@ test_happy_eyeballs_ipv6_error_ipv4_very_slow (HappyEyeballsFixture *fixture, AsyncData data = { 0 }; GError *ipv6_error; - g_test_bug ("merge_requests/865"); + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/merge_requests/865"); g_test_summary ("Ensure that we successfully return IPv4 results even when they come significantly later than an IPv6 failure."); /* If ipv6 fails, ensuring that ipv6 errors before ipv4 finishes, we still get ipv4. */ @@ -1183,38 +1183,37 @@ test_happy_eyeballs_both_error_delays_3 (HappyEyeballsFixture *fixture, int main (int argc, char *argv[]) { - gint i; + gsize i; gchar *path; g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://gitlab.gnome.org/GNOME/glib/"); g_test_add_func ("/network-address/basic", test_basic); for (i = 0; i < G_N_ELEMENTS (host_tests); i++) { - path = g_strdup_printf ("/network-address/parse-host/%d", i); + path = g_strdup_printf ("/network-address/parse-host/%" G_GSIZE_FORMAT, i); g_test_add_data_func (path, &host_tests[i], test_parse_host); g_free (path); } for (i = 0; i < G_N_ELEMENTS (uri_tests); i++) { - path = g_strdup_printf ("/network-address/parse-uri/%d", i); + path = g_strdup_printf ("/network-address/parse-uri/%" G_GSIZE_FORMAT, i); g_test_add_data_func (path, &uri_tests[i], test_parse_uri); g_free (path); } for (i = 0; i < G_N_ELEMENTS (address_tests); i++) { - path = g_strdup_printf ("/network-address/resolve-address/%d", i); + path = g_strdup_printf ("/network-address/resolve-address/%" G_GSIZE_FORMAT, i); g_test_add_data_func (path, &address_tests[i], test_resolve_address); g_free (path); } for (i = 0; i < G_N_ELEMENTS (address_tests); i++) { - path = g_strdup_printf ("/gresolver/resolve-address/%d", i); + path = g_strdup_printf ("/gresolver/resolve-address/%" G_GSIZE_FORMAT, i); g_test_add_data_func (path, &address_tests[i], test_resolve_address_gresolver); g_free (path); } diff --git a/gio/tests/network-monitor-race.c b/gio/tests/network-monitor-race.c index 9c6866e6a..00bd6fa8e 100644 --- a/gio/tests/network-monitor-race.c +++ b/gio/tests/network-monitor-race.c @@ -58,7 +58,7 @@ test_network_monitor (void) { guint ii; - g_test_bug ("793727"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=793727"); if (g_test_subprocess ()) { @@ -86,7 +86,6 @@ int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugzilla.gnome.org/show_bug.cgi?id="); g_test_add_func ("/network-monitor/create-in-thread", test_network_monitor); diff --git a/gio/tests/org.gtk.schemasourcecheck.gschema.xml b/gio/tests/org.gtk.schemasourcecheck.gschema.xml index 42c9c5104..b484da1a3 100644 --- a/gio/tests/org.gtk.schemasourcecheck.gschema.xml +++ b/gio/tests/org.gtk.schemasourcecheck.gschema.xml @@ -1,7 +1,8 @@ <schemalist> - <schema id="org.gtk.schemasourcecheck" path="/tests/"> + <schema id="org.gtk.schemasourcecheck"> <key name="enabled" type="b"> <default>true</default> </key> + <child name="child" schema="org.gtk.schemasourcecheck" /> </schema> </schemalist> diff --git a/gio/tests/proxy-test.c b/gio/tests/proxy-test.c index e3c0d09c7..eec4bf7ca 100644 --- a/gio/tests/proxy-test.c +++ b/gio/tests/proxy-test.c @@ -842,8 +842,8 @@ do_echo_test (GSocketConnection *conn) GIOStream *iostream = G_IO_STREAM (conn); GInputStream *istream = g_io_stream_get_input_stream (iostream); GOutputStream *ostream = g_io_stream_get_output_stream (iostream); - gssize nread, total; - gsize nwrote; + gssize nread; + gsize nwrote, total; gchar buf[128]; GError *error = NULL; diff --git a/gio/tests/readwrite.c b/gio/tests/readwrite.c index 2aa925b30..7551e5384 100644 --- a/gio/tests/readwrite.c +++ b/gio/tests/readwrite.c @@ -32,6 +32,7 @@ static void verify_iostream (GFileIOStream *file_iostream) { gboolean res; + gssize skipped; GIOStream *iostream; GError *error; GInputStream *in; @@ -73,8 +74,9 @@ verify_iostream (GFileIOStream *file_iostream) g_assert (res == 5); verify_pos (iostream, 15); - res = g_input_stream_skip (in, 10000, NULL, NULL); - g_assert (res == strlen (original_data) - 15); + skipped = g_input_stream_skip (in, 10000, NULL, NULL); + g_assert_cmpint (skipped, >=, 0); + g_assert ((gsize) skipped == strlen (original_data) - 15); verify_pos (iostream, strlen (original_data)); res = g_seekable_seek (G_SEEKABLE (iostream), diff --git a/gio/tests/resolver.c b/gio/tests/resolver.c index 3e6d89670..6e0c4d73b 100644 --- a/gio/tests/resolver.c +++ b/gio/tests/resolver.c @@ -672,7 +672,7 @@ static const GOptionEntry option_entries[] = { { "synchronous", 's', 0, G_OPTION_ARG_NONE, &synchronous, "Synchronous connections", NULL }, { "connectable", 'c', 0, G_OPTION_ARG_INT, &connectable_count, "Connectable count", "C" }, { "special-type", 't', 0, G_OPTION_ARG_CALLBACK, record_type_arg, "Record type like MX, TXT, NS or SOA", "RR" }, - { NULL }, + G_OPTION_ENTRY_NULL, }; int diff --git a/gio/tests/send-data.c b/gio/tests/send-data.c index a66976fa3..d70502eca 100644 --- a/gio/tests/send-data.c +++ b/gio/tests/send-data.c @@ -20,7 +20,7 @@ static GOptionEntry cmd_entries[] = { "Time out socket I/O after the specified number of seconds", NULL}, {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose debugging output", NULL}, - {NULL} + G_OPTION_ENTRY_NULL }; static gpointer diff --git a/gio/tests/sleepy-stream.c b/gio/tests/sleepy-stream.c index 664fb3b02..bbbeb2534 100644 --- a/gio/tests/sleepy-stream.c +++ b/gio/tests/sleepy-stream.c @@ -285,7 +285,6 @@ int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ("/filter-stream/input", test); g_test_add_func ("/filter-stream/async", asynch); diff --git a/gio/tests/socket-client.c b/gio/tests/socket-client.c index 8df1c28f3..6c25e08c9 100644 --- a/gio/tests/socket-client.c +++ b/gio/tests/socket-client.c @@ -34,7 +34,7 @@ static GOptionEntry cmd_entries[] = { "Time out reads after the specified number of seconds", NULL}, {"tls", 'T', 0, G_OPTION_ARG_NONE, &tls, "Use TLS (SSL)", NULL}, - {NULL} + G_OPTION_ENTRY_NULL }; #include "socket-common.c" diff --git a/gio/tests/socket-common.c b/gio/tests/socket-common.c index e59fa9cd4..18d083a30 100644 --- a/gio/tests/socket-common.c +++ b/gio/tests/socket-common.c @@ -45,7 +45,7 @@ static GSocketAddress * socket_address_from_string (const char *name) { #ifdef G_OS_UNIX - int i, len; + gsize i, len; for (i = 0; i < G_N_ELEMENTS (unix_socket_address_types); i++) { diff --git a/gio/tests/socket-listener.c b/gio/tests/socket-listener.c index 71e70b28f..6ceed13d4 100644 --- a/gio/tests/socket-listener.c +++ b/gio/tests/socket-listener.c @@ -86,8 +86,6 @@ main (int argc, { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); - g_test_add_func ("/socket-listener/event-signal", test_event_signal); return g_test_run(); diff --git a/gio/tests/socket-server.c b/gio/tests/socket-server.c index 24cf0182e..8b0d2a925 100644 --- a/gio/tests/socket-server.c +++ b/gio/tests/socket-server.c @@ -40,7 +40,7 @@ static GOptionEntry cmd_entries[] = { "Time out reads after the specified number of seconds", NULL}, {"tls", 'T', 0, G_OPTION_ARG_STRING, &tls_cert_file, "Use TLS (SSL) with indicated server certificate", "CERTFILE"}, - {NULL} + G_OPTION_ENTRY_NULL }; #include "socket-common.c" diff --git a/gio/tests/socket-service.c b/gio/tests/socket-service.c index c763fa6e6..a00c0c499 100644 --- a/gio/tests/socket-service.c +++ b/gio/tests/socket-service.c @@ -182,7 +182,7 @@ test_threaded_712570 (void) GSocketClient *client; GError *error = NULL; - g_test_bug ("712570"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=712570"); g_mutex_lock (&mutex_712570); @@ -557,8 +557,6 @@ main (int argc, { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); - g_test_add_func ("/socket-service/start-stop", test_start_stop); g_test_add_func ("/socket-service/threaded/712570", test_threaded_712570); g_test_add_func ("/socket-service/read_write_async", test_read_write_async); diff --git a/gio/tests/socket.c b/gio/tests/socket.c index ee098c55f..fa96a4087 100644 --- a/gio/tests/socket.c +++ b/gio/tests/socket.c @@ -502,7 +502,7 @@ test_ip_sync (GSocketFamily family) g_assert_cmpstr (testbuf, ==, buf); { - GOutputVector v[7] = { { NULL, }, }; + GOutputVector v[7] = { { NULL, 0 }, }; v[0].buffer = testbuf2 + 0; v[0].size = 3; @@ -627,10 +627,10 @@ test_ip_sync_dgram (GSocketFamily family) g_assert_cmpstr (testbuf, ==, buf); { - GOutputMessage m[3] = { { NULL, }, }; - GInputMessage im[3] = { { NULL, }, }; - GOutputVector v[7] = { { NULL, }, }; - GInputVector iv[7] = { { NULL, }, }; + GOutputMessage m[3] = { { NULL, NULL, 0, 0, NULL, 0 }, }; + GInputMessage im[3] = { { NULL, NULL, 0, 0, 0, NULL, 0 }, }; + GOutputVector v[7] = { { NULL, 0 }, }; + GInputVector iv[7] = { { NULL, 0 }, }; v[0].buffer = testbuf2 + 0; v[0].size = 3; @@ -868,8 +868,8 @@ test_ip_sync_dgram_timeouts (GSocketFamily family) /* Check for timeouts when no server is running. */ { gint64 start_time; - GInputMessage im = { NULL, }; - GInputVector iv = { NULL, }; + GInputMessage im = { NULL, NULL, 0, 0, 0, NULL, 0 }; + GInputVector iv = { NULL, 0 }; guint8 buf[128]; iv.buffer = buf; @@ -1227,7 +1227,7 @@ test_fd_reuse (void) gssize len; gchar buf[128]; - g_test_bug ("741707"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=741707"); data = create_server (G_SOCKET_FAMILY_IPV4, echo_server_thread, FALSE, &error); if (error != NULL) @@ -1694,7 +1694,8 @@ test_get_available (gconstpointer user_data) for (tries = 0; tries < 100; tries++) { - if (g_socket_get_available_bytes (server) > sizeof (data)) + gssize res = g_socket_get_available_bytes (server); + if ((res == -1) || ((gsize) res > sizeof (data))) break; g_usleep (100000); } @@ -2139,7 +2140,6 @@ main (int argc, GError *error = NULL; g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugzilla.gnome.org/"); sock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM, diff --git a/gio/tests/testfilemonitor.c b/gio/tests/testfilemonitor.c index b74dc2b71..a52ade715 100644 --- a/gio/tests/testfilemonitor.c +++ b/gio/tests/testfilemonitor.c @@ -118,7 +118,8 @@ check_expected_events (RecordedEvent *expected, GList *recorded, Environment env) { - gint i, li; + gsize i; + gint li; GList *l; for (i = 0, li = 0, l = recorded; i < n_expected && l != NULL;) @@ -217,7 +218,7 @@ check_expected_events (RecordedEvent *expected, e2->event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { g_test_message ("Event CHANGES_DONE_HINT ignored at " - "expected index %d, recorded index %d", i, li); + "expected index %" G_GSIZE_FORMAT ", recorded index %d", i, li); li++, l = l->next; continue; } @@ -225,7 +226,7 @@ check_expected_events (RecordedEvent *expected, * the event doesn't match, it means the expected event has lost. */ else if (env & e1->optional) { - g_test_message ("Event %d at expected index %d skipped because " + g_test_message ("Event %d at expected index %" G_GSIZE_FORMAT " skipped because " "it is marked as optional", e1->event_type, i); i++; continue; @@ -957,7 +958,7 @@ test_file_hard_links (Fixture *fixture, GError *error = NULL; TestData data; - g_test_bug ("755721"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=755721"); #ifdef HAVE_LINK g_test_message ("Running with hard link tests"); @@ -1011,8 +1012,6 @@ main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugzilla.gnome.org/show_bug.cgi?id="); - g_test_add ("/monitor/atomic-replace", Fixture, NULL, setup, test_atomic_replace, teardown); g_test_add ("/monitor/file-changes", Fixture, NULL, setup, test_file_changes, teardown); g_test_add ("/monitor/dir-monitor", Fixture, NULL, setup, test_dir_monitor, teardown); diff --git a/gio/tests/tls-certificate.c b/gio/tests/tls-certificate.c index 9dd415091..2995b1028 100644 --- a/gio/tests/tls-certificate.c +++ b/gio/tests/tls-certificate.c @@ -40,7 +40,7 @@ pem_parser (const Reference *ref) gchar *pem; gsize pem_len = 0; gchar *parsed_cert_pem = NULL; - const gchar *parsed_key_pem = NULL; + gchar *parsed_key_pem = NULL; GError *error = NULL; /* Check PEM parsing in certificate, private key order. */ @@ -55,13 +55,12 @@ pem_parser (const Reference *ref) g_object_get (cert, "certificate-pem", &parsed_cert_pem, + "private-key-pem", &parsed_key_pem, NULL); - parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); - g_free (parsed_cert_pem); - parsed_cert_pem = NULL; + g_clear_pointer (&parsed_cert_pem, g_free); g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem); - parsed_key_pem = NULL; + g_clear_pointer (&parsed_key_pem, g_free); g_object_unref (cert); @@ -89,13 +88,12 @@ pem_parser (const Reference *ref) g_object_get (cert, "certificate-pem", &parsed_cert_pem, + "private-key-pem", &parsed_key_pem, NULL); - parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); - g_free (parsed_cert_pem); - parsed_cert_pem = NULL; + g_clear_pointer (&parsed_cert_pem, g_free); g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem); - parsed_key_pem = NULL; + g_clear_pointer (&parsed_key_pem, g_free); g_free (pem); g_object_unref (cert); @@ -111,11 +109,10 @@ pem_parser (const Reference *ref) g_object_get (cert, "certificate-pem", &parsed_cert_pem, + "private-key-pem", &parsed_key_pem, NULL); - parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); - g_free (parsed_cert_pem); - parsed_cert_pem = NULL; + g_clear_pointer (&parsed_cert_pem, g_free); g_assert_null (parsed_key_pem); g_free (pem); @@ -141,7 +138,7 @@ pem_parser_handles_chain (const Reference *ref) GTlsCertificate *original_cert; gchar *pem; gchar *parsed_cert_pem = NULL; - const gchar *parsed_key_pem = NULL; + gchar *parsed_key_pem = NULL; GError *error = NULL; /* Check that a chain with exactly three certificates is returned */ @@ -156,14 +153,14 @@ pem_parser_handles_chain (const Reference *ref) g_object_get (cert, "certificate-pem", &parsed_cert_pem, + "private-key-pem", &parsed_key_pem, NULL); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); g_clear_pointer (&parsed_cert_pem, g_free); /* Make sure the private key was parsed */ - parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert); g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem); - parsed_key_pem = NULL; + g_clear_pointer (&parsed_key_pem, g_free); /* Now test the second cert */ issuer = g_tls_certificate_get_issuer (cert); @@ -175,12 +172,12 @@ pem_parser_handles_chain (const Reference *ref) g_object_get (cert, "certificate-pem", &parsed_cert_pem, + "private-key-pem", &parsed_key_pem, NULL); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[1]); g_clear_pointer (&parsed_cert_pem, g_free); /* Only the first cert should have a private key */ - parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert); g_assert_null (parsed_key_pem); /* Now test the final cert */ @@ -190,11 +187,11 @@ pem_parser_handles_chain (const Reference *ref) g_object_get (cert, "certificate-pem", &parsed_cert_pem, + "private-key-pem", &parsed_key_pem, NULL); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[2]); g_clear_pointer (&parsed_cert_pem, g_free); - parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert); g_assert_null (parsed_key_pem); g_object_unref (original_cert); @@ -237,7 +234,7 @@ from_file (const Reference *ref) { GTlsCertificate *cert; gchar *parsed_cert_pem = NULL; - const gchar *parsed_key_pem = NULL; + gchar *parsed_key_pem = NULL; GError *error = NULL; cert = g_tls_certificate_new_from_file (g_test_get_filename (G_TEST_DIST, "cert-tests", "key-cert.pem", NULL), @@ -247,13 +244,12 @@ from_file (const Reference *ref) g_object_get (cert, "certificate-pem", &parsed_cert_pem, + "private-key-pem", &parsed_key_pem, NULL); - parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); - g_free (parsed_cert_pem); - parsed_cert_pem = NULL; + g_clear_pointer (&parsed_cert_pem, g_free); g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem); - parsed_key_pem = NULL; + g_clear_pointer (&parsed_key_pem, g_free); g_object_unref (cert); } @@ -263,7 +259,7 @@ from_files (const Reference *ref) { GTlsCertificate *cert; gchar *parsed_cert_pem = NULL; - const gchar *parsed_key_pem = NULL; + gchar *parsed_key_pem = NULL; GError *error = NULL; cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL), @@ -274,13 +270,12 @@ from_files (const Reference *ref) g_object_get (cert, "certificate-pem", &parsed_cert_pem, + "private-key-pem", &parsed_key_pem, NULL); - parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); - g_free (parsed_cert_pem); - parsed_cert_pem = NULL; + g_clear_pointer (&parsed_cert_pem, g_free); g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem); - parsed_key_pem = NULL; + g_clear_pointer (&parsed_key_pem, g_free); g_object_unref (cert); @@ -332,7 +327,7 @@ from_files_crlf (const Reference *ref) { GTlsCertificate *cert; gchar *parsed_cert_pem = NULL; - const gchar *parsed_key_pem = NULL; + gchar *parsed_key_pem = NULL; GError *error = NULL; cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert-crlf.pem", NULL), @@ -343,13 +338,12 @@ from_files_crlf (const Reference *ref) g_object_get (cert, "certificate-pem", &parsed_cert_pem, + "private-key-pem", &parsed_key_pem, NULL); - parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_crlf_pem); - g_free (parsed_cert_pem); - parsed_cert_pem = NULL; + g_clear_pointer (&parsed_cert_pem, g_free); g_assert_cmpstr (parsed_key_pem, ==, ref->key_crlf_pem); - parsed_key_pem = NULL; + g_clear_pointer (&parsed_key_pem, g_free); g_object_unref (cert); } @@ -359,7 +353,7 @@ from_files_pkcs8 (const Reference *ref) { GTlsCertificate *cert; gchar *parsed_cert_pem = NULL; - const gchar *parsed_key_pem = NULL; + gchar *parsed_key_pem = NULL; GError *error = NULL; cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL), @@ -370,13 +364,12 @@ from_files_pkcs8 (const Reference *ref) g_object_get (cert, "certificate-pem", &parsed_cert_pem, + "private-key-pem", &parsed_key_pem, NULL); - parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); - g_free (parsed_cert_pem); - parsed_cert_pem = NULL; + g_clear_pointer (&parsed_cert_pem, g_free); g_assert_cmpstr (parsed_key_pem, ==, ref->key8_pem); - parsed_key_pem = NULL; + g_clear_pointer (&parsed_key_pem, g_free); g_object_unref (cert); } @@ -462,6 +455,137 @@ from_unsupported_pkcs11_uri (void) g_clear_error (&error); } +static void +not_valid_before (void) +{ + const gchar *EXPECTED_NOT_VALID_BEFORE = "2020-10-12T17:49:44Z"; + + GTlsCertificate *cert; + GError *error = NULL; + GDateTime *actual; + gchar *actual_str; + + cert = g_tls_certificate_new_from_pkcs11_uris ("pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=ca-bundle.crt", NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (cert); + + actual = g_tls_certificate_get_not_valid_before (cert); + g_assert_nonnull (actual); + actual_str = g_date_time_format_iso8601 (actual); + g_assert_cmpstr (actual_str, ==, EXPECTED_NOT_VALID_BEFORE); + g_free (actual_str); + g_date_time_unref (actual); + g_object_unref (cert); +} + +static void +not_valid_after (void) +{ + const gchar *EXPECTED_NOT_VALID_AFTER = "2045-10-06T17:49:44Z"; + + GTlsCertificate *cert; + GError *error = NULL; + GDateTime *actual; + gchar *actual_str; + + cert = g_tls_certificate_new_from_pkcs11_uris ("pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=ca-bundle.crt", NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (cert); + + actual = g_tls_certificate_get_not_valid_after (cert); + g_assert_nonnull (actual); + actual_str = g_date_time_format_iso8601 (actual); + g_assert_cmpstr (actual_str, ==, EXPECTED_NOT_VALID_AFTER); + g_free (actual_str); + g_date_time_unref (actual); + g_object_unref (cert); +} + +static void +subject_name (void) +{ + const gchar *EXPECTED_SUBJECT_NAME = "DC=COM,DC=EXAMPLE,CN=server.example.com"; + + GTlsCertificate *cert; + GError *error = NULL; + gchar *actual; + + cert = g_tls_certificate_new_from_pkcs11_uris ("pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=ca-bundle.crt", NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (cert); + + actual = g_tls_certificate_get_subject_name (cert); + g_assert_nonnull (actual); + g_assert_cmpstr (actual, ==, EXPECTED_SUBJECT_NAME); + g_free (actual); + g_object_unref (cert); +} + +static void +issuer_name (void) +{ + const gchar *EXPECTED_ISSUER_NAME = "DC=COM,DC=EXAMPLE,OU=Certificate Authority,CN=ca.example.com,emailAddress=ca@example.com"; + + GTlsCertificate *cert; + GError *error = NULL; + gchar *actual; + + cert = g_tls_certificate_new_from_pkcs11_uris ("pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=ca-bundle.crt", NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (cert); + + actual = g_tls_certificate_get_issuer_name (cert); + g_assert_nonnull (actual); + g_assert_cmpstr (actual, ==, EXPECTED_ISSUER_NAME); + g_free (actual); + g_object_unref (cert); +} + +static void +dns_names (void) +{ + GTlsCertificate *cert; + GError *error = NULL; + GPtrArray *actual; + const gchar *dns_name = "a.example.com"; + GBytes *expected = g_bytes_new_static (dns_name, strlen (dns_name)); + + cert = g_tls_certificate_new_from_pkcs11_uris ("pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=ca-bundle.crt", NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (cert); + + actual = g_tls_certificate_get_dns_names (cert); + g_assert_nonnull (actual); + g_assert_cmpuint (actual->len, ==, 1); + g_assert_true (g_ptr_array_find_with_equal_func (actual, expected, (GEqualFunc)g_bytes_equal, NULL)); + + g_ptr_array_free (actual, FALSE); + g_bytes_unref (expected); + g_object_unref (cert); +} + +static void +ip_addresses (void) +{ + GTlsCertificate *cert; + GError *error = NULL; + GPtrArray *actual; + GInetAddress *expected = g_inet_address_new_from_string ("192.0.2.1"); + + cert = g_tls_certificate_new_from_pkcs11_uris ("pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=ca-bundle.crt", NULL, &error); + g_assert_no_error (error); + g_assert_nonnull (cert); + + actual = g_tls_certificate_get_ip_addresses (cert); + g_assert_nonnull (actual); + g_assert_cmpuint (actual->len, ==, 1); + g_assert_true (g_ptr_array_find_with_equal_func (actual, expected, (GEqualFunc)g_inet_address_equal, NULL)); + + g_ptr_array_free (actual, TRUE); + g_object_unref (expected); + g_object_unref (cert); +} + int main (int argc, char *argv[]) @@ -532,6 +656,18 @@ main (int argc, from_pkcs11_uri); g_test_add_func ("/tls-certificate/pkcs11-uri-unsupported", from_unsupported_pkcs11_uri); + g_test_add_func ("/tls-certificate/not-valid-before", + not_valid_before); + g_test_add_func ("/tls-certificate/not-valid-after", + not_valid_after); + g_test_add_func ("/tls-certificate/subject-name", + subject_name); + g_test_add_func ("/tls-certificate/issuer-name", + issuer_name); + g_test_add_func ("/tls-certificate/dns-names", + dns_names); + g_test_add_func ("/tls-certificate/ip-addresses", + ip_addresses); g_test_add_func ("/tls-certificate/pem-parser-no-sentinel", pem_parser_no_sentinel); diff --git a/gio/tests/trash.c b/gio/tests/trash.c index adf729be2..2d3ec6774 100644 --- a/gio/tests/trash.c +++ b/gio/tests/trash.c @@ -38,7 +38,7 @@ test_trash_not_supported (void) gchar *parent_dirname; GStatBuf parent_stat, home_stat; - g_test_bug ("251"); + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/251"); /* The test assumes that tmp file is located on system internal mount. */ file = g_file_new_tmp ("test-trashXXXXXX", &stream, &error); @@ -105,7 +105,7 @@ test_trash_symlinks (void) gchar *target, *tmp, *target_over_symlink; GError *error = NULL; - g_test_bug ("1522"); + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1522"); target = g_build_filename (g_get_home_dir (), ".local", NULL); @@ -204,8 +204,6 @@ main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://gitlab.gnome.org/GNOME/glib/issues/"); - g_test_add_func ("/trash/not-supported", test_trash_not_supported); g_test_add_func ("/trash/symlinks", test_trash_symlinks); diff --git a/gio/tests/unix-streams.c b/gio/tests/unix-streams.c index 5ec829919..407a67dbd 100644 --- a/gio/tests/unix-streams.c +++ b/gio/tests/unix-streams.c @@ -474,8 +474,9 @@ test_write_wouldblock (void) gint fd[2]; GError *err = NULL; guint8 data_write[1024], data_read[1024]; - guint i; - gint pipe_capacity; + gsize i; + int retval; + gsize pipe_capacity; for (i = 0; i < sizeof (data_write); i++) data_write[i] = i; @@ -483,7 +484,9 @@ test_write_wouldblock (void) g_assert_cmpint (pipe (fd), ==, 0); g_assert_cmpint (fcntl (fd[0], F_SETPIPE_SZ, 4096, NULL), !=, 0); - pipe_capacity = fcntl (fd[0], F_GETPIPE_SZ, &pipe_capacity, NULL); + retval = fcntl (fd[0], F_GETPIPE_SZ); + g_assert_cmpint (retval, >=, 0); + pipe_capacity = (gsize) retval; g_assert_cmpint (pipe_capacity, >=, 4096); g_assert_cmpint (pipe_capacity % 1024, >=, 0); @@ -552,10 +555,11 @@ test_writev_wouldblock (void) gint fd[2]; GError *err = NULL; guint8 data_write[1024], data_read[1024]; - guint i; + gsize i; + int retval; + gsize pipe_capacity; GOutputVector vectors[4]; GPollableReturn res; - gint pipe_capacity; for (i = 0; i < sizeof (data_write); i++) data_write[i] = i; @@ -563,7 +567,9 @@ test_writev_wouldblock (void) g_assert_cmpint (pipe (fd), ==, 0); g_assert_cmpint (fcntl (fd[0], F_SETPIPE_SZ, 4096, NULL), !=, 0); - pipe_capacity = fcntl (fd[0], F_GETPIPE_SZ, &pipe_capacity, NULL); + retval = fcntl (fd[0], F_GETPIPE_SZ); + g_assert_cmpint (retval, >=, 0); + pipe_capacity = (gsize) retval; g_assert_cmpint (pipe_capacity, >=, 4096); g_assert_cmpint (pipe_capacity % 1024, >=, 0); @@ -667,8 +673,9 @@ test_write_async_wouldblock (void) GUnixOutputStream *os; gint fd[2]; guint8 *data, *data_read; - guint i; - gint pipe_capacity; + gsize i; + int retval; + gsize pipe_capacity; gsize bytes_written = 0, bytes_read = 0; g_assert_cmpint (pipe (fd), ==, 0); @@ -685,7 +692,9 @@ test_write_async_wouldblock (void) g_unix_set_fd_nonblocking (fd[1], TRUE, NULL); g_assert_cmpint (fcntl (fd[0], F_SETPIPE_SZ, 4096, NULL), !=, 0); - pipe_capacity = fcntl (fd[0], F_GETPIPE_SZ, &pipe_capacity, NULL); + retval = fcntl (fd[0], F_GETPIPE_SZ); + g_assert_cmpint (retval, >=, 0); + pipe_capacity = (gsize) retval; g_assert_cmpint (pipe_capacity, >=, 4096); data = g_new (guint8, 4 * pipe_capacity); @@ -754,8 +763,9 @@ test_writev_async_wouldblock (void) GUnixOutputStream *os; gint fd[2]; guint8 *data, *data_read; - guint i; - gint pipe_capacity; + gsize i; + int retval; + gsize pipe_capacity; gsize bytes_written = 0, bytes_read = 0; GOutputVector vectors[4]; @@ -773,7 +783,9 @@ test_writev_async_wouldblock (void) g_unix_set_fd_nonblocking (fd[1], TRUE, NULL); g_assert_cmpint (fcntl (fd[0], F_SETPIPE_SZ, 4096, NULL), !=, 0); - pipe_capacity = fcntl (fd[0], F_GETPIPE_SZ, &pipe_capacity, NULL); + retval = fcntl (fd[0], F_GETPIPE_SZ); + g_assert_cmpint (retval, >=, 0); + pipe_capacity = (gsize) retval; g_assert_cmpint (pipe_capacity, >=, 4096); data = g_new (guint8, 4 * pipe_capacity); @@ -56,7 +56,7 @@ <repository> <GitRepository> - <browse rdf:resource="https://gitlab.gnome.org/GNOME/glib/tree/master"/> + <browse rdf:resource="https://gitlab.gnome.org/GNOME/glib/"/> <location rdf:resource="https://gitlab.gnome.org/GNOME/glib.git"/> </GitRepository> </repository> @@ -700,7 +700,7 @@ fun:g_inet_address_get_type } -# From: https://github.com/fredericgermain/valgrind/blob/master/glibc-2.X-drd.supp +# From: https://github.com/fredericgermain/valgrind/blob/HEAD/glibc-2.X-drd.supp { drd-libc-stdio drd:ConflictingAccess diff --git a/glib/deprecated/gthread.h b/glib/deprecated/gthread.h index 33b422240..2d490a110 100644 --- a/glib/deprecated/gthread.h +++ b/glib/deprecated/gthread.h @@ -125,7 +125,11 @@ void g_thread_foreach (GFunc thread_func, #endif #define g_static_mutex_get_mutex g_static_mutex_get_mutex_impl GLIB_DEPRECATED_MACRO_IN_2_32 +#ifndef G_OS_WIN32 +#define G_STATIC_MUTEX_INIT { NULL, PTHREAD_MUTEX_INITIALIZER } GLIB_DEPRECATED_MACRO_IN_2_32_FOR(g_mutex_init) +#else #define G_STATIC_MUTEX_INIT { NULL } GLIB_DEPRECATED_MACRO_IN_2_32_FOR(g_mutex_init) +#endif typedef struct { GMutex *mutex; diff --git a/glib/dirent/dirent.c b/glib/dirent/dirent.c index 26b6cb1e5..5b8f3ff80 100644 --- a/glib/dirent/dirent.c +++ b/glib/dirent/dirent.c @@ -135,7 +135,7 @@ _topendir (const _TCHAR *szPath) nd->dd_dir.d_ino = 0;
nd->dd_dir.d_reclen = 0;
nd->dd_dir.d_namlen = 0;
- memset (nd->dd_dir.d_name, 0, FILENAME_MAX);
+ memset (nd->dd_dir.d_name, 0, sizeof (nd->dd_dir.d_name));
return nd;
}
diff --git a/glib/dirent/dirent.h b/glib/dirent/dirent.h index 237665b4e..857710f6a 100644 --- a/glib/dirent/dirent.h +++ b/glib/dirent/dirent.h @@ -22,7 +22,7 @@ struct dirent long d_ino; /* Always zero. */
unsigned short d_reclen; /* Always zero. */
unsigned short d_namlen; /* Length of name in d_name. */
- char d_name[FILENAME_MAX]; /* File name. */
+ char d_name[FILENAME_MAX+1]; /* File name plus nul delimiter. */
};
#ifdef _WIN64
@@ -76,7 +76,7 @@ struct _wdirent long d_ino; /* Always zero. */
unsigned short d_reclen; /* Always zero. */
unsigned short d_namlen; /* Length of name in d_name. */
- wchar_t d_name[FILENAME_MAX]; /* File name. */
+ wchar_t d_name[FILENAME_MAX+1]; /* File name plus nul delimiter. */
};
/*
diff --git a/glib/galloca.h b/glib/galloca.h index 47151ee8b..014a0efcb 100644 --- a/glib/galloca.h +++ b/glib/galloca.h @@ -81,6 +81,11 @@ G_END_DECLS * way as out of stack space situations from infinite function recursion, i.e. * with a segmentation fault. * + * - Allowing @size to be specified by an untrusted party would allow for them + * to trigger a segmentation fault by specifying a large size, leading to a + * denial of service vulnerability. @size must always be entirely under the + * control of the program. + * * - Special care has to be taken when mixing alloca() with GNU C variable sized arrays. * Stack space allocated with alloca() in the same scope as a variable sized array * will be freed together with the variable sized array upon exit of that scope, and @@ -96,6 +101,12 @@ G_END_DECLS * * Wraps g_alloca() in a more typesafe manner. * + * As mentioned in the documentation for g_alloca(), @n_structs must always be + * entirely under the control of the program, or you may introduce a denial of + * service vulnerability. In addition, the multiplication of @struct_type by + * @n_structs is not checked, so an overflow may lead to a remote code execution + * vulnerability. + * * Returns: Pointer to stack space for @n_structs chunks of type @struct_type */ #define g_newa(struct_type, n_structs) ((struct_type*) g_alloca (sizeof (struct_type) * (gsize) (n_structs))) diff --git a/glib/garray.c b/glib/garray.c index 2b66f16a6..025747ee5 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -188,7 +188,7 @@ g_array_new (gboolean zero_terminated, /** * g_array_steal: * @array: a #GArray. - * @len: (optional) (out caller-allocates): pointer to retrieve the number of + * @len: (optional) (out): pointer to retrieve the number of * elements of the original array * * Frees the data in the array and resets the size to zero, while @@ -299,6 +299,27 @@ g_array_sized_new (gboolean zero_terminated, * functions, @clear_func is expected to clear the contents of * the array element it is given, but not free the element itself. * + * |[<!-- language="C" --> + * typedef struct + * { + * gchar *str; + * GObject *obj; + * } ArrayElement; + * + * static void + * array_element_clear (ArrayElement *element) + * { + * g_clear_pointer (&element->str, g_free); + * g_clear_object (&element->obj); + * } + * + * // main code + * GArray *garray = g_array_new (FALSE, FALSE, sizeof (ArrayElement)); + * g_array_set_clear_func (garray, (GDestroyNotify) array_element_clear); + * // assign data to the structure + * g_array_free (garray, TRUE); + * ]| + * * Since: 2.32 */ void @@ -867,7 +888,7 @@ g_array_sort_with_data (GArray *farray, * @array: a #GArray. * @target: a pointer to the item to look up. * @compare_func: A #GCompareFunc used to locate @target. - * @out_match_index: (optional) (out caller-allocates): return location + * @out_match_index: (optional) (out): return location * for the index of the element, if found. * * Checks whether @target exists in @array by performing a binary @@ -1114,7 +1135,7 @@ g_ptr_array_new (void) /** * g_ptr_array_steal: * @array: a #GPtrArray. - * @len: (optional) (out caller-allocates): pointer to retrieve the number of + * @len: (optional) (out): pointer to retrieve the number of * elements of the original array * * Frees the data in the array and resets the size to zero, while @@ -2099,7 +2120,7 @@ g_ptr_array_foreach (GPtrArray *array, * g_ptr_array_find: (skip) * @haystack: pointer array to be searched * @needle: pointer to look for - * @index_: (optional) (out caller-allocates): return location for the index of + * @index_: (optional) (out): return location for the index of * the element, if found * * Checks whether @needle exists in @haystack. If the element is found, %TRUE is @@ -2128,7 +2149,7 @@ g_ptr_array_find (GPtrArray *haystack, * @equal_func: (nullable): the function to call for each element, which should * return %TRUE when the desired element is found; or %NULL to use pointer * equality - * @index_: (optional) (out caller-allocates): return location for the index of + * @index_: (optional) (out): return location for the index of * the element, if found * * Checks whether @needle exists in @haystack, using the given @equal_func. @@ -2234,7 +2255,7 @@ g_byte_array_new (void) /** * g_byte_array_steal: * @array: a #GByteArray. - * @len: (optional) (out caller-allocates): pointer to retrieve the number of + * @len: (optional) (out): pointer to retrieve the number of * elements of the original array * * Frees the data in the array and resets the size to zero, while diff --git a/glib/gasyncqueue.c b/glib/gasyncqueue.c index a452617fd..db053f399 100644 --- a/glib/gasyncqueue.c +++ b/glib/gasyncqueue.c @@ -123,7 +123,7 @@ g_async_queue_new (void) /** * g_async_queue_new_full: - * @item_free_func: function to free queue elements + * @item_free_func: (nullable): function to free queue elements * * Creates a new asynchronous queue and sets up a destroy notify * function that is used to free any remaining queue items when diff --git a/glib/gatomic.h b/glib/gatomic.h index 2ad648aad..5583fb0c9 100644 --- a/glib/gatomic.h +++ b/glib/gatomic.h @@ -25,11 +25,7 @@ #endif #include <glib/gtypes.h> - -#if defined(glib_typeof_2_68) && GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68 -/* for glib_typeof */ -#include <type_traits> -#endif +#include <glib/glib-typeof.h> G_BEGIN_DECLS @@ -108,7 +104,7 @@ G_END_DECLS __atomic_store ((gint *)(atomic), &gais_temp, __ATOMIC_SEQ_CST); \ })) -#if defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) +#if defined(glib_typeof) #define g_atomic_pointer_get(atomic) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ @@ -125,7 +121,7 @@ G_END_DECLS (void) (0 ? (gpointer) * (atomic) : NULL); \ __atomic_store (gaps_temp_atomic, &gaps_temp_newval, __ATOMIC_SEQ_CST); \ })) -#else /* if !(defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68)) */ +#else /* if !(defined(glib_typeof) */ #define g_atomic_pointer_get(atomic) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ @@ -142,7 +138,7 @@ G_END_DECLS (void) (0 ? (gpointer) *(atomic) : NULL); \ __atomic_store (gaps_temp_atomic, &gaps_temp_newval, __ATOMIC_SEQ_CST); \ })) -#endif /* if defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) */ +#endif /* if defined(glib_typeof) */ #define g_atomic_int_inc(atomic) \ (G_GNUC_EXTENSION ({ \ @@ -307,7 +303,7 @@ G_END_DECLS __asm__ __volatile__ ("" : : : "memory"); \ gapg_result; \ })) -#if defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) +#if defined(glib_typeof) #define g_atomic_pointer_set(atomic, newval) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ @@ -316,7 +312,7 @@ G_END_DECLS __asm__ __volatile__ ("" : : : "memory"); \ *(atomic) = (glib_typeof (*(atomic))) (gsize) (newval); \ })) -#else /* if !(defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68)) */ +#else /* if !(defined(glib_typeof) */ #define g_atomic_pointer_set(atomic, newval) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ @@ -325,7 +321,7 @@ G_END_DECLS __asm__ __volatile__ ("" : : : "memory"); \ *(atomic) = (gpointer) (gsize) (newval); \ })) -#endif /* if defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) */ +#endif /* if defined(glib_typeof) */ #define g_atomic_int_inc(atomic) \ (G_GNUC_EXTENSION ({ \ @@ -428,7 +424,7 @@ G_END_DECLS #define g_atomic_int_dec_and_test(atomic) \ (g_atomic_int_dec_and_test ((gint *) (atomic))) -#if defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) +#if defined(glib_typeof) /* The (void *) cast in the middle *looks* redundant, because * g_atomic_pointer_get returns void * already, but it's to silence * -Werror=bad-function-cast when we're doing something like: @@ -438,7 +434,7 @@ G_END_DECLS * non-pointer-typed result. */ #define g_atomic_pointer_get(atomic) \ (glib_typeof (*(atomic))) (void *) ((g_atomic_pointer_get) ((void *) atomic)) -#else /* !(defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68)) */ +#else /* !(defined(glib_typeof) */ #define g_atomic_pointer_get(atomic) \ (g_atomic_pointer_get (atomic)) #endif diff --git a/glib/gbitlock.c b/glib/gbitlock.c index 45fb50999..9384d1a44 100644 --- a/glib/gbitlock.c +++ b/glib/gbitlock.c @@ -22,6 +22,7 @@ #include "gbitlock.h" +#include <glib/gmacros.h> #include <glib/gmessages.h> #include <glib/gatomic.h> #include <glib/gslist.h> @@ -75,8 +76,8 @@ static GSList *g_futex_address_list = NULL; * separate process. */ static void -g_futex_wait (const volatile gint *address, - gint value) +g_futex_wait (const gint *address, + gint value) { syscall (__NR_futex, address, (gsize) FUTEX_WAIT_PRIVATE, (gsize) value, NULL); } @@ -93,7 +94,7 @@ g_futex_wait (const volatile gint *address, * thread being woken up. */ static void -g_futex_wake (const volatile gint *address) +g_futex_wake (const gint *address) { syscall (__NR_futex, address, (gsize) FUTEX_WAKE_PRIVATE, (gsize) 1, NULL); } @@ -103,13 +104,13 @@ g_futex_wake (const volatile gint *address) /* emulate futex(2) */ typedef struct { - const volatile gint *address; - gint ref_count; - GCond wait_queue; + const gint *address; + gint ref_count; + GCond wait_queue; } WaitAddress; static WaitAddress * -g_futex_find_address (const volatile gint *address) +g_futex_find_address (const gint *address) { GSList *node; @@ -125,8 +126,8 @@ g_futex_find_address (const volatile gint *address) } static void -g_futex_wait (const volatile gint *address, - gint value) +g_futex_wait (const gint *address, + gint value) { g_mutex_lock (&g_futex_mutex); if G_LIKELY (g_atomic_int_get (address) == value) @@ -158,7 +159,7 @@ g_futex_wait (const volatile gint *address, } static void -g_futex_wake (const volatile gint *address) +g_futex_wake (const gint *address) { WaitAddress *waiter; @@ -176,10 +177,10 @@ g_futex_wake (const volatile gint *address) #endif #define CONTENTION_CLASSES 11 -static volatile gint g_bit_lock_contended[CONTENTION_CLASSES]; +static gint g_bit_lock_contended[CONTENTION_CLASSES]; /* (atomic) */ #if (defined (i386) || defined (__amd64__)) - #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + #if G_GNUC_CHECK_VERSION(4, 5) #define USE_ASM_GOTO 1 #endif #endif @@ -201,7 +202,8 @@ static volatile gint g_bit_lock_contended[CONTENTION_CLASSES]; * * This function accesses @address atomically. All other accesses to * @address must be atomic in order for this function to work - * reliably. + * reliably. While @address has a `volatile` qualifier, this is a historical + * artifact and the argument passed to it should not be `volatile`. * * Since: 2.24 **/ @@ -209,6 +211,8 @@ void g_bit_lock (volatile gint *address, gint lock_bit) { + gint *address_nonvolatile = (gint *) address; + #ifdef USE_ASM_GOTO retry: __asm__ volatile goto ("lock bts %1, (%0)\n" @@ -224,13 +228,13 @@ g_bit_lock (volatile gint *address, guint mask = 1u << lock_bit; guint v; - v = (guint) g_atomic_int_get (address); + v = (guint) g_atomic_int_get (address_nonvolatile); if (v & mask) { - guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended); + guint class = ((gsize) address_nonvolatile) % G_N_ELEMENTS (g_bit_lock_contended); g_atomic_int_add (&g_bit_lock_contended[class], +1); - g_futex_wait (address, v); + g_futex_wait (address_nonvolatile, v); g_atomic_int_add (&g_bit_lock_contended[class], -1); } } @@ -240,14 +244,14 @@ g_bit_lock (volatile gint *address, guint v; retry: - v = g_atomic_int_or (address, mask); + v = g_atomic_int_or (address_nonvolatile, mask); if (v & mask) /* already locked */ { - guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended); + guint class = ((gsize) address_nonvolatile) % G_N_ELEMENTS (g_bit_lock_contended); g_atomic_int_add (&g_bit_lock_contended[class], +1); - g_futex_wait (address, v); + g_futex_wait (address_nonvolatile, v); g_atomic_int_add (&g_bit_lock_contended[class], -1); goto retry; @@ -271,7 +275,8 @@ g_bit_lock (volatile gint *address, * * This function accesses @address atomically. All other accesses to * @address must be atomic in order for this function to work - * reliably. + * reliably. While @address has a `volatile` qualifier, this is a historical + * artifact and the argument passed to it should not be `volatile`. * * Returns: %TRUE if the lock was acquired * @@ -293,10 +298,11 @@ g_bit_trylock (volatile gint *address, return result; #else + gint *address_nonvolatile = (gint *) address; guint mask = 1u << lock_bit; guint v; - v = g_atomic_int_or (address, mask); + v = g_atomic_int_or (address_nonvolatile, mask); return ~v & mask; #endif @@ -313,7 +319,8 @@ g_bit_trylock (volatile gint *address, * * This function accesses @address atomically. All other accesses to * @address must be atomic in order for this function to work - * reliably. + * reliably. While @address has a `volatile` qualifier, this is a historical + * artifact and the argument passed to it should not be `volatile`. * * Since: 2.24 **/ @@ -321,6 +328,8 @@ void g_bit_unlock (volatile gint *address, gint lock_bit) { + gint *address_nonvolatile = (gint *) address; + #ifdef USE_ASM_GOTO __asm__ volatile ("lock btr %1, (%0)" : /* no output */ @@ -329,14 +338,14 @@ g_bit_unlock (volatile gint *address, #else guint mask = 1u << lock_bit; - g_atomic_int_and (address, ~mask); + g_atomic_int_and (address_nonvolatile, ~mask); #endif { - guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended); + guint class = ((gsize) address_nonvolatile) % G_N_ELEMENTS (g_bit_lock_contended); if (g_atomic_int_get (&g_bit_lock_contended[class])) - g_futex_wake (address); + g_futex_wake (address_nonvolatile); } } @@ -365,10 +374,10 @@ g_bit_unlock (volatile gint *address, * * g_futex_wake (g_futex_int_address (int_address)); */ -static const volatile gint * -g_futex_int_address (const volatile void *address) +static const gint * +g_futex_int_address (const void *address) { - const volatile gint *int_address = address; + const gint *int_address = address; /* this implementation makes these (reasonable) assumptions: */ G_STATIC_ASSERT (G_BYTE_ORDER == G_LITTLE_ENDIAN || @@ -394,12 +403,17 @@ g_futex_int_address (const volatile void *address) * For portability reasons, you may only lock on the bottom 32 bits of * the pointer. * + * While @address has a `volatile` qualifier, this is a historical + * artifact and the argument passed to it should not be `volatile`. + * * Since: 2.30 **/ void (g_pointer_bit_lock) (volatile void *address, gint lock_bit) { + void *address_nonvolatile = (void *) address; + g_return_if_fail (lock_bit < 32); { @@ -415,23 +429,23 @@ void contended: { - volatile gsize *pointer_address = address; + gsize *pointer_address = address_nonvolatile; gsize mask = 1u << lock_bit; gsize v; v = (gsize) g_atomic_pointer_get (pointer_address); if (v & mask) { - guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended); + guint class = ((gsize) address_nonvolatile) % G_N_ELEMENTS (g_bit_lock_contended); g_atomic_int_add (&g_bit_lock_contended[class], +1); - g_futex_wait (g_futex_int_address (address), v); + g_futex_wait (g_futex_int_address (address_nonvolatile), v); g_atomic_int_add (&g_bit_lock_contended[class], -1); } } goto retry; #else - volatile gsize *pointer_address = address; + gsize *pointer_address = address_nonvolatile; gsize mask = 1u << lock_bit; gsize v; @@ -440,10 +454,10 @@ void if (v & mask) /* already locked */ { - guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended); + guint class = ((gsize) address_nonvolatile) % G_N_ELEMENTS (g_bit_lock_contended); g_atomic_int_add (&g_bit_lock_contended[class], +1); - g_futex_wait (g_futex_int_address (address), (guint) v); + g_futex_wait (g_futex_int_address (address_nonvolatile), (guint) v); g_atomic_int_add (&g_bit_lock_contended[class], -1); goto retry; @@ -457,12 +471,15 @@ void * @address: (not nullable): a pointer to a #gpointer-sized value * @lock_bit: a bit value between 0 and 31 * - * This is equivalent to g_bit_trylock, but working on pointers (or + * This is equivalent to g_bit_trylock(), but working on pointers (or * other pointer-sized values). * * For portability reasons, you may only lock on the bottom 32 bits of * the pointer. * + * While @address has a `volatile` qualifier, this is a historical + * artifact and the argument passed to it should not be `volatile`. + * * Returns: %TRUE if the lock was acquired * * Since: 2.30 @@ -486,7 +503,8 @@ gboolean return result; #else - volatile gsize *pointer_address = address; + void *address_nonvolatile = (void *) address; + gsize *pointer_address = address_nonvolatile; gsize mask = 1u << lock_bit; gsize v; @@ -510,12 +528,17 @@ gboolean * For portability reasons, you may only lock on the bottom 32 bits of * the pointer. * + * While @address has a `volatile` qualifier, this is a historical + * artifact and the argument passed to it should not be `volatile`. + * * Since: 2.30 **/ void (g_pointer_bit_unlock) (volatile void *address, gint lock_bit) { + void *address_nonvolatile = (void *) address; + g_return_if_fail (lock_bit < 32); { @@ -525,16 +548,16 @@ void : "r" (address), "r" ((gsize) lock_bit) : "cc", "memory"); #else - volatile gsize *pointer_address = address; + gsize *pointer_address = address_nonvolatile; gsize mask = 1u << lock_bit; g_atomic_pointer_and (pointer_address, ~mask); #endif { - guint class = ((gsize) address) % G_N_ELEMENTS (g_bit_lock_contended); + guint class = ((gsize) address_nonvolatile) % G_N_ELEMENTS (g_bit_lock_contended); if (g_atomic_int_get (&g_bit_lock_contended[class])) - g_futex_wake (g_futex_int_address (address)); + g_futex_wake (g_futex_int_address (address_nonvolatile)); } } } diff --git a/glib/gbookmarkfile.c b/glib/gbookmarkfile.c index ff74a2e2d..14536ec9b 100644 --- a/glib/gbookmarkfile.c +++ b/glib/gbookmarkfile.c @@ -80,7 +80,7 @@ * displaying the bookmark inside a GUI. * * Here is an example of a bookmark file: - * [bookmarks.xbel](https://git.gnome.org/browse/glib/tree/glib/tests/bookmarks.xbel) + * [bookmarks.xbel](https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/glib/tests/bookmarks.xbel) * * A bookmark file might contain more than one bookmark; each bookmark * is accessed through its URI. @@ -552,9 +552,7 @@ static gchar * bookmark_item_dump (BookmarkItem *item) { GString *retval; - gchar *added, *visited, *modified; gchar *escaped_uri; - gchar *buffer; /* at this point, we must have at least a registered application; if we don't * we don't screw up the bookmark file, and just skip this item @@ -567,43 +565,63 @@ bookmark_item_dump (BookmarkItem *item) retval = g_string_sized_new (4096); - added = g_date_time_format_iso8601 (item->added); - modified = g_date_time_format_iso8601 (item->modified); - visited = g_date_time_format_iso8601 (item->visited); + g_string_append (retval, " <" XBEL_BOOKMARK_ELEMENT " "); escaped_uri = g_markup_escape_text (item->uri, -1); - buffer = g_strconcat (" <" - XBEL_BOOKMARK_ELEMENT - " " - XBEL_HREF_ATTRIBUTE "=\"", escaped_uri, "\" " - XBEL_ADDED_ATTRIBUTE "=\"", added, "\" " - XBEL_MODIFIED_ATTRIBUTE "=\"", modified, "\" " - XBEL_VISITED_ATTRIBUTE "=\"", visited, "\">\n", - NULL); - - g_string_append (retval, buffer); + g_string_append (retval, XBEL_HREF_ATTRIBUTE "=\""); + g_string_append (retval, escaped_uri); + g_string_append (retval , "\" "); g_free (escaped_uri); - g_free (visited); - g_free (modified); - g_free (added); - g_free (buffer); + + if (item->added) + { + char *added; + + added = g_date_time_format_iso8601 (item->added); + g_string_append (retval, XBEL_ADDED_ATTRIBUTE "=\""); + g_string_append (retval, added); + g_string_append (retval, "\" "); + g_free (added); + } + + if (item->modified) + { + char *modified; + + modified = g_date_time_format_iso8601 (item->modified); + g_string_append (retval, XBEL_MODIFIED_ATTRIBUTE "=\""); + g_string_append (retval, modified); + g_string_append (retval, "\" "); + g_free (modified); + } + + if (item->visited) + { + char *visited; + + visited = g_date_time_format_iso8601 (item->visited); + g_string_append (retval, XBEL_VISITED_ATTRIBUTE "=\""); + g_string_append (retval, visited); + g_string_append (retval, "\" "); + g_free (visited); + } + + if (retval->str[retval->len - 1] == ' ') + g_string_truncate (retval, retval->len - 1); + g_string_append (retval, ">\n"); if (item->title) { gchar *escaped_title; escaped_title = g_markup_escape_text (item->title, -1); - buffer = g_strconcat (" " - "<" XBEL_TITLE_ELEMENT ">", - escaped_title, - "</" XBEL_TITLE_ELEMENT ">\n", - NULL); - g_string_append (retval, buffer); + g_string_append (retval, " " "<" XBEL_TITLE_ELEMENT ">"); + g_string_append (retval, escaped_title); + g_string_append (retval, "</" XBEL_TITLE_ELEMENT ">\n"); g_free (escaped_title); - g_free (buffer); } if (item->description) @@ -611,15 +629,11 @@ bookmark_item_dump (BookmarkItem *item) gchar *escaped_desc; escaped_desc = g_markup_escape_text (item->description, -1); - buffer = g_strconcat (" " - "<" XBEL_DESC_ELEMENT ">", - escaped_desc, - "</" XBEL_DESC_ELEMENT ">\n", - NULL); - g_string_append (retval, buffer); + g_string_append (retval, " " "<" XBEL_DESC_ELEMENT ">"); + g_string_append (retval, escaped_desc); + g_string_append (retval, "</" XBEL_DESC_ELEMENT ">\n"); g_free (escaped_desc); - g_free (buffer); } if (item->metadata) @@ -629,17 +643,12 @@ bookmark_item_dump (BookmarkItem *item) metadata = bookmark_metadata_dump (item->metadata); if (metadata) { - buffer = g_strconcat (" " - "<" XBEL_INFO_ELEMENT ">\n", - metadata, - " " - "</" XBEL_INFO_ELEMENT ">\n", - NULL); - retval = g_string_append (retval, buffer); - - g_free (buffer); - g_free (metadata); - } + g_string_append (retval, " " "<" XBEL_INFO_ELEMENT ">\n"); + g_string_append (retval, metadata); + g_string_append (retval, " " "</" XBEL_INFO_ELEMENT ">\n"); + + g_free (metadata); + } } g_string_append (retval, " </" XBEL_BOOKMARK_ELEMENT ">\n"); diff --git a/glib/gbytes.c b/glib/gbytes.c index aaadf451b..a6ca0e300 100644 --- a/glib/gbytes.c +++ b/glib/gbytes.c @@ -538,3 +538,75 @@ g_bytes_unref_to_array (GBytes *bytes) data = g_bytes_unref_to_data (bytes, &size); return g_byte_array_new_take (data, size); } + +/** + * g_bytes_get_region: + * @bytes: a #GBytes + * @element_size: a non-zero element size + * @offset: an offset to the start of the region within the @bytes + * @n_elements: the number of elements in the region + * + * Gets a pointer to a region in @bytes. + * + * The region starts at @offset many bytes from the start of the data + * and contains @n_elements many elements of @element_size size. + * + * @n_elements may be zero, but @element_size must always be non-zero. + * Ideally, @element_size is a static constant (eg: sizeof a struct). + * + * This function does careful bounds checking (including checking for + * arithmetic overflows) and returns a non-%NULL pointer if the + * specified region lies entirely within the @bytes. If the region is + * in some way out of range, or if an overflow has occurred, then %NULL + * is returned. + * + * Note: it is possible to have a valid zero-size region. In this case, + * the returned pointer will be equal to the base pointer of the data of + * @bytes, plus @offset. This will be non-%NULL except for the case + * where @bytes itself was a zero-sized region. Since it is unlikely + * that you will be using this function to check for a zero-sized region + * in a zero-sized @bytes, %NULL effectively always means "error". + * + * Returns: (nullable): the requested region, or %NULL in case of an error + * + * Since: 2.70 + */ +gconstpointer +g_bytes_get_region (GBytes *bytes, + gsize element_size, + gsize offset, + gsize n_elements) +{ + gsize total_size; + gsize end_offset; + + g_return_val_if_fail (element_size > 0, NULL); + + /* No other assertion checks here. If something is wrong then we will + * simply crash (via NULL dereference or divide-by-zero). + */ + + if (!g_size_checked_mul (&total_size, element_size, n_elements)) + return NULL; + + if (!g_size_checked_add (&end_offset, offset, total_size)) + return NULL; + + /* We now have: + * + * 0 <= offset <= end_offset + * + * So we need only check that end_offset is within the range of the + * size of @bytes and we're good to go. + */ + + if (end_offset > bytes->size) + return NULL; + + /* We now have: + * + * 0 <= offset <= end_offset <= bytes->size + */ + + return ((guchar *) bytes->data) + offset; +}
\ No newline at end of file diff --git a/glib/gbytes.h b/glib/gbytes.h index 0bb1517b9..37cad861d 100644 --- a/glib/gbytes.h +++ b/glib/gbytes.h @@ -85,6 +85,13 @@ GLIB_AVAILABLE_IN_ALL gint g_bytes_compare (gconstpointer bytes1, gconstpointer bytes2); +GLIB_AVAILABLE_IN_2_70 +gconstpointer g_bytes_get_region (GBytes *bytes, + gsize element_size, + gsize offset, + gsize n_elements); + + G_END_DECLS #endif /* __G_BYTES_H__ */ diff --git a/glib/gcharset.c b/glib/gcharset.c index bb775bda4..9f91a9b48 100644 --- a/glib/gcharset.c +++ b/glib/gcharset.c @@ -36,6 +36,12 @@ #include <string.h> #include <stdio.h> + +#if (HAVE_LANGINFO_TIME_CODESET || HAVE_LANGINFO_CODESET) +#include <langinfo.h> +#endif + +#include <locale.h> #ifdef G_OS_WIN32 #define WIN32_LEAN_AND_MEAN #include <windows.h> @@ -215,6 +221,87 @@ g_get_charset (const char **charset) return cache->is_utf8; } +/* + * Do the same as g_get_charset() but it temporarily set locale (LC_ALL to + * LC_TIME) to correctly check for charset about time conversion relatives. + * + * Returns: %TRUE if the returned charset is UTF-8 + */ +gboolean +_g_get_time_charset (const char **charset) +{ + static GPrivate cache_private = G_PRIVATE_INIT (charset_cache_free); + GCharsetCache *cache = g_private_get (&cache_private); + const gchar *raw; + + if (!cache) + cache = g_private_set_alloc0 (&cache_private, sizeof (GCharsetCache)); + +#ifdef HAVE_LANGINFO_TIME_CODESET + raw = nl_langinfo (_NL_TIME_CODESET); +#else + G_LOCK (aliases); + raw = _g_locale_charset_raw (); + G_UNLOCK (aliases); +#endif + + if (cache->raw == NULL || strcmp (cache->raw, raw) != 0) + { + const gchar *new_charset; + + g_free (cache->raw); + g_free (cache->charset); + cache->raw = g_strdup (raw); + cache->is_utf8 = g_utf8_get_charset_internal (raw, &new_charset); + cache->charset = g_strdup (new_charset); + } + + if (charset) + *charset = cache->charset; + + return cache->is_utf8; +} +/* + * Do the same as g_get_charset() but it temporarily set locale (LC_ALL to + * LC_CTYPE) to correctly check for charset about CTYPE conversion relatives. + * + * Returns: %TRUE if the returned charset is UTF-8 + */ +gboolean +_g_get_ctype_charset (const char **charset) +{ + static GPrivate cache_private = G_PRIVATE_INIT (charset_cache_free); + GCharsetCache *cache = g_private_get (&cache_private); + const gchar *raw; + + if (!cache) + cache = g_private_set_alloc0 (&cache_private, sizeof (GCharsetCache)); + +#ifdef HAVE_LANGINFO_CODESET + raw = nl_langinfo (CODESET); +#else + G_LOCK (aliases); + raw = _g_locale_charset_raw (); + G_UNLOCK (aliases); +#endif + + if (cache->raw == NULL || strcmp (cache->raw, raw) != 0) + { + const gchar *new_charset; + + g_free (cache->raw); + g_free (cache->charset); + cache->raw = g_strdup (raw); + cache->is_utf8 = g_utf8_get_charset_internal (raw, &new_charset); + cache->charset = g_strdup (new_charset); + } + + if (charset) + *charset = cache->charset; + + return cache->is_utf8; +} + /** * g_get_codeset: * diff --git a/glib/gcharsetprivate.h b/glib/gcharsetprivate.h index f6b68dcd7..9b1def278 100644 --- a/glib/gcharsetprivate.h +++ b/glib/gcharsetprivate.h @@ -25,6 +25,10 @@ G_BEGIN_DECLS const char ** _g_charset_get_aliases (const char *canonical_name); +gboolean _g_get_time_charset (const char **charset); + +gboolean _g_get_ctype_charset (const char **charset); + G_END_DECLS #endif diff --git a/glib/gconvert.c b/glib/gconvert.c index f78cff01d..7697ff65d 100644 --- a/glib/gconvert.c +++ b/glib/gconvert.c @@ -40,6 +40,7 @@ #endif #include "gconvert.h" +#include "gconvertprivate.h" #include "gcharsetprivate.h" #include "gslist.h" @@ -1015,6 +1016,52 @@ g_locale_to_utf8 (const gchar *opsysstring, bytes_read, bytes_written, error); } +/* + * Do the exact same as g_locale_to_utf8 except that the charset would + * be retrieved from _g_get_time_charset (which uses LC_TIME) + * + * Returns: The converted string, or %NULL on an error. + */ +gchar * +_g_time_locale_to_utf8 (const gchar *opsysstring, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error) +{ + const char *charset; + + if (_g_get_time_charset (&charset)) + return strdup_len (opsysstring, len, bytes_read, bytes_written, error); + else + return convert_checked (opsysstring, len, "UTF-8", charset, + CONVERT_CHECK_NO_NULS_IN_OUTPUT, + bytes_read, bytes_written, error); +} + +/* + * Do the exact same as g_locale_to_utf8 except that the charset would + * be retrieved from _g_get_ctype_charset (which uses LC_CTYPE) + * + * Returns: The converted string, or %NULL on an error. + */ +gchar * +_g_ctype_locale_to_utf8 (const gchar *opsysstring, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error) +{ + const char *charset; + + if (_g_get_ctype_charset (&charset)) + return strdup_len (opsysstring, len, bytes_read, bytes_written, error); + else + return convert_checked (opsysstring, len, "UTF-8", charset, + CONVERT_CHECK_NO_NULS_IN_OUTPUT, + bytes_read, bytes_written, error); +} + /** * g_locale_from_utf8: * @utf8string: a UTF-8 encoded string diff --git a/glib/gconvertprivate.h b/glib/gconvertprivate.h new file mode 100644 index 000000000..5bdc87ff6 --- /dev/null +++ b/glib/gconvertprivate.h @@ -0,0 +1,40 @@ +/* gconvertprivate.h - Private GLib gconvert functions + * + * Copyright 2020 Frederic Martinsons + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __G_CONVERTPRIVATE_H__ +#define __G_CONVERTPRIVATE_H__ + +G_BEGIN_DECLS + +#include "glib.h" + +gchar *_g_time_locale_to_utf8 (const gchar *opsysstring, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error) G_GNUC_MALLOC; + +gchar *_g_ctype_locale_to_utf8 (const gchar *opsysstring, + gssize len, + gsize *bytes_read, + gsize *bytes_written, + GError **error) G_GNUC_MALLOC; + +G_END_DECLS + +#endif /* __G_CONVERTPRIVATE_H__ */ diff --git a/glib/gdate.c b/glib/gdate.c index 253ab6524..6b36ae718 100644 --- a/glib/gdate.c +++ b/glib/gdate.c @@ -1206,6 +1206,22 @@ g_date_prepare_to_parse (const gchar *str, g_date_fill_parse_tokens (str, pt); } +static guint +convert_twodigit_year (guint y) +{ + if (using_twodigit_years && y < 100) + { + guint two = twodigit_start_year % 100; + guint century = (twodigit_start_year / 100) * 100; + + if (y < two) + century += 100; + + y += century; + } + return y; +} + /** * g_date_set_parse: * @date: a #GDate to fill in @@ -1302,16 +1318,8 @@ g_date_set_parse (GDate *d, { y += locale_era_adjust; } - else if (using_twodigit_years && y < 100) - { - guint two = twodigit_start_year % 100; - guint century = (twodigit_start_year / 100) * 100; - - if (y < two) - century += 100; - - y += century; - } + + y = convert_twodigit_year (y); } break; default: @@ -1355,18 +1363,8 @@ g_date_set_parse (GDate *d, m = (pt.n[0]/100) % 100; day = pt.n[0] % 100; y = pt.n[0]/10000; - - /* FIXME move this into a separate function */ - if (using_twodigit_years && y < 100) - { - guint two = twodigit_start_year % 100; - guint century = (twodigit_start_year / 100) * 100; - - if (y < two) - century += 100; - - y += century; - } + + y = convert_twodigit_year (y); } } diff --git a/glib/gdatetime.c b/glib/gdatetime.c index ffdeddd81..a31afe713 100644 --- a/glib/gdatetime.c +++ b/glib/gdatetime.c @@ -60,23 +60,23 @@ #include <langinfo.h> #endif -#include "gdatetime.h" - -#include "gslice.h" #include "gatomic.h" #include "gcharset.h" +#include "gcharsetprivate.h" #include "gconvert.h" +#include "gconvertprivate.h" +#include "gdatetime.h" #include "gfileutils.h" #include "ghash.h" +#include "glibintl.h" #include "gmain.h" #include "gmappedfile.h" +#include "gslice.h" #include "gstrfuncs.h" #include "gtestutils.h" #include "gthread.h" #include "gtimezone.h" -#include "glibintl.h" - #ifndef G_OS_WIN32 #include <sys/time.h> #include <time.h> @@ -2871,7 +2871,7 @@ initialize_alt_digits (void) if (g_strcmp0 (locale_digit, "") == 0) return NULL; - digit = g_locale_to_utf8 (locale_digit, -1, NULL, &digit_len, NULL); + digit = _g_ctype_locale_to_utf8 (locale_digit, -1, NULL, &digit_len, NULL); if (digit == NULL) return NULL; @@ -2995,7 +2995,7 @@ g_date_time_format_locale (GDateTime *datetime, if (locale_is_utf8) return g_date_time_format_utf8 (datetime, locale_format, outstr, locale_is_utf8); - utf8_format = g_locale_to_utf8 (locale_format, -1, NULL, NULL, NULL); + utf8_format = _g_time_locale_to_utf8 (locale_format, -1, NULL, NULL, NULL); if (utf8_format == NULL) return FALSE; @@ -3019,7 +3019,7 @@ string_append (GString *string, } else { - utf8 = g_locale_to_utf8 (s, -1, NULL, &utf8_len, NULL); + utf8 = _g_time_locale_to_utf8 (s, -1, NULL, &utf8_len, NULL); if (utf8 == NULL) return FALSE; g_string_append_len (string, utf8, utf8_len); @@ -3445,10 +3445,11 @@ g_date_time_format (GDateTime *datetime, { GString *outstr; const gchar *charset; - /* Avoid conversions from locale charset to UTF-8 if charset is compatible + /* Avoid conversions from locale (for LC_TIME and not for LC_MESSAGES unless + * specified otherwise) charset to UTF-8 if charset is compatible * with UTF-8 already. Check for UTF-8 and synonymous canonical names of * ASCII. */ - gboolean locale_is_utf8_compatible = g_get_charset (&charset) || + gboolean time_is_utf8_compatible = _g_get_time_charset (&charset) || g_strcmp0 ("ASCII", charset) == 0 || g_strcmp0 ("ANSI_X3.4-1968", charset) == 0; @@ -3459,7 +3460,7 @@ g_date_time_format (GDateTime *datetime, outstr = g_string_sized_new (strlen (format) * 2); if (!g_date_time_format_utf8 (datetime, format, outstr, - locale_is_utf8_compatible)) + time_is_utf8_compatible)) { g_string_free (outstr, TRUE); return NULL; diff --git a/glib/gdir.c b/glib/gdir.c index c26edc1dc..b07eb5c20 100644 --- a/glib/gdir.c +++ b/glib/gdir.c @@ -60,7 +60,9 @@ struct _GDir DIR *dirp; #endif #ifdef G_OS_WIN32 - gchar utf8_buf[FILENAME_MAX*4]; + /* maximum encoding of FILENAME_MAX UTF-8 characters, plus a nul terminator + * (FILENAME_MAX is not guaranteed to include one) */ + gchar utf8_buf[FILENAME_MAX*4 + 1]; #endif }; diff --git a/glib/gerror.c b/glib/gerror.c index 82bf626ed..bd5408872 100644 --- a/glib/gerror.c +++ b/glib/gerror.c @@ -114,6 +114,12 @@ * function (the file being opened, or whatever - though in the * g_file_get_contents() case, the @message already contains a filename). * + * Since error messages may be displayed to the user, they need to be valid + * UTF-8 (all GTK widgets expect text to be UTF-8). Keep this in mind in + * particular when formatting error messages with filenames, which are in + * the 'filename encoding', and need to be turned into UTF-8 using + * g_filename_to_utf8(), g_filename_display_name() or g_utf8_make_valid(). + * * Note, however, that many error messages are too technical to display to the * user in an application, so prefer to use g_error_matches() to categorize errors * from called functions, and build an appropriate error message for the context @@ -1095,6 +1101,30 @@ g_prefix_error (GError **err, } /** + * g_prefix_error_literal: + * @err: (allow-none): a return location for a #GError, or %NULL + * @prefix: string to prefix @err with + * + * Prefixes @prefix to an existing error message. If @err or *@err is + * %NULL (i.e.: no error variable) then do nothing. + * + * Since: 2.70 + */ +void +g_prefix_error_literal (GError **err, + const gchar *prefix) +{ + if (err && *err) + { + gchar *oldstring; + + oldstring = (*err)->message; + (*err)->message = g_strconcat (prefix, oldstring, NULL); + g_free (oldstring); + } +} + +/** * g_propagate_prefixed_error: * @dest: error return location * @src: error to move into the return location diff --git a/glib/gerror.h b/glib/gerror.h index 6431d5b6c..bc9c03a91 100644 --- a/glib/gerror.h +++ b/glib/gerror.h @@ -244,6 +244,11 @@ void g_prefix_error (GError **err, const gchar *format, ...) G_GNUC_PRINTF (2, 3); +/* if (err) prefix the string to the ->message */ +GLIB_AVAILABLE_IN_2_70 +void g_prefix_error_literal (GError **err, + const gchar *prefix); + /* g_propagate_error then g_error_prefix on dest */ GLIB_AVAILABLE_IN_ALL void g_propagate_prefixed_error (GError **dest, diff --git a/glib/gfileutils.c b/glib/gfileutils.c index a4e90265e..e0a2a65d0 100644 --- a/glib/gfileutils.c +++ b/glib/gfileutils.c @@ -1208,14 +1208,6 @@ write_to_file (const gchar *contents, return TRUE; } -static inline int -steal_fd (int *fd_ptr) -{ - int fd = *fd_ptr; - *fd_ptr = -1; - return fd; -} - /** * g_file_set_contents: * @filename: (type filename): name of a file to write @contents to, in the GLib file name @@ -1369,7 +1361,7 @@ g_file_set_contents_full (const gchar *filename, } do_fsync = fd_should_be_fsynced (fd, filename, flags); - if (!write_to_file (contents, length, steal_fd (&fd), tmp_filename, do_fsync, error)) + if (!write_to_file (contents, length, g_steal_fd (&fd), tmp_filename, do_fsync, error)) { g_unlink (tmp_filename); retval = FALSE; @@ -1479,7 +1471,7 @@ consistent_out: } do_fsync = fd_should_be_fsynced (direct_fd, filename, flags); - if (!write_to_file (contents, length, steal_fd (&direct_fd), filename, + if (!write_to_file (contents, length, g_steal_fd (&direct_fd), filename, do_fsync, error)) return FALSE; } diff --git a/glib/ghash.c b/glib/ghash.c index cc2d00087..48a7db0e2 100644 --- a/glib/ghash.c +++ b/glib/ghash.c @@ -2191,7 +2191,7 @@ g_hash_table_get_keys (GHashTable *hash_table) /** * g_hash_table_get_keys_as_array: * @hash_table: a #GHashTable - * @length: (out): the length of the returned array + * @length: (out) (optional): the length of the returned array * * Retrieves every key inside @hash_table, as an array. * diff --git a/glib/glib-typeof.h b/glib/glib-typeof.h new file mode 100644 index 000000000..198901c29 --- /dev/null +++ b/glib/glib-typeof.h @@ -0,0 +1,43 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 2021 Iain Lane, Xavier Claessens + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GLIB_TYPEOF_H__ +#define __GLIB_TYPEOF_H__ + +#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION) +#error "Only <glib.h> can be included directly." +#endif + +#include <glib/gversionmacros.h> + +/* + * We can only use __typeof__ on GCC >= 4.8, and not when compiling C++. Since + * __typeof__ is used in a few places in GLib, provide a pre-processor symbol + * to factor the check out from callers. + * + * This symbol is private. + */ +#undef glib_typeof +#if !defined(__cplusplus) && (G_GNUC_CHECK_VERSION(4, 8) || defined(__clang__)) +#define glib_typeof(t) __typeof__ (t) +#elif defined(__cplusplus) && __cplusplus >= 201103L && GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68 +/* C++11 decltype() is close enough for our usage */ +#include <type_traits> +#define glib_typeof(t) typename std::remove_reference<decltype (t)>::type +#endif + +#endif /* __GLIB_TYPEOF_H__ */ diff --git a/glib/glib.h b/glib/glib.h index a4d43a9bf..e72c09da5 100644 --- a/glib/glib.h +++ b/glib/glib.h @@ -112,6 +112,7 @@ #include <glib/deprecated/gthread.h> #include <glib/glib-autocleanups.h> +#include <glib/glib-typeof.h> #undef __GLIB_H_INSIDE__ diff --git a/glib/gmacros.h b/glib/gmacros.h index 42e3c66c7..27c2c48ac 100644 --- a/glib/gmacros.h +++ b/glib/gmacros.h @@ -37,6 +37,12 @@ */ #include <stddef.h> +/* + * Note: Clang (but not clang-cl) defines __GNUC__ and __GNUC_MINOR__. + * Both Clang 11.1 on current Arch Linux and Apple's Clang 12.0 define + * __GNUC__ = 4 and __GNUC_MINOR__ = 2. So G_GNUC_CHECK_VERSION(4, 2) on + * current Clang will be 1. + */ #ifdef __GNUC__ #define G_GNUC_CHECK_VERSION(major, minor) \ ((__GNUC__ > (major)) || \ @@ -50,7 +56,7 @@ * where this is valid. This allows for warningless compilation of * "long long" types even in the presence of '-ansi -pedantic'. */ -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8) +#if G_GNUC_CHECK_VERSION(2, 8) #define G_GNUC_EXTENSION __extension__ #else #define G_GNUC_EXTENSION @@ -106,6 +112,39 @@ # define G_INLINE_FUNC static inline GLIB_DEPRECATED_MACRO_IN_2_48_FOR(static inline) #endif /* G_IMPLEMENT_INLINES */ +/* + * Attribute support detection. Works on clang and GCC >= 5 + * https://clang.llvm.org/docs/LanguageExtensions.html#has-attribute + * https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html + */ + +#ifdef __has_attribute +#define g_macro__has_attribute __has_attribute +#else + +/* + * Fallback for GCC < 5 and other compilers not supporting __has_attribute. + */ +#define g_macro__has_attribute(x) g_macro__has_attribute_##x + +#define g_macro__has_attribute___pure__ G_GNUC_CHECK_VERSION (2, 96) +#define g_macro__has_attribute___malloc__ G_GNUC_CHECK_VERSION (2, 96) +#define g_macro__has_attribute___noinline__ G_GNUC_CHECK_VERSION (2, 96) +#define g_macro__has_attribute___sentinel__ G_GNUC_CHECK_VERSION (4, 0) +#define g_macro__has_attribute___alloc_size__ G_GNUC_CHECK_VERSION (4, 3) +#define g_macro__has_attribute___format__ G_GNUC_CHECK_VERSION (2, 4) +#define g_macro__has_attribute___format_arg__ G_GNUC_CHECK_VERSION (2, 4) +#define g_macro__has_attribute___noreturn__ (G_GNUC_CHECK_VERSION (2, 8) || (0x5110 <= __SUNPRO_C)) +#define g_macro__has_attribute___const__ G_GNUC_CHECK_VERSION (2, 4) +#define g_macro__has_attribute___unused__ G_GNUC_CHECK_VERSION (2, 4) +#define g_macro__has_attribute___no_instrument_function__ G_GNUC_CHECK_VERSION (2, 4) +#define g_macro__has_attribute_fallthrough G_GNUC_CHECK_VERSION (6, 0) +#define g_macro__has_attribute___deprecated__ G_GNUC_CHECK_VERSION (3, 1) +#define g_macro__has_attribute_may_alias G_GNUC_CHECK_VERSION (3, 3) +#define g_macro__has_attribute_warn_unused_result G_GNUC_CHECK_VERSION (3, 4) + +#endif + /* Provide macros to feature the GCC function attribute. */ @@ -188,14 +227,27 @@ * * Since: 2.58 */ +/* Note: We can’t annotate this with GLIB_AVAILABLE_MACRO_IN_2_58 because it’s + * used within the GLib headers in function declarations which are always + * evaluated when a header is included. This results in warnings in third party + * code which includes glib.h, even if the third party code doesn’t use the new + * macro itself. */ -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +#if g_macro__has_attribute(__pure__) #define G_GNUC_PURE __attribute__((__pure__)) -#define G_GNUC_MALLOC __attribute__((__malloc__)) -#define G_GNUC_NO_INLINE __attribute__((noinline)) #else #define G_GNUC_PURE +#endif + +#if g_macro__has_attribute(__malloc__) +#define G_GNUC_MALLOC __attribute__ ((__malloc__)) +#else #define G_GNUC_MALLOC +#endif + +#if g_macro__has_attribute(__noinline__) +#define G_GNUC_NO_INLINE __attribute__ ((__noinline__)) +#else #define G_GNUC_NO_INLINE #endif @@ -218,37 +270,13 @@ * * Since: 2.8 */ -#if __GNUC__ >= 4 +#if g_macro__has_attribute(__sentinel__) #define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__)) #else #define G_GNUC_NULL_TERMINATED #endif /* - * We can only use __typeof__ on GCC >= 4.8, and not when compiling C++. Since - * __typeof__ is used in a few places in GLib, provide a pre-processor symbol - * to factor the check out from callers. - * - * This symbol is private. - */ -#undef glib_typeof -#if !defined(__cplusplus) && \ - ((defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || \ - defined(__clang__)) -#define glib_typeof(t) __typeof__ (t) -#elif defined(__cplusplus) && __cplusplus >= 201103L -/* C++11 decltype() is close enough for our usage */ -/* This needs `#include <type_traits>`, but we have guarded this feature with a - * `GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68` check, and such a check - * cannot be enforced in this header due to include ordering requirements. - * Within GLib itself, which use `glib_typeof` need to add the include - * themselves. See other examples in GLib for how to do this. - */ -#define glib_typeof(t) typename std::remove_reference<decltype (t)>::type -#define glib_typeof_2_68 -#endif - -/* * Clang feature detection: http://clang.llvm.org/docs/LanguageExtensions.html * These are not available on GCC, but since the pre-processor doesn't do * operator short-circuiting, we can't use it in a statement or we'll get: @@ -258,12 +286,6 @@ * So we define it to 0 to satisfy the pre-processor. */ -#ifdef __has_attribute -#define g_macro__has_attribute __has_attribute -#else -#define g_macro__has_attribute(x) 0 -#endif - #ifdef __has_feature #define g_macro__has_feature __has_feature #else @@ -276,6 +298,12 @@ #define g_macro__has_builtin(x) 0 #endif +#ifdef __has_extension +#define g_macro__has_extension __has_extension +#else +#define g_macro__has_extension(x) 0 +#endif + /** * G_GNUC_ALLOC_SIZE: * @x: the index of the argument specifying the allocation size @@ -319,8 +347,7 @@ * * Since: 2.18 */ -#if (!defined(__clang__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || \ - (defined(__clang__) && g_macro__has_attribute(__alloc_size__)) +#if g_macro__has_attribute(__alloc_size__) #define G_GNUC_ALLOC_SIZE(x) __attribute__((__alloc_size__(x))) #define G_GNUC_ALLOC_SIZE2(x,y) __attribute__((__alloc_size__(x,y))) #else @@ -506,46 +533,73 @@ * See the [GNU C documentation](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-no_005finstrument_005ffunction-function-attribute) for more details. */ -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#if g_macro__has_attribute(__format__) + #if !defined (__clang__) && G_GNUC_CHECK_VERSION (4, 4) #define G_GNUC_PRINTF( format_idx, arg_idx ) \ __attribute__((__format__ (gnu_printf, format_idx, arg_idx))) #define G_GNUC_SCANF( format_idx, arg_idx ) \ __attribute__((__format__ (gnu_scanf, format_idx, arg_idx))) #define G_GNUC_STRFTIME( format_idx ) \ - __attribute__((__format__ (gnu_strftime, format_idx, 0))) + __attribute__((__format__ (gnu_strftime, format_idx, 0))) \ + GLIB_AVAILABLE_MACRO_IN_2_60 #else #define G_GNUC_PRINTF( format_idx, arg_idx ) \ __attribute__((__format__ (__printf__, format_idx, arg_idx))) #define G_GNUC_SCANF( format_idx, arg_idx ) \ __attribute__((__format__ (__scanf__, format_idx, arg_idx))) #define G_GNUC_STRFTIME( format_idx ) \ - __attribute__((__format__ (__strftime__, format_idx, 0))) + __attribute__((__format__ (__strftime__, format_idx, 0))) \ + GLIB_AVAILABLE_MACRO_IN_2_60 #endif -#define G_GNUC_FORMAT( arg_idx ) \ - __attribute__((__format_arg__ (arg_idx))) -#define G_GNUC_NORETURN \ - __attribute__((__noreturn__)) -#define G_GNUC_CONST \ - __attribute__((__const__)) -#define G_GNUC_UNUSED \ - __attribute__((__unused__)) -#define G_GNUC_NO_INSTRUMENT \ - __attribute__((__no_instrument_function__)) -#else /* !__GNUC__ */ + +#else + #define G_GNUC_PRINTF( format_idx, arg_idx ) #define G_GNUC_SCANF( format_idx, arg_idx ) -#define G_GNUC_STRFTIME( format_idx ) +#define G_GNUC_STRFTIME( format_idx ) \ + GLIB_AVAILABLE_MACRO_IN_2_60 + +#endif + +#if g_macro__has_attribute(__format_arg__) +#define G_GNUC_FORMAT(arg_idx) \ + __attribute__ ((__format_arg__ (arg_idx))) +#else #define G_GNUC_FORMAT( arg_idx ) +#endif + +#if g_macro__has_attribute(__noreturn__) +#define G_GNUC_NORETURN \ + __attribute__ ((__noreturn__)) +#else /* NOTE: MSVC has __declspec(noreturn) but unlike GCC __attribute__, * __declspec can only be placed at the start of the function prototype * and not at the end, so we can't use it without breaking API. */ #define G_GNUC_NORETURN +#endif + +#if g_macro__has_attribute(__const__) +#define G_GNUC_CONST \ + __attribute__ ((__const__)) +#else #define G_GNUC_CONST +#endif + +#if g_macro__has_attribute(__unused__) +#define G_GNUC_UNUSED \ + __attribute__ ((__unused__)) +#else #define G_GNUC_UNUSED +#endif + +#if g_macro__has_attribute(__no_instrument_function__) +#define G_GNUC_NO_INSTRUMENT \ + __attribute__ ((__no_instrument_function__)) +#else #define G_GNUC_NO_INSTRUMENT -#endif /* !__GNUC__ */ +#endif /** * G_GNUC_FALLTHROUGH: @@ -575,13 +629,13 @@ * * Since: 2.60 */ -#if __GNUC__ > 6 -#define G_GNUC_FALLTHROUGH __attribute__((fallthrough)) -#elif g_macro__has_attribute (fallthrough) -#define G_GNUC_FALLTHROUGH __attribute__((fallthrough)) +#if g_macro__has_attribute(fallthrough) +#define G_GNUC_FALLTHROUGH __attribute__((fallthrough)) \ + GLIB_AVAILABLE_MACRO_IN_2_60 #else -#define G_GNUC_FALLTHROUGH -#endif /* __GNUC__ */ +#define G_GNUC_FALLTHROUGH \ + GLIB_AVAILABLE_MACRO_IN_2_60 +#endif /** * G_GNUC_DEPRECATED: @@ -601,7 +655,7 @@ * * Since: 2.2 */ -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || defined (__clang__) +#if g_macro__has_attribute(__deprecated__) #define G_GNUC_DEPRECATED __attribute__((__deprecated__)) #else #define G_GNUC_DEPRECATED @@ -630,11 +684,13 @@ * * Since: 2.26 */ -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) || defined (__clang__) +#if G_GNUC_CHECK_VERSION(4, 5) || defined(__clang__) #define G_GNUC_DEPRECATED_FOR(f) \ - __attribute__((deprecated("Use " #f " instead"))) + __attribute__((deprecated("Use " #f " instead"))) \ + GLIB_AVAILABLE_MACRO_IN_2_26 #else -#define G_GNUC_DEPRECATED_FOR(f) G_GNUC_DEPRECATED +#define G_GNUC_DEPRECATED_FOR(f) G_GNUC_DEPRECATED \ + GLIB_AVAILABLE_MACRO_IN_2_26 #endif /* __GNUC__ */ #ifdef __ICC @@ -643,7 +699,7 @@ _Pragma ("warning (disable:1478)") #define G_GNUC_END_IGNORE_DEPRECATIONS \ _Pragma ("warning (pop)") -#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#elif G_GNUC_CHECK_VERSION(4, 6) #define G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wdeprecated-declarations\"") @@ -677,7 +733,7 @@ * * Since: 2.14 */ -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) +#if g_macro__has_attribute(may_alias) #define G_GNUC_MAY_ALIAS __attribute__((may_alias)) #else #define G_GNUC_MAY_ALIAS @@ -701,7 +757,7 @@ * * Since: 2.10 */ -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#if g_macro__has_attribute(warn_unused_result) #define G_GNUC_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) #else #define G_GNUC_WARN_UNUSED_RESULT @@ -743,6 +799,9 @@ #if g_macro__has_feature(attribute_analyzer_noreturn) && defined(__clang_analyzer__) #define G_ANALYZER_ANALYZING 1 #define G_ANALYZER_NORETURN __attribute__((analyzer_noreturn)) +#elif defined(__COVERITY__) +#define G_ANALYZER_ANALYZING 1 +#define G_ANALYZER_NORETURN __attribute__((noreturn)) #else #define G_ANALYZER_ANALYZING 0 #define G_ANALYZER_NORETURN @@ -754,7 +813,8 @@ #ifndef __GI_SCANNER__ /* The static assert macro really confuses the introspection parser */ #define G_PASTE_ARGS(identifier1,identifier2) identifier1 ## identifier2 #define G_PASTE(identifier1,identifier2) G_PASTE_ARGS (identifier1, identifier2) -#if !defined(__cplusplus) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#if !defined(__cplusplus) && defined(__STDC_VERSION__) && \ + (__STDC_VERSION__ >= 201112L || g_macro__has_feature(c_static_assert) || g_macro__has_extension(c_static_assert)) #define G_STATIC_ASSERT(expr) _Static_assert (expr, "Expression evaluates to false") #elif (defined(__cplusplus) && __cplusplus >= 201103L) || \ (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \ @@ -848,7 +908,7 @@ * fields through their offsets. */ -#if (defined(__GNUC__) && __GNUC__ >= 4) || defined (_MSC_VER) +#if G_GNUC_CHECK_VERSION(4, 0) || defined(_MSC_VER) #define G_STRUCT_OFFSET(struct_type, member) \ ((glong) offsetof (struct_type, member)) #else @@ -907,9 +967,11 @@ * Since: 2.60 */ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__cplusplus) -#define G_ALIGNOF(type) _Alignof (type) +#define G_ALIGNOF(type) _Alignof (type) \ + GLIB_AVAILABLE_MACRO_IN_2_60 #else -#define G_ALIGNOF(type) (G_STRUCT_OFFSET (struct { char a; type b; }, b)) +#define G_ALIGNOF(type) (G_STRUCT_OFFSET (struct { char a; type b; }, b)) \ + GLIB_AVAILABLE_MACRO_IN_2_60 #endif /** @@ -956,7 +1018,7 @@ * evaluated when a header is included. This results in warnings in third party * code which includes glib.h, even if the third party code doesn’t use the new * macro itself. */ -#if (3 <= __GNUC__ || (__GNUC__ == 2 && 8 <= __GNUC_MINOR__)) || (0x5110 <= __SUNPRO_C) +#if g_macro__has_attribute(__noreturn__) /* For compatibility with G_NORETURN_FUNCPTR on clang, use __attribute__((__noreturn__)), not _Noreturn. */ # define G_NORETURN __attribute__ ((__noreturn__)) @@ -964,10 +1026,10 @@ /* Use MSVC specific syntax. */ # define G_NORETURN __declspec (noreturn) /* Use ISO C++11 syntax when the compiler supports it. */ -#elif (defined (__cplusplus) && __cplusplus >= 201103 && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) || defined (_MSC_VER) && (_MSC_VER >= 1900) +#elif defined (__cplusplus) && __cplusplus >= 201103 # define G_NORETURN [[noreturn]] /* Use ISO C11 syntax when the compiler supports it. */ -#elif (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112 # define G_NORETURN _Noreturn #else # define G_NORETURN /* empty */ @@ -995,7 +1057,7 @@ * * Since: 2.68 */ -#if (3 <= __GNUC__ || (__GNUC__ == 2 && 8 <= __GNUC_MINOR__)) || (0x5110 <= __SUNPRO_C) +#if g_macro__has_attribute(__noreturn__) # define G_NORETURN_FUNCPTR __attribute__ ((__noreturn__)) \ GLIB_AVAILABLE_MACRO_IN_2_68 #else @@ -1011,7 +1073,7 @@ * The _G_BOOLEAN_EXPR macro is intended to trigger a gcc warning when * putting assignments in g_return_if_fail (). */ -#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +#if G_GNUC_CHECK_VERSION(2, 0) && defined(__OPTIMIZE__) #define _G_BOOLEAN_EXPR(expr) \ G_GNUC_EXTENSION ({ \ int _g_boolean_var_; \ @@ -1028,7 +1090,7 @@ #define G_UNLIKELY(expr) (expr) #endif -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || defined (__clang__) +#if G_GNUC_CHECK_VERSION(3, 1) || defined(__clang__) #define G_DEPRECATED __attribute__((__deprecated__)) #elif defined(_MSC_VER) && (_MSC_VER >= 1300) #define G_DEPRECATED __declspec(deprecated) @@ -1036,7 +1098,7 @@ #define G_DEPRECATED #endif -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) || defined (__clang__) +#if G_GNUC_CHECK_VERSION(4, 5) || defined(__clang__) #define G_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead"))) #elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320) #define G_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead")) @@ -1044,7 +1106,7 @@ #define G_DEPRECATED_FOR(f) G_DEPRECATED #endif -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) || defined (__clang__) +#if G_GNUC_CHECK_VERSION(4, 5) || defined(__clang__) #define G_UNAVAILABLE(maj,min) __attribute__((deprecated("Not available before " #maj "." #min))) #elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320) #define G_UNAVAILABLE(maj,min) __declspec(deprecated("is not available before " #maj "." #min)) @@ -1075,12 +1137,14 @@ #endif #if !defined(GLIB_DISABLE_DEPRECATION_WARNINGS) && \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || \ + (G_GNUC_CHECK_VERSION(4, 6) || \ __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 4)) #define _GLIB_GNUC_DO_PRAGMA(x) _Pragma(G_STRINGIFY (x)) #define GLIB_DEPRECATED_MACRO _GLIB_GNUC_DO_PRAGMA(GCC warning "Deprecated pre-processor symbol") -#define GLIB_DEPRECATED_MACRO_FOR(f) _GLIB_GNUC_DO_PRAGMA(GCC warning "Deprecated pre-processor symbol, replace with " #f) -#define GLIB_UNAVAILABLE_MACRO(maj,min) _GLIB_GNUC_DO_PRAGMA(GCC warning "Not available before " #maj "." #min) +#define GLIB_DEPRECATED_MACRO_FOR(f) \ + _GLIB_GNUC_DO_PRAGMA(GCC warning G_STRINGIFY (Deprecated pre-processor symbol: replace with #f)) +#define GLIB_UNAVAILABLE_MACRO(maj,min) \ + _GLIB_GNUC_DO_PRAGMA(GCC warning G_STRINGIFY (Not available before maj.min)) #else #define GLIB_DEPRECATED_MACRO #define GLIB_DEPRECATED_MACRO_FOR(f) @@ -1088,7 +1152,7 @@ #endif #if !defined(GLIB_DISABLE_DEPRECATION_WARNINGS) && \ - ((defined (__GNUC__) && (__GNUC__ > 6 || (__GNUC__ == 6 && __GNUC_MINOR__ >= 1))) || \ + (G_GNUC_CHECK_VERSION(6, 1) || \ (defined (__clang_major__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 0)))) #define GLIB_DEPRECATED_ENUMERATOR G_DEPRECATED #define GLIB_DEPRECATED_ENUMERATOR_FOR(f) G_DEPRECATED_FOR(f) @@ -1100,7 +1164,7 @@ #endif #if !defined(GLIB_DISABLE_DEPRECATION_WARNINGS) && \ - ((defined (__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) || \ + (G_GNUC_CHECK_VERSION(3, 1) || \ (defined (__clang_major__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 0)))) #define GLIB_DEPRECATED_TYPE G_DEPRECATED #define GLIB_DEPRECATED_TYPE_FOR(f) G_DEPRECATED_FOR(f) diff --git a/glib/gmain.c b/glib/gmain.c index 15581ee7a..4efa9ad6f 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -1370,6 +1370,10 @@ g_source_destroy_internal (GSource *source, * * This function is safe to call from any thread, regardless of which thread * the #GMainContext is running in. + * + * If the source is currently attached to a #GMainContext, destroying it + * will effectively unset the callback similar to calling g_source_set_callback(). + * This can mean, that the data's #GDestroyNotify gets called right away. */ void g_source_destroy (GSource *source) @@ -1761,6 +1765,9 @@ g_source_set_callback_indirect (GSource *source, * It is safe to call this function multiple times on a source which has already * been attached to a context. The changes will take effect for the next time * the source is dispatched after this call returns. + * + * Note that g_source_destroy() for a currently attached source has the effect + * of also unsetting the callback. **/ void g_source_set_callback (GSource *source, @@ -5723,7 +5730,7 @@ g_child_watch_source_new (GPid pid) * you will need to pass #G_SPAWN_DO_NOT_REAP_CHILD as flag to * the spawn function for the child watching to work. * - * In many programs, you will want to call g_spawn_check_exit_status() + * In many programs, you will want to call g_spawn_check_wait_status() * in the callback to determine whether or not the child exited * successfully. * @@ -6122,3 +6129,23 @@ g_get_worker_context (void) return glib_worker_context; } + +/** + * g_steal_fd: + * @fd_ptr: (not optional) (inout): A pointer to a file descriptor + * + * Sets @fd_ptr to `-1`, returning the value that was there before. + * + * Conceptually, this transfers the ownership of the file descriptor + * from the referenced variable to the caller of the function (i.e. + * ‘steals’ the reference). This is very similar to g_steal_pointer(), + * but for file descriptors. + * + * On POSIX platforms, this function is async-signal safe + * (see [`signal(7)`](man:signal(7)) and + * [`signal-safety(7)`](man:signal-safety(7))), making it safe to call from a + * signal handler or a #GSpawnChildSetupFunc. + * + * Returns: the value that @fd_ptr previously had + * Since: 2.70 + */ diff --git a/glib/gmain.h b/glib/gmain.h index 5c0e524cc..8428e01a4 100644 --- a/glib/gmain.h +++ b/glib/gmain.h @@ -193,16 +193,20 @@ typedef gboolean (*GSourceFunc) (gpointer user_data); /** * GChildWatchFunc: * @pid: the process id of the child process - * @status: Status information about the child process, encoded - * in a platform-specific manner + * @wait_status: Status information about the child process, encoded + * in a platform-specific manner * @user_data: user data passed to g_child_watch_add() * * Prototype of a #GChildWatchSource callback, called when a child - * process has exited. To interpret @status, see the documentation - * for g_spawn_check_exit_status(). + * process has exited. + * + * To interpret @wait_status, see the documentation + * for g_spawn_check_wait_status(). In particular, + * on Unix platforms, note that it is usually not equal + * to the integer passed to `exit()` or returned from `main()`. */ typedef void (*GChildWatchFunc) (GPid pid, - gint status, + gint wait_status, gpointer user_data); @@ -264,8 +268,8 @@ typedef void (*GSourceDummyMarshal) (void); struct _GSourceFuncs { gboolean (*prepare) (GSource *source, - gint *timeout_); - gboolean (*check) (GSource *source); + gint *timeout_);/* Can be NULL */ + gboolean (*check) (GSource *source);/* Can be NULL */ gboolean (*dispatch) (GSource *source, GSourceFunc callback, gpointer user_data); @@ -781,6 +785,15 @@ void g_main_context_invoke (GMainContext *context, GSourceFunc function, gpointer data); +GLIB_AVAILABLE_STATIC_INLINE_IN_2_70 +static inline int +g_steal_fd (int *fd_ptr) +{ + int fd = *fd_ptr; + *fd_ptr = -1; + return fd; +} + /* Hook for GClosure / GSource integration. Don't touch */ GLIB_VAR GSourceFuncs g_timeout_funcs; GLIB_VAR GSourceFuncs g_child_watch_funcs; diff --git a/glib/gmem.h b/glib/gmem.h index ccf477843..47c4735ac 100644 --- a/glib/gmem.h +++ b/glib/gmem.h @@ -30,11 +30,7 @@ #endif #include <glib/gutils.h> - -#if defined(glib_typeof_2_68) && GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68 -/* for glib_typeof */ -#include <type_traits> -#endif +#include <glib/glib-typeof.h> G_BEGIN_DECLS @@ -115,7 +111,7 @@ gpointer g_try_realloc_n (gpointer mem, gsize n_blocks, gsize n_block_bytes) G_GNUC_WARN_UNUSED_RESULT; -#if defined(glib_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_58 && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) +#if defined(glib_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_58 #define g_clear_pointer(pp, destroy) \ G_STMT_START \ { \ @@ -218,7 +214,7 @@ g_steal_pointer (gpointer pp) } /* type safety */ -#if defined(glib_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_58 && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) +#if defined(glib_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_58 #define g_steal_pointer(pp) ((glib_typeof (*pp)) (g_steal_pointer) (pp)) #else /* __GNUC__ */ /* This version does not depend on gcc extensions, but gcc does not warn diff --git a/glib/goption.c b/glib/goption.c index a351f84cb..8cb72376c 100644 --- a/glib/goption.c +++ b/glib/goption.c @@ -102,7 +102,7 @@ * { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL }, * { "beep", 'b', 0, G_OPTION_ARG_NONE, &beep, "Beep when done", NULL }, * { "rand", 0, 0, G_OPTION_ARG_NONE, &randomize, "Randomize the data", NULL }, - * { NULL } + * G_OPTION_ENTRY_NULL * }; * * int @@ -1543,23 +1543,14 @@ parse_short_option (GOptionContext *context, if (idx < *argc - 1) { - if (!OPTIONAL_ARG (&group->entries[j])) + if (OPTIONAL_ARG (&group->entries[j]) && ((*argv)[idx + 1][0] == '-')) + value = NULL; + else { value = (*argv)[idx + 1]; add_pending_null (context, &((*argv)[idx + 1]), NULL); *new_idx = idx + 1; } - else - { - if ((*argv)[idx + 1][0] == '-') - value = NULL; - else - { - value = (*argv)[idx + 1]; - add_pending_null (context, &((*argv)[idx + 1]), NULL); - *new_idx = idx + 1; - } - } } else if (idx >= *argc - 1 && OPTIONAL_ARG (&group->entries[j])) value = NULL; diff --git a/glib/goption.h b/glib/goption.h index 63552fb0d..44815a77d 100644 --- a/glib/goption.h +++ b/glib/goption.h @@ -286,6 +286,24 @@ struct _GOptionEntry */ #define G_OPTION_REMAINING "" +/** + * G_OPTION_ENTRY_NULL: + * + * A #GOptionEntry array requires a %NULL terminator, this macro can + * be used as terminator instead of an explicit `{ 0 }` but it cannot + * be assigned to a variable. + * + * |[ + * GOptionEntry option[] = { G_OPTION_ENTRY_NULL }; + * ]| + * + * Since: 2.70 + */ +#define G_OPTION_ENTRY_NULL \ + GLIB_AVAILABLE_MACRO_IN_2_70 \ + { NULL, 0, 0, 0, NULL, NULL, NULL } + + GLIB_AVAILABLE_IN_ALL GOptionContext *g_option_context_new (const gchar *parameter_string); GLIB_AVAILABLE_IN_ALL diff --git a/glib/gpattern.c b/glib/gpattern.c index 16a0bf5f7..8725f509f 100644 --- a/glib/gpattern.c +++ b/glib/gpattern.c @@ -22,10 +22,11 @@ #include "gpattern.h" #include "gmacros.h" -#include "gmessages.h" #include "gmem.h" +#include "gmessages.h" +#include "gstrfuncs.h" #include "gunicode.h" -#include "gutils.h" +#include "gutils.h" /** * SECTION:patterns @@ -157,7 +158,7 @@ g_pattern_ph_match (const gchar *match_pattern, } /** - * g_pattern_match: + * g_pattern_spec_match: * @pspec: a #GPatternSpec * @string_length: the length of @string (in bytes, i.e. strlen(), * not g_utf8_strlen()) @@ -183,12 +184,14 @@ g_pattern_ph_match (const gchar *match_pattern, * g_utf8_strreverse() function to reverse UTF-8 encoded strings. * * Returns: %TRUE if @string matches @pspec + * + * Since: 2.70 **/ gboolean -g_pattern_match (GPatternSpec *pspec, - guint string_length, - const gchar *string, - const gchar *string_reversed) +g_pattern_spec_match (GPatternSpec *pspec, + gsize string_length, + const gchar *string, + const gchar *string_reversed) { g_return_val_if_fail (pspec != NULL, FALSE); g_return_val_if_fail (string != NULL, FALSE); @@ -238,6 +241,44 @@ g_pattern_match (GPatternSpec *pspec, } /** + * g_pattern_match: (skip) + * @pspec: a #GPatternSpec + * @string_length: the length of @string (in bytes, i.e. strlen(), + * not g_utf8_strlen()) + * @string: the UTF-8 encoded string to match + * @string_reversed: (nullable): the reverse of @string or %NULL + * + * Matches a string against a compiled pattern. Passing the correct + * length of the string given is mandatory. The reversed string can be + * omitted by passing %NULL, this is more efficient if the reversed + * version of the string to be matched is not at hand, as + * g_pattern_match() will only construct it if the compiled pattern + * requires reverse matches. + * + * Note that, if the user code will (possibly) match a string against a + * multitude of patterns containing wildcards, chances are high that + * some patterns will require a reversed string. In this case, it's + * more efficient to provide the reversed string to avoid multiple + * constructions thereof in the various calls to g_pattern_match(). + * + * Note also that the reverse of a UTF-8 encoded string can in general + * not be obtained by g_strreverse(). This works only if the string + * does not contain any multibyte characters. GLib offers the + * g_utf8_strreverse() function to reverse UTF-8 encoded strings. + * + * Returns: %TRUE if @string matches @pspec + * Deprecated: 2.70: Use g_pattern_spec_match() instead + **/ +gboolean +g_pattern_match (GPatternSpec *pspec, + guint string_length, + const gchar *string, + const gchar *string_reversed) +{ + return g_pattern_spec_match (pspec, string_length, string, string_reversed); +} + +/** * g_pattern_spec_new: * @pattern: a zero-terminated UTF-8 encoded string * @@ -354,6 +395,30 @@ g_pattern_spec_new (const gchar *pattern) } /** + * g_pattern_spec_copy: + * @pspec: a #GPatternSpec + * + * Copies @pspec in a new #GPatternSpec. + * + * Returns: (transfer full): a copy of @pspec. + * + * Since: 2.70 + **/ +GPatternSpec * +g_pattern_spec_copy (GPatternSpec *pspec) +{ + GPatternSpec *pspec_copy; + + g_return_val_if_fail (pspec != NULL, NULL); + + pspec_copy = g_new (GPatternSpec, 1); + *pspec_copy = *pspec; + pspec_copy->pattern = g_strndup (pspec->pattern, pspec->pattern_length); + + return pspec_copy; +} + +/** * g_pattern_spec_free: * @pspec: a #GPatternSpec * @@ -391,7 +456,7 @@ g_pattern_spec_equal (GPatternSpec *pspec1, } /** - * g_pattern_match_string: + * g_pattern_spec_match_string: * @pspec: a #GPatternSpec * @string: the UTF-8 encoded string to match * @@ -400,15 +465,36 @@ g_pattern_spec_equal (GPatternSpec *pspec1, * g_pattern_match() instead while supplying the reversed string. * * Returns: %TRUE if @string matches @pspec + * + * Since: 2.70 **/ gboolean -g_pattern_match_string (GPatternSpec *pspec, - const gchar *string) +g_pattern_spec_match_string (GPatternSpec *pspec, + const gchar *string) { g_return_val_if_fail (pspec != NULL, FALSE); g_return_val_if_fail (string != NULL, FALSE); - return g_pattern_match (pspec, strlen (string), string, NULL); + return g_pattern_spec_match (pspec, strlen (string), string, NULL); +} + +/** + * g_pattern_match_string: (skip) + * @pspec: a #GPatternSpec + * @string: the UTF-8 encoded string to match + * + * Matches a string against a compiled pattern. If the string is to be + * matched against more than one pattern, consider using + * g_pattern_match() instead while supplying the reversed string. + * + * Returns: %TRUE if @string matches @pspec + * Deprecated: 2.70: Use g_pattern_spec_match_string() instead + **/ +gboolean +g_pattern_match_string (GPatternSpec *pspec, + const gchar *string) +{ + return g_pattern_spec_match_string (pspec, string); } /** @@ -434,7 +520,7 @@ g_pattern_match_simple (const gchar *pattern, g_return_val_if_fail (string != NULL, FALSE); pspec = g_pattern_spec_new (pattern); - ergo = g_pattern_match (pspec, strlen (string), string, NULL); + ergo = g_pattern_spec_match (pspec, strlen (string), string, NULL); g_pattern_spec_free (pspec); return ergo; diff --git a/glib/gpattern.h b/glib/gpattern.h index bd9e4a7af..2d7f83077 100644 --- a/glib/gpattern.h +++ b/glib/gpattern.h @@ -33,15 +33,25 @@ GLIB_AVAILABLE_IN_ALL GPatternSpec* g_pattern_spec_new (const gchar *pattern); GLIB_AVAILABLE_IN_ALL void g_pattern_spec_free (GPatternSpec *pspec); +GLIB_AVAILABLE_IN_2_70 +GPatternSpec *g_pattern_spec_copy (GPatternSpec *pspec); GLIB_AVAILABLE_IN_ALL gboolean g_pattern_spec_equal (GPatternSpec *pspec1, GPatternSpec *pspec2); -GLIB_AVAILABLE_IN_ALL +GLIB_AVAILABLE_IN_2_70 +gboolean g_pattern_spec_match (GPatternSpec *pspec, + gsize string_length, + const gchar *string, + const gchar *string_reversed); +GLIB_AVAILABLE_IN_2_70 +gboolean g_pattern_spec_match_string (GPatternSpec *pspec, + const gchar *string); +GLIB_DEPRECATED_IN_2_70_FOR (g_pattern_spec_match) gboolean g_pattern_match (GPatternSpec *pspec, guint string_length, const gchar *string, const gchar *string_reversed); -GLIB_AVAILABLE_IN_ALL +GLIB_DEPRECATED_IN_2_70_FOR (g_pattern_spec_match_string) gboolean g_pattern_match_string (GPatternSpec *pspec, const gchar *string); GLIB_AVAILABLE_IN_ALL diff --git a/glib/grcbox.h b/glib/grcbox.h index 47dfd488b..0f8b99a80 100644 --- a/glib/grcbox.h +++ b/glib/grcbox.h @@ -23,11 +23,7 @@ #endif #include <glib/gmem.h> - -#if defined(glib_typeof_2_68) && GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68 -/* for glib_typeof */ -#include <type_traits> -#endif +#include <glib/glib-typeof.h> G_BEGIN_DECLS @@ -76,7 +72,7 @@ gsize g_atomic_rc_box_get_size (gpointer mem_block); #define g_atomic_rc_box_new0(type) \ ((type *) g_atomic_rc_box_alloc0 (sizeof (type))) -#if defined(glib_typeof) && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) +#if defined(glib_typeof) /* Type check to avoid assigning references to different types */ #define g_rc_box_acquire(mem_block) \ ((glib_typeof (mem_block)) (g_rc_box_acquire) (mem_block)) diff --git a/glib/grefcount.c b/glib/grefcount.c index 7cb12fc46..6826a0005 100644 --- a/glib/grefcount.c +++ b/glib/grefcount.c @@ -84,7 +84,7 @@ * g_ref_count_init: * @rc: the address of a reference count variable * - * Initializes a reference count variable. + * Initializes a reference count variable to 1. * * Since: 2.58 */ @@ -142,6 +142,10 @@ void * * Decreases the reference count. * + * If %TRUE is returned, the reference count reached 0. After this point, @rc + * is an undefined state and must be reinitialized with + * g_ref_count_init() to be used again. + * * Returns: %TRUE if the reference count reached 0, and %FALSE otherwise * * Since: 2.58 @@ -199,7 +203,7 @@ gboolean * g_atomic_ref_count_init: * @arc: the address of an atomic reference count variable * - * Initializes a reference count variable. + * Initializes a reference count variable to 1. * * Since: 2.58 */ @@ -231,16 +235,14 @@ void void (g_atomic_ref_count_inc) (gatomicrefcount *arc) { - g_return_if_fail (arc != NULL); - g_return_if_fail (g_atomic_int_get (arc) > 0); + gint old_value; - if (g_atomic_int_get (arc) == G_MAXINT) - { - g_critical ("Reference count has reached saturation"); - return; - } + g_return_if_fail (arc != NULL); + old_value = g_atomic_int_add (arc, 1); + g_return_if_fail (old_value > 0); - g_atomic_int_inc (arc); + if (old_value == G_MAXINT) + g_critical ("Reference count has reached saturation"); } /** @@ -249,6 +251,10 @@ void * * Atomically decreases the reference count. * + * If %TRUE is returned, the reference count reached 0. After this point, @arc + * is an undefined state and must be reinitialized with + * g_atomic_ref_count_init() to be used again. + * * Returns: %TRUE if the reference count reached 0, and %FALSE otherwise * * Since: 2.58 @@ -256,10 +262,13 @@ void gboolean (g_atomic_ref_count_dec) (gatomicrefcount *arc) { + gint old_value; + g_return_val_if_fail (arc != NULL, FALSE); - g_return_val_if_fail (g_atomic_int_get (arc) > 0, FALSE); + old_value = g_atomic_int_add (arc, -1); + g_return_val_if_fail (old_value > 0, FALSE); - return g_atomic_int_dec_and_test (arc); + return old_value == 1; } /** diff --git a/glib/gregex.c b/glib/gregex.c index 5e6ddfb46..a8a35a424 100644 --- a/glib/gregex.c +++ b/glib/gregex.c @@ -22,11 +22,7 @@ #include <string.h> -#ifdef USE_SYSTEM_PCRE #include <pcre.h> -#else -#include "pcre/pcre.h" -#endif #include "gtypes.h" #include "gregex.h" @@ -35,6 +31,7 @@ #include "gmessages.h" #include "gstrfuncs.h" #include "gatomic.h" +#include "gtestutils.h" #include "gthread.h" /** @@ -206,7 +203,8 @@ struct _GMatchInfo gint ref_count; /* the ref count (atomic) */ GRegex *regex; /* the regex */ GRegexMatchFlags match_opts; /* options used at match time on the regex */ - gint matches; /* number of matching sub patterns */ + gint matches; /* number of matching sub patterns, guaranteed to be <= (n_subpatterns + 1) if doing a single match (rather than matching all) */ + gint n_subpatterns; /* total number of sub patterns in the regex */ gint pos; /* position in the string where last match left off */ gint n_offsets; /* number of offsets */ gint *offsets; /* array of offsets paired 0,1 ; 2,3 ; 3,4 etc */ @@ -574,6 +572,9 @@ match_info_new (const GRegex *regex, match_info->pos = start_position; match_info->match_opts = match_options; + pcre_fullinfo (regex->pcre_re, regex->extra, + PCRE_INFO_CAPTURECOUNT, &match_info->n_subpatterns); + if (is_dfa) { /* These values should be enough for most cases, if they are not @@ -584,10 +585,7 @@ match_info_new (const GRegex *regex, } else { - gint capture_count; - pcre_fullinfo (regex->pcre_re, regex->extra, - PCRE_INFO_CAPTURECOUNT, &capture_count); - match_info->n_offsets = (capture_count + 1) * 3; + match_info->n_offsets = (match_info->n_subpatterns + 1) * 3; } match_info->offsets = g_new0 (gint, match_info->n_offsets); @@ -768,6 +766,8 @@ g_match_info_next (GMatchInfo *match_info, match_info->pos = match_info->offsets[1]; } + g_assert (match_info->matches <= match_info->n_subpatterns + 1); + /* it's possible to get two identical matches when we are matching * empty strings, for instance if the pattern is "(?=[A-Z0-9])" and * the string is "RegExTest" we have: @@ -1044,16 +1044,21 @@ g_match_info_fetch_pos (const GMatchInfo *match_info, g_return_val_if_fail (match_info != NULL, FALSE); g_return_val_if_fail (match_num >= 0, FALSE); + /* check whether there was an error */ + if (match_info->matches < 0) + return FALSE; + /* make sure the sub expression number they're requesting is less than - * the total number of sub expressions that were matched. */ - if (match_num >= match_info->matches) + * the total number of sub expressions in the regex. When matching all + * (g_regex_match_all()), also compare against the number of matches */ + if (match_num >= MAX (match_info->n_subpatterns + 1, match_info->matches)) return FALSE; if (start_pos != NULL) - *start_pos = match_info->offsets[2 * match_num]; + *start_pos = (match_num < match_info->matches) ? match_info->offsets[2 * match_num] : -1; if (end_pos != NULL) - *end_pos = match_info->offsets[2 * match_num + 1]; + *end_pos = (match_num < match_info->matches) ? match_info->offsets[2 * match_num + 1] : -1; return TRUE; } @@ -1989,6 +1994,9 @@ g_regex_match_all_full (const GRegex *regex, pcre_free (pcre_re); #endif + /* don’t assert that (info->matches <= info->n_subpatterns + 1) as that only + * holds true for a single match, rather than matching all */ + /* set info->pos to -1 so that a call to g_match_info_next() fails. */ info->pos = -1; retval = info->matches >= 0; diff --git a/glib/gscanner.c b/glib/gscanner.c index c858abf9e..9102b3a92 100644 --- a/glib/gscanner.c +++ b/glib/gscanner.c @@ -1678,7 +1678,7 @@ g_scanner_get_token_i (GScanner *scanner, case G_TOKEN_SYMBOL: if (scanner->config->symbol_2_token) - *token_p = (GTokenType) value_p->v_symbol; + *token_p = (GTokenType) ((size_t) value_p->v_symbol); break; case G_TOKEN_BINARY: diff --git a/glib/gspawn-win32.c b/glib/gspawn-win32.c index 0f6579eab..638bac5cd 100644 --- a/glib/gspawn-win32.c +++ b/glib/gspawn-win32.c @@ -531,6 +531,28 @@ do_spawn_directly (gint *exit_status, } static gboolean +might_be_console_process (void) +{ + // we should always fail to attach ourself to a console (because we're + // either already attached, or we do not have a console) + gboolean attached_to_self = AttachConsole (GetCurrentProcessId ()); + g_return_val_if_fail (!attached_to_self, TRUE); + + switch (GetLastError ()) + { + // current process is already attached to a console + case ERROR_ACCESS_DENIED: + return TRUE; + // current process does not have a console + case ERROR_INVALID_HANDLE: + return FALSE; + // we should not get ERROR_INVALID_PARAMETER + } + + g_return_val_if_reached (FALSE); +} + +static gboolean fork_exec (gint *exit_status, gboolean do_return_handle, const gchar *working_directory, @@ -625,7 +647,7 @@ fork_exec (gint *exit_status, goto cleanup_and_fail; new_argv = g_new (char *, argc + 1 + ARG_COUNT); - if (GetConsoleWindow () != NULL) + if (might_be_console_process ()) helper_process = HELPER_PROCESS "-console.exe"; else helper_process = HELPER_PROCESS ".exe"; @@ -927,7 +949,7 @@ g_spawn_sync (const gchar *working_directory, gpointer user_data, gchar **standard_output, gchar **standard_error, - gint *exit_status, + gint *wait_status, GError **error) { gint outpipe = -1; @@ -1102,8 +1124,8 @@ g_spawn_sync (const gchar *working_directory, /* No helper process, exit status of actual spawned process * already available. */ - if (exit_status) - *exit_status = status; + if (wait_status) + *wait_status = status; } else { @@ -1119,8 +1141,8 @@ g_spawn_sync (const gchar *working_directory, switch (helper_report[0]) { case CHILD_NO_ERROR: - if (exit_status) - *exit_status = helper_report[1]; + if (wait_status) + *wait_status = helper_report[1]; break; default: set_child_error (helper_report, working_directory, error); @@ -1310,7 +1332,7 @@ gboolean g_spawn_command_line_sync (const gchar *command_line, gchar **standard_output, gchar **standard_error, - gint *exit_status, + gint *wait_status, GError **error) { gboolean retval; @@ -1331,7 +1353,7 @@ g_spawn_command_line_sync (const gchar *command_line, NULL, standard_output, standard_error, - exit_status, + wait_status, error); g_strfreev (argv); @@ -1372,16 +1394,18 @@ g_spawn_close_pid (GPid pid) } gboolean -g_spawn_check_exit_status (gint exit_status, +g_spawn_check_wait_status (gint wait_status, GError **error) { gboolean ret = FALSE; - if (exit_status != 0) + if (wait_status != 0) { - g_set_error (error, G_SPAWN_EXIT_ERROR, exit_status, + /* On Windows, the wait status is just the exit status: the + * difference between the two that exists on Unix is not relevant */ + g_set_error (error, G_SPAWN_EXIT_ERROR, wait_status, _("Child process exited with code %ld"), - (long) exit_status); + (long) wait_status); goto out; } @@ -1390,6 +1414,13 @@ g_spawn_check_exit_status (gint exit_status, return ret; } +gboolean +g_spawn_check_exit_status (gint wait_status, + GError **error) +{ + return g_spawn_check_wait_status (wait_status, error); +} + #ifdef G_OS_WIN32 /* Binary compatibility versions. Not for newly compiled code. */ @@ -1421,12 +1452,12 @@ _GLIB_EXTERN gboolean g_spawn_sync_utf8 (const gchar *wo gpointer user_data, gchar **standard_output, gchar **standard_error, - gint *exit_status, + gint *wait_status, GError **error); _GLIB_EXTERN gboolean g_spawn_command_line_sync_utf8 (const gchar *command_line, gchar **standard_output, gchar **standard_error, - gint *exit_status, + gint *wait_status, GError **error); _GLIB_EXTERN gboolean g_spawn_command_line_async_utf8 (const gchar *command_line, GError **error); @@ -1486,7 +1517,7 @@ g_spawn_sync_utf8 (const gchar *working_directory, gpointer user_data, gchar **standard_output, gchar **standard_error, - gint *exit_status, + gint *wait_status, GError **error) { return g_spawn_sync (working_directory, @@ -1497,7 +1528,7 @@ g_spawn_sync_utf8 (const gchar *working_directory, user_data, standard_output, standard_error, - exit_status, + wait_status, error); } @@ -1505,13 +1536,13 @@ gboolean g_spawn_command_line_sync_utf8 (const gchar *command_line, gchar **standard_output, gchar **standard_error, - gint *exit_status, + gint *wait_status, GError **error) { return g_spawn_command_line_sync (command_line, standard_output, standard_error, - exit_status, + wait_status, error); } diff --git a/glib/gspawn.c b/glib/gspawn.c index a15fb1ca1..899647c2f 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -141,7 +141,7 @@ extern char **environ; * gpointer user_data) * { * g_message ("Child %" G_PID_FORMAT " exited %s", pid, - * g_spawn_check_exit_status (status, NULL) ? "normally" : "abnormally"); + * g_spawn_check_wait_status (status, NULL) ? "normally" : "abnormally"); * * // Free any resources associated with the child here, such as I/O channels * // on its stdout and stderr FDs. If you have no code to put in the @@ -249,16 +249,6 @@ g_spawn_async (const gchar *working_directory, error); } -/* This function is called between fork() and exec() and hence must be - * async-signal-safe (see signal-safety(7)). */ -static gint -steal_fd (gint *fd) -{ - gint fd_out = *fd; - *fd = -1; - return fd_out; -} - /* Avoids a danger in threaded situations (calling close() * on a file descriptor twice, and another thread has * re-opened it since the first close) @@ -335,7 +325,7 @@ read_data (GString *str, * @user_data: (closure): user data for @child_setup * @standard_output: (out) (array zero-terminated=1) (element-type guint8) (optional): return location for child output, or %NULL * @standard_error: (out) (array zero-terminated=1) (element-type guint8) (optional): return location for child error messages, or %NULL - * @exit_status: (out) (optional): return location for child exit status, as returned by waitpid(), or %NULL + * @wait_status: (out) (optional): return location for child wait status, as returned by waitpid(), or %NULL * @error: return location for error, or %NULL * * Executes a child synchronously (waits for the child to exit before returning). @@ -344,15 +334,18 @@ read_data (GString *str, * %G_SPAWN_STDOUT_TO_DEV_NULL and %G_SPAWN_STDERR_TO_DEV_NULL flags when * passing %NULL for @standard_output and @standard_error. * - * If @exit_status is non-%NULL, the platform-specific exit status of + * If @wait_status is non-%NULL, the platform-specific status of * the child is stored there; see the documentation of - * g_spawn_check_exit_status() for how to use and interpret this. + * g_spawn_check_wait_status() for how to use and interpret this. + * On Unix platforms, note that it is usually not equal + * to the integer passed to `exit()` or returned from `main()`. + * * Note that it is invalid to pass %G_SPAWN_DO_NOT_REAP_CHILD in * @flags, and on POSIX platforms, the same restrictions as for * g_child_watch_source_new() apply. * * If an error occurs, no data is returned in @standard_output, - * @standard_error, or @exit_status. + * @standard_error, or @wait_status. * * This function calls g_spawn_async_with_pipes() internally; see that * function for full details on the other parameters and details on @@ -369,7 +362,7 @@ g_spawn_sync (const gchar *working_directory, gpointer user_data, gchar **standard_output, gchar **standard_error, - gint *exit_status, + gint *wait_status, GError **error) { gint outpipe = -1; @@ -527,13 +520,13 @@ g_spawn_sync (const gchar *working_directory, goto again; else if (errno == ECHILD) { - if (exit_status) + if (wait_status) { - g_warning ("In call to g_spawn_sync(), exit status of a child process was requested but ECHILD was received by waitpid(). See the documentation of g_child_watch_source_new() for possible causes."); + g_warning ("In call to g_spawn_sync(), wait status of a child process was requested but ECHILD was received by waitpid(). See the documentation of g_child_watch_source_new() for possible causes."); } else { - /* We don't need the exit status. */ + /* We don't need the wait status. */ } } else @@ -564,8 +557,8 @@ g_spawn_sync (const gchar *working_directory, } else { - if (exit_status) - *exit_status = status; + if (wait_status) + *wait_status = status; if (standard_output) *standard_output = g_string_free (outstr, FALSE); @@ -989,7 +982,7 @@ g_spawn_async_with_fds (const gchar *working_directory, * @command_line: (type filename): a command line * @standard_output: (out) (array zero-terminated=1) (element-type guint8) (optional): return location for child output * @standard_error: (out) (array zero-terminated=1) (element-type guint8) (optional): return location for child errors - * @exit_status: (out) (optional): return location for child exit status, as returned by waitpid() + * @wait_status: (out) (optional): return location for child wait status, as returned by waitpid() * @error: return location for errors * * A simple version of g_spawn_sync() with little-used parameters @@ -1001,9 +994,11 @@ g_spawn_async_with_fds (const gchar *working_directory, * appropriate. Possible errors are those from g_spawn_sync() and those * from g_shell_parse_argv(). * - * If @exit_status is non-%NULL, the platform-specific exit status of + * If @wait_status is non-%NULL, the platform-specific status of * the child is stored there; see the documentation of - * g_spawn_check_exit_status() for how to use and interpret this. + * g_spawn_check_wait_status() for how to use and interpret this. + * On Unix platforms, note that it is usually not equal + * to the integer passed to `exit()` or returned from `main()`. * * On Windows, please note the implications of g_shell_parse_argv() * parsing @command_line. Parsing is done according to Unix shell rules, not @@ -1021,7 +1016,7 @@ gboolean g_spawn_command_line_sync (const gchar *command_line, gchar **standard_output, gchar **standard_error, - gint *exit_status, + gint *wait_status, GError **error) { gboolean retval; @@ -1042,7 +1037,7 @@ g_spawn_command_line_sync (const gchar *command_line, NULL, standard_output, standard_error, - exit_status, + wait_status, error); g_strfreev (argv); @@ -1094,80 +1089,83 @@ g_spawn_command_line_async (const gchar *command_line, } /** - * g_spawn_check_exit_status: - * @exit_status: An exit code as returned from g_spawn_sync() + * g_spawn_check_wait_status: + * @wait_status: A platform-specific wait status as returned from g_spawn_sync() * @error: a #GError * - * Set @error if @exit_status indicates the child exited abnormally + * Set @error if @wait_status indicates the child exited abnormally * (e.g. with a nonzero exit code, or via a fatal signal). * - * The g_spawn_sync() and g_child_watch_add() family of APIs return an - * exit status for subprocesses encoded in a platform-specific way. + * The g_spawn_sync() and g_child_watch_add() family of APIs return the + * status of subprocesses encoded in a platform-specific way. * On Unix, this is guaranteed to be in the same format waitpid() returns, * and on Windows it is guaranteed to be the result of GetExitCodeProcess(). * * Prior to the introduction of this function in GLib 2.34, interpreting - * @exit_status required use of platform-specific APIs, which is problematic + * @wait_status required use of platform-specific APIs, which is problematic * for software using GLib as a cross-platform layer. * * Additionally, many programs simply want to determine whether or not * the child exited successfully, and either propagate a #GError or * print a message to standard error. In that common case, this function * can be used. Note that the error message in @error will contain - * human-readable information about the exit status. + * human-readable information about the wait status. * * The @domain and @code of @error have special semantics in the case * where the process has an "exit code", as opposed to being killed by * a signal. On Unix, this happens if WIFEXITED() would be true of - * @exit_status. On Windows, it is always the case. + * @wait_status. On Windows, it is always the case. * * The special semantics are that the actual exit code will be the * code set in @error, and the domain will be %G_SPAWN_EXIT_ERROR. * This allows you to differentiate between different exit codes. * * If the process was terminated by some means other than an exit - * status, the domain will be %G_SPAWN_ERROR, and the code will be - * %G_SPAWN_ERROR_FAILED. + * status (for example if it was killed by a signal), the domain will be + * %G_SPAWN_ERROR and the code will be %G_SPAWN_ERROR_FAILED. * * This function just offers convenience; you can of course also check * the available platform via a macro such as %G_OS_UNIX, and use - * WIFEXITED() and WEXITSTATUS() on @exit_status directly. Do not attempt + * WIFEXITED() and WEXITSTATUS() on @wait_status directly. Do not attempt * to scan or parse the error message string; it may be translated and/or * change in future versions of GLib. * + * Prior to version 2.70, g_spawn_check_exit_status() provides the same + * functionality, although under a misleading name. + * * Returns: %TRUE if child exited successfully, %FALSE otherwise (and * @error will be set) * - * Since: 2.34 + * Since: 2.70 */ gboolean -g_spawn_check_exit_status (gint exit_status, +g_spawn_check_wait_status (gint wait_status, GError **error) { gboolean ret = FALSE; - if (WIFEXITED (exit_status)) + if (WIFEXITED (wait_status)) { - if (WEXITSTATUS (exit_status) != 0) + if (WEXITSTATUS (wait_status) != 0) { - g_set_error (error, G_SPAWN_EXIT_ERROR, WEXITSTATUS (exit_status), + g_set_error (error, G_SPAWN_EXIT_ERROR, WEXITSTATUS (wait_status), _("Child process exited with code %ld"), - (long) WEXITSTATUS (exit_status)); + (long) WEXITSTATUS (wait_status)); goto out; } } - else if (WIFSIGNALED (exit_status)) + else if (WIFSIGNALED (wait_status)) { g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, _("Child process killed by signal %ld"), - (long) WTERMSIG (exit_status)); + (long) WTERMSIG (wait_status)); goto out; } - else if (WIFSTOPPED (exit_status)) + else if (WIFSTOPPED (wait_status)) { g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, _("Child process stopped by signal %ld"), - (long) WSTOPSIG (exit_status)); + (long) WSTOPSIG (wait_status)); goto out; } else @@ -1182,6 +1180,34 @@ g_spawn_check_exit_status (gint exit_status, return ret; } +/** + * g_spawn_check_exit_status: + * @wait_status: A status as returned from g_spawn_sync() + * @error: a #GError + * + * An old name for g_spawn_check_wait_status(), deprecated because its + * name is misleading. + * + * Despite the name of the function, @wait_status must be the wait status + * as returned by g_spawn_sync(), g_subprocess_get_status(), `waitpid()`, + * etc. On Unix platforms, it is incorrect for it to be the exit status + * as passed to `exit()` or returned by g_subprocess_get_exit_status() or + * `WEXITSTATUS()`. + * + * Returns: %TRUE if child exited successfully, %FALSE otherwise (and + * @error will be set) + * + * Since: 2.34 + * + * Deprecated: 2.70: Use g_spawn_check_wait_status() instead, and check whether your code is conflating wait and exit statuses. + */ +gboolean +g_spawn_check_exit_status (gint wait_status, + GError **error) +{ + return g_spawn_check_wait_status (wait_status, error); +} + /* This function is called between fork() and exec() and hence must be * async-signal-safe (see signal-safety(7)). */ static gssize @@ -1494,7 +1520,7 @@ safe_closefrom (int lowfd) * * Handle ENOSYS in case it’s supported in libc but not the kernel; if so, * fall back to safe_fdwalk(). */ - if (close_range (lowfd, G_MAXUINT, 0) != 0 && errno == ENOSYS) + if (close_range (lowfd, G_MAXUINT) != 0 && errno == ENOSYS) #endif /* HAVE_CLOSE_RANGE */ (void) safe_fdwalk (close_func, GINT_TO_POINTER (lowfd)); #endif @@ -2436,13 +2462,13 @@ success: close_and_invalidate (&stderr_pipe[1]); if (stdin_pipe_out != NULL) - *stdin_pipe_out = steal_fd (&stdin_pipe[1]); + *stdin_pipe_out = g_steal_fd (&stdin_pipe[1]); if (stdout_pipe_out != NULL) - *stdout_pipe_out = steal_fd (&stdout_pipe[0]); + *stdout_pipe_out = g_steal_fd (&stdout_pipe[0]); if (stderr_pipe_out != NULL) - *stderr_pipe_out = steal_fd (&stderr_pipe[0]); + *stderr_pipe_out = g_steal_fd (&stderr_pipe[0]); return TRUE; diff --git a/glib/gspawn.h b/glib/gspawn.h index e09dc2aec..3cad30765 100644 --- a/glib/gspawn.h +++ b/glib/gspawn.h @@ -95,7 +95,7 @@ typedef enum /** * G_SPAWN_EXIT_ERROR: * - * Error domain used by g_spawn_check_exit_status(). The code + * Error domain used by g_spawn_check_wait_status(). The code * will be the program exit code. */ #define G_SPAWN_EXIT_ERROR g_spawn_exit_error_quark () @@ -259,21 +259,25 @@ gboolean g_spawn_sync (const gchar *working_directory, gpointer user_data, gchar **standard_output, gchar **standard_error, - gint *exit_status, + gint *wait_status, GError **error); GLIB_AVAILABLE_IN_ALL gboolean g_spawn_command_line_sync (const gchar *command_line, gchar **standard_output, gchar **standard_error, - gint *exit_status, + gint *wait_status, GError **error); GLIB_AVAILABLE_IN_ALL gboolean g_spawn_command_line_async (const gchar *command_line, GError **error); -GLIB_AVAILABLE_IN_2_34 -gboolean g_spawn_check_exit_status (gint exit_status, +GLIB_AVAILABLE_IN_2_70 +gboolean g_spawn_check_wait_status (gint wait_status, + GError **error); + +GLIB_DEPRECATED_IN_2_70_FOR(g_spawn_check_wait_status) +gboolean g_spawn_check_exit_status (gint wait_status, GError **error); GLIB_AVAILABLE_IN_ALL diff --git a/glib/gstring.c b/glib/gstring.c index 4f1d116d3..ad2ec1771 100644 --- a/glib/gstring.c +++ b/glib/gstring.c @@ -963,13 +963,8 @@ g_string_erase (GString *string, * * Replaces the string @find with the string @replace in a #GString up to * @limit times. If the number of instances of @find in the #GString is - * less than @limit, all instances are replaced. If the number of - * instances is `0`, all instances of @find are replaced. - * - * If @find is the empty string, since versions 2.69.1 and 2.68.4 the - * replacement will be inserted no more than once per possible position - * (beginning of string, end of string and between characters). This did - * not work correctly in earlier versions. + * less than @limit, all instances are replaced. If @limit is `0`, + * all instances of @find are replaced. * * Returns: the number of find and replace operations performed. * @@ -983,7 +978,7 @@ g_string_replace (GString *string, { gsize f_len, r_len, pos; gchar *cur, *next; - gint n = 0; + guint n = 0; g_return_val_if_fail (string != NULL, 0); g_return_val_if_fail (find != NULL, 0); @@ -1000,15 +995,6 @@ g_string_replace (GString *string, g_string_insert (string, pos, replace); cur = string->str + pos + r_len; n++; - /* Only match the empty string once at any given position, to - * avoid infinite loops */ - if (f_len == 0) - { - if (cur[0] == '\0') - break; - else - cur++; - } if (n == limit) break; } diff --git a/glib/gstrvbuilder.c b/glib/gstrvbuilder.c index 909360c95..07030b92f 100644 --- a/glib/gstrvbuilder.c +++ b/glib/gstrvbuilder.c @@ -1,5 +1,6 @@ /* * Copyright © 2020 Canonical Ltd. + * Copyright © 2021 Alexandros Theodotou * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,6 +22,7 @@ #include "garray.h" #include "gmem.h" +#include "gmessages.h" /** * SECTION:gstrvbuilder @@ -114,6 +116,48 @@ g_strv_builder_add (GStrvBuilder *builder, } /** + * g_strv_builder_addv: + * @builder: a #GStrvBuilder + * @value: (array zero-terminated=1): the vector of strings to add + * + * Appends all the strings in the given vector to the builder. + * + * Since 2.70 + */ +void +g_strv_builder_addv (GStrvBuilder *builder, + const char **value) +{ + gsize i = 0; + g_return_if_fail (builder != NULL); + g_return_if_fail (value != NULL); + for (i = 0; value[i] != NULL; i++) + g_strv_builder_add (builder, value[i]); +} + +/** + * g_strv_builder_add_many: + * @builder: a #GStrvBuilder + * @...: one or more strings followed by %NULL + * + * Appends all the given strings to the builder. + * + * Since 2.70 + */ +void +g_strv_builder_add_many (GStrvBuilder *builder, + ...) +{ + va_list var_args; + const gchar *str; + g_return_if_fail (builder != NULL); + va_start (var_args, builder); + while ((str = va_arg (var_args, gchar *)) != NULL) + g_strv_builder_add (builder, str); + va_end (var_args); +} + +/** * g_strv_builder_end: * @builder: a #GStrvBuilder * diff --git a/glib/gstrvbuilder.h b/glib/gstrvbuilder.h index 395bcfbbe..48aee0128 100644 --- a/glib/gstrvbuilder.h +++ b/glib/gstrvbuilder.h @@ -1,5 +1,6 @@ /* * Copyright © 2020 Canonical Ltd. + * Copyright © 2021 Alexandros Theodotou * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,7 +30,7 @@ G_BEGIN_DECLS /** * GStrvBuilder: - * + * * A helper object to build a %NULL-terminated string array * by appending. See g_strv_builder_new(). * @@ -50,6 +51,14 @@ GLIB_AVAILABLE_IN_2_68 void g_strv_builder_add (GStrvBuilder *builder, const char *value); +GLIB_AVAILABLE_IN_2_70 +void g_strv_builder_addv (GStrvBuilder *builder, + const char **value); + +GLIB_AVAILABLE_IN_2_70 +void g_strv_builder_add_many (GStrvBuilder *builder, + ...) G_GNUC_NULL_TERMINATED; + GLIB_AVAILABLE_IN_2_68 GStrv g_strv_builder_end (GStrvBuilder *builder); diff --git a/glib/gtester.c b/glib/gtester.c index fdcdaca10..94cfba641 100644 --- a/glib/gtester.c +++ b/glib/gtester.c @@ -745,6 +745,7 @@ fixture_test (guint *fix, g_test_bug ("123"); g_test_bug_base ("http://www.example.com/bugtracker?bugnum=%s;cmd=showbug"); g_test_bug ("456"); + g_test_bug ("https://example.com/no-base-used"); } static void fixture_teardown (guint *fix, diff --git a/glib/gtestutils.c b/glib/gtestutils.c index d9a04e044..2c3ea24a8 100644 --- a/glib/gtestutils.c +++ b/glib/gtestutils.c @@ -2013,7 +2013,7 @@ g_test_message (const char *format, * case only. * Bug URIs are constructed by appending a bug specific URI * portion to @uri_pattern, or by replacing the special string - * '\%s' within @uri_pattern if that is present. + * `%s` within @uri_pattern if that is present. * * If g_test_bug_base() is not called, bug URIs are formed solely * from the value provided by g_test_bug(). @@ -2029,15 +2029,19 @@ g_test_bug_base (const char *uri_pattern) /** * g_test_bug: - * @bug_uri_snippet: Bug specific bug tracker URI portion. + * @bug_uri_snippet: Bug specific bug tracker URI or URI portion. * * This function adds a message to test reports that * associates a bug URI with a test case. + * * Bug URIs are constructed from a base URI set with g_test_bug_base() * and @bug_uri_snippet. If g_test_bug_base() has not been called, it is * assumed to be the empty string, so a full URI can be provided to * g_test_bug() instead. * + * Since GLib 2.70, the base URI is not prepended to @bug_uri_snippet if it + * is already a valid URI. + * * Since: 2.16 * See also: g_test_summary() */ @@ -2048,6 +2052,13 @@ g_test_bug (const char *bug_uri_snippet) g_return_if_fail (bug_uri_snippet != NULL); + if (g_str_has_prefix (bug_uri_snippet, "http:") || + g_str_has_prefix (bug_uri_snippet, "https:")) + { + g_test_message ("Bug Reference: %s", bug_uri_snippet); + return; + } + if (test_uri_base != NULL) c = strstr (test_uri_base, "%s"); if (c) diff --git a/glib/gthreadpool.c b/glib/gthreadpool.c index 305152ae7..15d5d4e52 100644 --- a/glib/gthreadpool.c +++ b/glib/gthreadpool.c @@ -559,6 +559,38 @@ g_thread_pool_new (GFunc func, gboolean exclusive, GError **error) { + return g_thread_pool_new_full (func, user_data, NULL, max_threads, exclusive, error); +} + +/** + * g_thread_pool_new_full: + * @func: a function to execute in the threads of the new thread pool + * @user_data: user data that is handed over to @func every time it + * is called + * @item_free_func: (nullable): used to pass as a free function to + * g_async_queue_new_full() + * @max_threads: the maximal number of threads to execute concurrently + * in the new thread pool, `-1` means no limit + * @exclusive: should this thread pool be exclusive? + * @error: return location for error, or %NULL + * + * This function creates a new thread pool similar to g_thread_pool_new() + * but allowing @item_free_func to be specified to free the data passed + * to g_thread_pool_push() in the case that the #GThreadPool is stopped + * and freed before all tasks have been executed. + * + * Returns: (transfer full): the new #GThreadPool + * + * Since: 2.70 + */ +GThreadPool * +g_thread_pool_new_full (GFunc func, + gpointer user_data, + GDestroyNotify item_free_func, + gint max_threads, + gboolean exclusive, + GError **error) +{ GRealThreadPool *retval; G_LOCK_DEFINE_STATIC (init); @@ -571,7 +603,7 @@ g_thread_pool_new (GFunc func, retval->pool.func = func; retval->pool.user_data = user_data; retval->pool.exclusive = exclusive; - retval->queue = g_async_queue_new (); + retval->queue = g_async_queue_new_full (item_free_func); g_cond_init (&retval->cond); retval->max_threads = max_threads; retval->num_threads = 0; diff --git a/glib/gthreadpool.h b/glib/gthreadpool.h index 11c3d1d16..f2501b88b 100644 --- a/glib/gthreadpool.h +++ b/glib/gthreadpool.h @@ -51,6 +51,13 @@ GThreadPool * g_thread_pool_new (GFunc func, gint max_threads, gboolean exclusive, GError **error); +GLIB_AVAILABLE_IN_2_70 +GThreadPool * g_thread_pool_new_full (GFunc func, + gpointer user_data, + GDestroyNotify item_free_func, + gint max_threads, + gboolean exclusive, + GError **error); GLIB_AVAILABLE_IN_ALL void g_thread_pool_free (GThreadPool *pool, gboolean immediate, diff --git a/glib/gtree.c b/glib/gtree.c index 94842ac92..6ed917514 100644 --- a/glib/gtree.c +++ b/glib/gtree.c @@ -338,7 +338,16 @@ g_tree_node_next (GTreeNode *node) return tmp; } -static void +/** + * g_tree_remove_all: + * @tree: a #GTree + * + * Removes all nodes from a #GTree and destroys their keys and values, + * then resets the #GTree’s root to %NULL. + * + * Since: 2.70 + */ +void g_tree_remove_all (GTree *tree) { GTreeNode *node; diff --git a/glib/gtree.h b/glib/gtree.h index 19f9f7ea1..ff11ba435 100644 --- a/glib/gtree.h +++ b/glib/gtree.h @@ -111,6 +111,10 @@ void g_tree_replace (GTree *tree, GLIB_AVAILABLE_IN_ALL gboolean g_tree_remove (GTree *tree, gconstpointer key); + +GLIB_AVAILABLE_IN_2_70 +void g_tree_remove_all (GTree *tree); + GLIB_AVAILABLE_IN_ALL gboolean g_tree_steal (GTree *tree, gconstpointer key); diff --git a/glib/gunicollate.c b/glib/gunicollate.c index d54ef19ed..dfed1041d 100644 --- a/glib/gunicollate.c +++ b/glib/gunicollate.c @@ -441,7 +441,7 @@ g_utf8_collate_key (const gchar *str, if (str_locale) { xfrm_len = strxfrm (NULL, str_locale, 0); - if (xfrm_len < 0 || xfrm_len >= G_MAXINT - 2) + if (xfrm_len >= G_MAXINT - 2) { g_free (str_locale); str_locale = NULL; diff --git a/glib/guri.c b/glib/guri.c index a57c670ac..2c94efbc6 100644 --- a/glib/guri.c +++ b/glib/guri.c @@ -1508,6 +1508,10 @@ g_uri_parse_relative (GUri *base_uri, uri->port = normalize_port (uri->scheme, uri->port); } } + else + { + remove_dot_segments (uri->path); + } return g_steal_pointer (&uri); } diff --git a/glib/gutf8.c b/glib/gutf8.c index 51ad0d09b..ca1a395c1 100644 --- a/glib/gutf8.c +++ b/glib/gutf8.c @@ -706,7 +706,7 @@ g_utf8_get_char_validated (const gchar *p, * @str: a UTF-8 encoded string * @len: the maximum length of @str to use, in bytes. If @len < 0, * then the string is nul-terminated. - * @items_written: (out caller-allocates) (optional): location to store the + * @items_written: (out) (optional): location to store the * number of characters in the result, or %NULL. * * Convert a string from UTF-8 to a 32-bit fixed width @@ -823,13 +823,13 @@ try_malloc_n (gsize n_blocks, gsize n_block_bytes, GError **error) * @str: a UTF-8 encoded string * @len: the maximum length of @str to use, in bytes. If @len < 0, * then the string is nul-terminated. - * @items_read: (out caller-allocates) (optional): location to store number of + * @items_read: (out) (optional): location to store number of * bytes read, or %NULL. * If %NULL, then %G_CONVERT_ERROR_PARTIAL_INPUT will be * returned in case @str contains a trailing partial * character. If an error occurs then the index of the * invalid input is stored here. - * @items_written: (out caller-allocates) (optional): location to store number + * @items_written: (out) (optional): location to store number * of characters written or %NULL. The value here stored does not include * the trailing 0 character. * @error: location to store the error occurring, or %NULL to ignore @@ -909,9 +909,9 @@ g_utf8_to_ucs4 (const gchar *str, * @str: a UCS-4 encoded string * @len: the maximum length (number of characters) of @str to use. * If @len < 0, then the string is nul-terminated. - * @items_read: (out caller-allocates) (optional): location to store number of + * @items_read: (out) (optional): location to store number of * characters read, or %NULL. - * @items_written: (out caller-allocates) (optional): location to store number + * @items_written: (out) (optional): location to store number * of bytes written or %NULL. The value here stored does not include the * trailing 0 byte. * @error: location to store the error occurring, or %NULL to ignore @@ -983,11 +983,11 @@ g_ucs4_to_utf8 (const gunichar *str, * @str: a UTF-16 encoded string * @len: the maximum length (number of #gunichar2) of @str to use. * If @len < 0, then the string is nul-terminated. - * @items_read: (out caller-allocates) (optional): location to store number of + * @items_read: (out) (optional): location to store number of * words read, or %NULL. If %NULL, then %G_CONVERT_ERROR_PARTIAL_INPUT will * be returned in case @str contains a trailing partial character. If * an error occurs then the index of the invalid input is stored here. - * @items_written: (out caller-allocates) (optional): location to store number + * @items_written: (out) (optional): location to store number * of bytes written, or %NULL. The value stored here does not include the * trailing 0 byte. * @error: location to store the error occurring, or %NULL to ignore @@ -1138,11 +1138,11 @@ g_utf16_to_utf8 (const gunichar2 *str, * @str: a UTF-16 encoded string * @len: the maximum length (number of #gunichar2) of @str to use. * If @len < 0, then the string is nul-terminated. - * @items_read: (out caller-allocates) (optional): location to store number of + * @items_read: (out) (optional): location to store number of * words read, or %NULL. If %NULL, then %G_CONVERT_ERROR_PARTIAL_INPUT will * be returned in case @str contains a trailing partial character. If * an error occurs then the index of the invalid input is stored here. - * @items_written: (out caller-allocates) (optional): location to store number + * @items_written: (out) (optional): location to store number * of characters written, or %NULL. The value stored here does not include * the trailing 0 character. * @error: location to store the error occurring, or %NULL to ignore @@ -1276,11 +1276,11 @@ g_utf16_to_ucs4 (const gunichar2 *str, * @str: a UTF-8 encoded string * @len: the maximum length (number of bytes) of @str to use. * If @len < 0, then the string is nul-terminated. - * @items_read: (out caller-allocates) (optional): location to store number of + * @items_read: (out) (optional): location to store number of * bytes read, or %NULL. If %NULL, then %G_CONVERT_ERROR_PARTIAL_INPUT will * be returned in case @str contains a trailing partial character. If * an error occurs then the index of the invalid input is stored here. - * @items_written: (out caller-allocates) (optional): location to store number + * @items_written: (out) (optional): location to store number * of #gunichar2 written, or %NULL. The value stored here does not include * the trailing 0. * @error: location to store the error occurring, or %NULL to ignore @@ -1393,10 +1393,10 @@ g_utf8_to_utf16 (const gchar *str, * @str: a UCS-4 encoded string * @len: the maximum length (number of characters) of @str to use. * If @len < 0, then the string is nul-terminated. - * @items_read: (out caller-allocates) (optional): location to store number of + * @items_read: (out) (optional): location to store number of * bytes read, or %NULL. If an error occurs then the index of the invalid * input is stored here. - * @items_written: (out caller-allocates) (optional): location to store number + * @items_written: (out) (optional): location to store number * of #gunichar2 written, or %NULL. The value stored here does not include * the trailing 0. * @error: location to store the error occurring, or %NULL to ignore diff --git a/glib/gutils.c b/glib/gutils.c index dad162528..b7a2113d4 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -340,7 +340,17 @@ g_find_program_in_path (const gchar *program) { if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE) && !g_file_test (program, G_FILE_TEST_IS_DIR)) - return g_strdup (program); + { + gchar *out = NULL, *cwd = NULL; + + if (g_path_is_absolute (program)) + return g_strdup (program); + + cwd = g_get_current_dir (); + out = g_build_filename (cwd, program, NULL); + g_free (cwd); + return g_steal_pointer (&out); + } else return NULL; } @@ -548,23 +558,20 @@ static gchar **g_user_special_dirs = NULL; #ifdef G_OS_WIN32 static gchar * -get_special_folder (int csidl) +get_special_folder (REFKNOWNFOLDERID known_folder_guid_ptr) { - wchar_t path[MAX_PATH+1]; + wchar_t *wcp = NULL; + gchar *result = NULL; HRESULT hr; - LPITEMIDLIST pidl = NULL; - BOOL b; - gchar *retval = NULL; - hr = SHGetSpecialFolderLocation (NULL, csidl, &pidl); - if (hr == S_OK) - { - b = SHGetPathFromIDListW (pidl, path); - if (b) - retval = g_utf16_to_utf8 (path, -1, NULL, NULL, NULL); - CoTaskMemFree (pidl); - } - return retval; + hr = SHGetKnownFolderPath (known_folder_guid_ptr, 0, NULL, &wcp); + + if (SUCCEEDED (hr)) + result = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL); + + CoTaskMemFree (wcp); + + return result; } static char * @@ -814,7 +821,7 @@ g_build_home_dir (void) } if (home_dir == NULL) - home_dir = get_special_folder (CSIDL_PROFILE); + home_dir = get_special_folder (&FOLDERID_Profile); if (home_dir == NULL) home_dir = get_windows_directory_root (); @@ -1704,7 +1711,7 @@ g_build_user_data_dir (void) data_dir = g_strdup (data_dir_env); #ifdef G_OS_WIN32 else - data_dir = get_special_folder (CSIDL_LOCAL_APPDATA); + data_dir = get_special_folder (&FOLDERID_LocalAppData); #endif if (!data_dir || !data_dir[0]) { @@ -1730,7 +1737,7 @@ g_build_user_data_dir (void) * On Windows it follows XDG Base Directory Specification if `XDG_DATA_HOME` * is defined. If `XDG_DATA_HOME` is undefined, the folder to use for local (as * opposed to roaming) application data is used instead. See the - * [documentation for `CSIDL_LOCAL_APPDATA`](https://msdn.microsoft.com/en-us/library/windows/desktop/bb762494%28v=vs.85%29.aspx#csidl_local_appdata). + * [documentation for `FOLDERID_LocalAppData`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid). * Note that in this case on Windows it will be the same * as what g_get_user_config_dir() returns. * @@ -1768,7 +1775,7 @@ g_build_user_config_dir (void) config_dir = g_strdup (config_dir_env); #ifdef G_OS_WIN32 else - config_dir = get_special_folder (CSIDL_LOCAL_APPDATA); + config_dir = get_special_folder (&FOLDERID_LocalAppData); #endif if (!config_dir || !config_dir[0]) { @@ -1794,7 +1801,7 @@ g_build_user_config_dir (void) * On Windows it follows XDG Base Directory Specification if `XDG_CONFIG_HOME` is defined. * If `XDG_CONFIG_HOME` is undefined, the folder to use for local (as opposed * to roaming) application data is used instead. See the - * [documentation for `CSIDL_LOCAL_APPDATA`](https://msdn.microsoft.com/en-us/library/windows/desktop/bb762494%28v=vs.85%29.aspx#csidl_local_appdata). + * [documentation for `FOLDERID_LocalAppData`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid). * Note that in this case on Windows it will be the same * as what g_get_user_data_dir() returns. * @@ -1831,7 +1838,7 @@ g_build_user_cache_dir (void) cache_dir = g_strdup (cache_dir_env); #ifdef G_OS_WIN32 else - cache_dir = get_special_folder (CSIDL_INTERNET_CACHE); + cache_dir = get_special_folder (&FOLDERID_InternetCache); #endif if (!cache_dir || !cache_dir[0]) { @@ -1858,7 +1865,7 @@ g_build_user_cache_dir (void) * If `XDG_CACHE_HOME` is undefined, the directory that serves as a common * repository for temporary Internet files is used instead. A typical path is * `C:\Documents and Settings\username\Local Settings\Temporary Internet Files`. - * See the [documentation for `CSIDL_INTERNET_CACHE`](https://msdn.microsoft.com/en-us/library/windows/desktop/bb762494%28v=vs.85%29.aspx#csidl_internet_cache). + * See the [documentation for `FOLDERID_InternetCache`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid). * * The return value is cached and modifying it at runtime is not supported, as * it’s not thread-safe to modify environment variables at runtime. @@ -1965,69 +1972,22 @@ load_user_special_dirs (void) static void load_user_special_dirs (void) { - typedef HRESULT (WINAPI *t_SHGetKnownFolderPath) (const GUID *rfid, - DWORD dwFlags, - HANDLE hToken, - PWSTR *ppszPath); - t_SHGetKnownFolderPath p_SHGetKnownFolderPath; + g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] = get_special_folder (&FOLDERID_Desktop); + g_user_special_dirs[G_USER_DIRECTORY_DOCUMENTS] = get_special_folder (&FOLDERID_Documents); - static const GUID FOLDERID_Downloads = - { 0x374de290, 0x123f, 0x4565, { 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b } }; - static const GUID FOLDERID_Public = - { 0xDFDF76A2, 0xC82A, 0x4D63, { 0x90, 0x6A, 0x56, 0x44, 0xAC, 0x45, 0x73, 0x85 } }; + g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (&FOLDERID_Downloads); + if (g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] == NULL) + g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (&FOLDERID_Desktop); - wchar_t *wcp; - - p_SHGetKnownFolderPath = (t_SHGetKnownFolderPath) GetProcAddress (GetModuleHandleW (L"shell32.dll"), - "SHGetKnownFolderPath"); - - g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] = get_special_folder (CSIDL_DESKTOPDIRECTORY); - g_user_special_dirs[G_USER_DIRECTORY_DOCUMENTS] = get_special_folder (CSIDL_PERSONAL); - - if (p_SHGetKnownFolderPath == NULL) - { - g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (CSIDL_DESKTOPDIRECTORY); - } - else - { - wcp = NULL; - (*p_SHGetKnownFolderPath) (&FOLDERID_Downloads, 0, NULL, &wcp); - if (wcp) - { - g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL); - if (g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] == NULL) - g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (CSIDL_DESKTOPDIRECTORY); - CoTaskMemFree (wcp); - } - else - g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (CSIDL_DESKTOPDIRECTORY); - } + g_user_special_dirs[G_USER_DIRECTORY_MUSIC] = get_special_folder (&FOLDERID_Music); + g_user_special_dirs[G_USER_DIRECTORY_PICTURES] = get_special_folder (&FOLDERID_Pictures); - g_user_special_dirs[G_USER_DIRECTORY_MUSIC] = get_special_folder (CSIDL_MYMUSIC); - g_user_special_dirs[G_USER_DIRECTORY_PICTURES] = get_special_folder (CSIDL_MYPICTURES); + g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (&FOLDERID_Public); + if (g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] == NULL) + g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (&FOLDERID_PublicDocuments); - if (p_SHGetKnownFolderPath == NULL) - { - /* XXX */ - g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (CSIDL_COMMON_DOCUMENTS); - } - else - { - wcp = NULL; - (*p_SHGetKnownFolderPath) (&FOLDERID_Public, 0, NULL, &wcp); - if (wcp) - { - g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL); - if (g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] == NULL) - g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (CSIDL_COMMON_DOCUMENTS); - CoTaskMemFree (wcp); - } - else - g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (CSIDL_COMMON_DOCUMENTS); - } - - g_user_special_dirs[G_USER_DIRECTORY_TEMPLATES] = get_special_folder (CSIDL_TEMPLATES); - g_user_special_dirs[G_USER_DIRECTORY_VIDEOS] = get_special_folder (CSIDL_MYVIDEO); + g_user_special_dirs[G_USER_DIRECTORY_TEMPLATES] = get_special_folder (&FOLDERID_Templates); + g_user_special_dirs[G_USER_DIRECTORY_VIDEOS] = get_special_folder (&FOLDERID_Videos); } #else /* default is unix */ @@ -2379,12 +2339,12 @@ g_win32_get_system_data_dirs_for_module_real (void (*address_of_function)(void)) data_dirs = g_array_new (TRUE, TRUE, sizeof (char *)); /* Documents and Settings\All Users\Application Data */ - p = get_special_folder (CSIDL_COMMON_APPDATA); + p = get_special_folder (&FOLDERID_ProgramData); if (p) g_array_append_val (data_dirs, p); /* Documents and Settings\All Users\Documents */ - p = get_special_folder (CSIDL_COMMON_DOCUMENTS); + p = get_special_folder (&FOLDERID_PublicDocuments); if (p) g_array_append_val (data_dirs, p); @@ -2531,8 +2491,8 @@ g_build_system_data_dirs (void) * the first elements in the list are the Application Data * and Documents folders for All Users. (These can be determined only * on Windows 2000 or later and are not present in the list on other - * Windows versions.) See documentation for CSIDL_COMMON_APPDATA and - * CSIDL_COMMON_DOCUMENTS. + * Windows versions.) See documentation for FOLDERID_ProgramData and + * FOLDERID_PublicDocuments. * * Then follows the "share" subfolder in the installation folder for * the package containing the DLL that calls this function, if it can @@ -2587,7 +2547,7 @@ g_build_system_config_dirs (void) } else { - gchar *special_conf_dirs = get_special_folder (CSIDL_COMMON_APPDATA); + gchar *special_conf_dirs = get_special_folder (&FOLDERID_ProgramData); if (special_conf_dirs) conf_dir_vector = g_strsplit (special_conf_dirs, G_SEARCHPATH_SEPARATOR_S, 0); @@ -2625,7 +2585,7 @@ g_build_system_config_dirs (void) * This folder is used for application data * that is not user specific. For example, an application can store * a spell-check dictionary, a database of clip art, or a log file in the - * CSIDL_COMMON_APPDATA folder. This information will not roam and is available + * FOLDERID_ProgramData folder. This information will not roam and is available * to anyone using the computer. * * The return value is cached and modifying it at runtime is not supported, as diff --git a/glib/guuid.c b/glib/guuid.c index f26343ee0..5368465c5 100644 --- a/glib/guuid.c +++ b/glib/guuid.c @@ -113,7 +113,7 @@ uuid_parse_string (const gchar *str, if (hi == -1 || lo == -1) return FALSE; - bytes[i++] = hi << 8 | lo; + bytes[i++] = hi << 4 | lo; } if (uuid != NULL) diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c index b34ba8d8e..a31d396dd 100644 --- a/glib/gvariant-core.c +++ b/glib/gvariant-core.c @@ -81,22 +81,22 @@ struct _GVariant /* struct GVariant: * - * There are two primary forms of GVariant instances: "serialised form" + * There are two primary forms of GVariant instances: "serialized form" * and "tree form". * - * "serialised form": A serialised GVariant instance stores its value in - * the GVariant serialisation format. All + * "serialized form": A serialized GVariant instance stores its value in + * the GVariant serialization format. All * basic-typed instances (ie: non-containers) are in - * serialised format, as are some containers. + * serialized format, as are some containers. * * "tree form": Some containers are in "tree form". In this case, - * instead of containing the serialised data for the + * instead of containing the serialized data for the * container, the instance contains an array of pointers to * the child values of the container (thus forming a tree). * * It is possible for an instance to transition from tree form to - * serialised form. This happens, implicitly, if the serialised data is - * requested (eg: via g_variant_get_data()). Serialised form instances + * serialized form. This happens, implicitly, if the serialized data is + * requested (eg: via g_variant_get_data()). Serialized form instances * never transition into tree form. * * @@ -109,8 +109,8 @@ struct _GVariant * The type_info field never changes during the life of the * instance, so it can be accessed without a lock. * - * size: this is the size of the serialised form for the instance, if it - * is known. If the instance is in serialised form then it is, by + * size: this is the size of the serialized form for the instance, if it + * is known. If the instance is in serialized form then it is, by * definition, known. If the instance is in tree form then it may * be unknown (in which case it is -1). It is possible for the * size to be known when in tree form if, for example, the user @@ -126,33 +126,33 @@ struct _GVariant * that, the size field can be accessed without a lock. * * contents: a union containing either the information associated with - * holding a value in serialised form or holding a value in + * holding a value in serialized form or holding a value in * tree form. * - * .serialised: Only valid when the instance is in serialised form. + * .serialised: Only valid when the instance is in serialized form. * * Since an instance can never transition away from - * serialised form, once these fields are set, they will + * serialized form, once these fields are set, they will * never be changed. It is therefore valid to access * them without holding a lock. * * .bytes: the #GBytes that contains the memory pointed to by * .data, or %NULL if .data is %NULL. In the event that - * the instance was deserialised from another instance, + * the instance was deserialized from another instance, * then the bytes will be shared by both of them. When * the instance is freed, this reference must be released * with g_bytes_unref(). * - * .data: the serialised data (of size 'size') of the instance. + * .data: the serialized data (of size 'size') of the instance. * This pointer should not be freed or modified in any way. * #GBytes is responsible for memory management. * * This pointer may be %NULL in two cases: * - * - if the serialised size of the instance is 0 + * - if the serialized size of the instance is 0 * * - if the instance is of a fixed-sized type and was - * deserialised out of a corrupted container such that + * deserialized out of a corrupted container such that * the container contains too few bytes to point to the * entire proper fixed-size of this instance. In this * case, 'size' will still be equal to the proper fixed @@ -165,12 +165,12 @@ struct _GVariant * .tree: Only valid when the instance is in tree form. * * Note that accesses from other threads could result in - * conversion of the instance from tree form to serialised form + * conversion of the instance from tree form to serialized form * at any time. For this reason, the instance lock must always * be held while performing any operations on 'contents.tree'. * * .children: the array of the child instances of this instance. - * When the instance is freed (or converted to serialised + * When the instance is freed (or converted to serialized * form) then each child must have g_variant_unref() * called on it and the array must be freed using * g_free(). @@ -183,18 +183,18 @@ struct _GVariant * STATE_LOCKED: the instance lock is held. This is the bit used by * g_bit_lock(). * - * STATE_SERIALISED: the instance is in serialised form. If this + * STATE_SERIALISED: the instance is in serialized form. If this * flag is not set then the instance is in tree * form. * - * STATE_TRUSTED: for serialised form instances, this means that the - * serialised data is known to be in normal form (ie: + * STATE_TRUSTED: for serialized form instances, this means that the + * serialized data is known to be in normal form (ie: * not corrupted). * * For tree form instances, this means that all of the * child instances in the contents.tree.children array * are trusted. This means that if the container is - * serialised then the resulting data will be in + * serialized then the resulting data will be in * normal form. * * If this flag is unset it does not imply that the @@ -209,7 +209,7 @@ struct _GVariant * depth: the depth of the GVariant in a hierarchy of nested containers, * increasing with the level of nesting. The top-most GVariant has depth * zero. This is used to avoid recursing too deeply and overflowing the - * stack when handling deeply nested untrusted serialised GVariants. + * stack when handling deeply nested untrusted serialized GVariants. */ #define STATE_LOCKED 1 #define STATE_SERIALISED 2 @@ -249,7 +249,7 @@ g_variant_unlock (GVariant *value) * @value and frees the array itself. @value must be in tree form. * * This is done when freeing a tree-form instance or converting it to - * serialised form. + * serialized form. * * The current thread must hold the lock on @value. */ @@ -267,52 +267,52 @@ g_variant_release_children (GVariant *value) g_free (value->contents.tree.children); } -/* This begins the main body of the recursive serialiser. +/* This begins the main body of the recursive serializer. * - * There are 3 functions here that work as a team with the serialiser to + * There are 3 functions here that work as a team with the serializer to * get things done. g_variant_store() has a trivial role, but as a * public API function, it has its definition elsewhere. * - * Note that "serialisation" of an instance does not mean that the - * instance is converted to serialised form -- it means that the - * serialised form of an instance is written to an external buffer. + * Note that "serialization" of an instance does not mean that the + * instance is converted to serialized form -- it means that the + * serialized form of an instance is written to an external buffer. * g_variant_ensure_serialised() (which is not part of this set of * functions) is the function that is responsible for converting an - * instance to serialised form. + * instance to serialized form. * * We are only concerned here with container types since non-container - * instances are always in serialised form. For these instances, - * storing their serialised form merely involves a memcpy(). + * instances are always in serialized form. For these instances, + * storing their serialized form merely involves a memcpy(). * - * Serialisation is a two-step process. First, the size of the - * serialised data must be calculated so that an appropriately-sized + * Serialization is a two-step process. First, the size of the + * serialized data must be calculated so that an appropriately-sized * buffer can be allocated. Second, the data is written into the * buffer. * * Determining the size: * The process of determining the size is triggered by a call to * g_variant_ensure_size() on a container. This invokes the - * serialiser code to determine the size. The serialiser is passed + * serializer code to determine the size. The serializer is passed * g_variant_fill_gvs() as a callback. * - * g_variant_fill_gvs() is called by the serialiser on each child of + * g_variant_fill_gvs() is called by the serializer on each child of * the container which, in turn, calls g_variant_ensure_size() on * itself and fills in the result of its own size calculation. * - * The serialiser uses the size information from the children to + * The serializer uses the size information from the children to * calculate the size needed for the entire container. * * Writing the data: * After the buffer has been allocated, g_variant_serialise() is - * called on the container. This invokes the serialiser code to write - * the bytes to the container. The serialiser is, again, passed + * called on the container. This invokes the serializer code to write + * the bytes to the container. The serializer is, again, passed * g_variant_fill_gvs() as a callback. * * This time, when g_variant_fill_gvs() is called for each child, the * child is given a pointer to a sub-region of the allocated buffer * where it should write its data. This is done by calling - * g_variant_store(). In the event that the instance is in serialised - * form this means a memcpy() of the serialised data into the + * g_variant_store(). In the event that the instance is in serialized + * form this means a memcpy() of the serialized data into the * allocated buffer. In the event that the instance is in tree form * this means a recursive call back into g_variant_serialise(). * @@ -326,7 +326,7 @@ static void g_variant_fill_gvs (GVariantSerialised *, gpointer); * @value: a #GVariant * * Ensures that the ->size field of @value is filled in properly. This - * must be done as a precursor to any serialisation of the value in + * must be done as a precursor to any serialization of the value in * order to know how large of a buffer is needed to store the data. * * The current thread must hold the lock on @value. @@ -354,7 +354,7 @@ g_variant_ensure_size (GVariant *value) * @value: a #GVariant * @data: an appropriately-sized buffer * - * Serialises @value into @data. @value must be in tree form. + * Serializes @value into @data. @value must be in tree form. * * No change is made to @value. * @@ -389,15 +389,15 @@ g_variant_serialise (GVariant *value, * @data: a #GVariant instance * * This is the callback that is passed by a tree-form container instance - * to the serialiser. This callback gets called on each child of the + * to the serializer. This callback gets called on each child of the * container. Each child is responsible for performing the following * actions: * * - reporting its type * - * - reporting its serialised size (requires knowing the size first) + * - reporting its serialized size (requires knowing the size first) * - * - possibly storing its serialised form into the provided buffer + * - possibly storing its serialized form into the provided buffer */ static void g_variant_fill_gvs (GVariantSerialised *serialised, @@ -425,18 +425,18 @@ g_variant_fill_gvs (GVariantSerialised *serialised, g_variant_store (value, serialised->data); } -/* this ends the main body of the recursive serialiser */ +/* this ends the main body of the recursive serializer */ /* < private > * g_variant_ensure_serialised: * @value: a #GVariant * - * Ensures that @value is in serialised form. + * Ensures that @value is in serialized form. * * If @value is in tree form then this function ensures that the - * serialised size is known and then allocates a buffer of that size and - * serialises the instance into the buffer. The 'children' array is - * then released and the instance is set to serialised form based on the + * serialized size is known and then allocates a buffer of that size and + * serializes the instance into the buffer. The 'children' array is + * then released and the instance is set to serialized form based on the * contents of the buffer. * * The current thread must hold the lock on @value. @@ -501,8 +501,8 @@ g_variant_alloc (const GVariantType *type, * @bytes: a #GBytes * @trusted: if the contents of @bytes are trusted * - * Constructs a new serialised-mode #GVariant instance. This is the - * inner interface for creation of new serialised values that gets + * Constructs a new serialized-mode #GVariant instance. This is the + * inner interface for creation of new serialized values that gets * called from various functions in gvariant.c. * * A reference is taken on @bytes. @@ -605,7 +605,7 @@ g_variant_new_from_bytes (const GVariantType *type, * @trusted: %TRUE if every child in @children in trusted * * Constructs a new tree-mode #GVariant instance. This is the inner - * interface for creation of new serialised values that gets called from + * interface for creation of new serialized values that gets called from * various functions in gvariant.c. * * @children is consumed by this function. g_free() will be called on @@ -872,13 +872,13 @@ g_variant_is_floating (GVariant *value) * If @value has a fixed-sized type then this function always returned * that fixed size. * - * In the case that @value is already in serialised form or the size has + * In the case that @value is already in serialized form or the size has * already been calculated (ie: this function has been called before) * then this function is O(1). Otherwise, the size is calculated, an * operation which is approximately O(n) in the number of values * involved. * - * Returns: the serialised size of @value + * Returns: the serialized size of @value * * Since: 2.24 **/ @@ -896,33 +896,33 @@ g_variant_get_size (GVariant *value) * g_variant_get_data: * @value: a #GVariant instance * - * Returns a pointer to the serialised form of a #GVariant instance. + * Returns a pointer to the serialized form of a #GVariant instance. * The returned data may not be in fully-normalised form if read from an * untrusted source. The returned data must not be freed; it remains * valid for as long as @value exists. * - * If @value is a fixed-sized value that was deserialised from a - * corrupted serialised container then %NULL may be returned. In this + * If @value is a fixed-sized value that was deserialized from a + * corrupted serialized container then %NULL may be returned. In this * case, the proper thing to do is typically to use the appropriate * number of nul bytes in place of @value. If @value is not fixed-sized * then %NULL is never returned. * - * In the case that @value is already in serialised form, this function - * is O(1). If the value is not already in serialised form, - * serialisation occurs implicitly and is approximately O(n) in the size + * In the case that @value is already in serialized form, this function + * is O(1). If the value is not already in serialized form, + * serialization occurs implicitly and is approximately O(n) in the size * of the result. * - * To deserialise the data returned by this function, in addition to the - * serialised data, you must know the type of the #GVariant, and (if the + * To deserialize the data returned by this function, in addition to the + * serialized data, you must know the type of the #GVariant, and (if the * machine might be different) the endianness of the machine that stored * it. As a result, file formats or network messages that incorporate - * serialised #GVariants must include this information either + * serialized #GVariants must include this information either * implicitly (for instance "the file always contains a * %G_VARIANT_TYPE_VARIANT and it is always in little-endian order") or * explicitly (by storing the type and/or endianness in addition to the - * serialised data). + * serialized data). * - * Returns: (transfer none): the serialised form of @value, or %NULL + * Returns: (transfer none): the serialized form of @value, or %NULL * * Since: 2.24 **/ @@ -940,7 +940,7 @@ g_variant_get_data (GVariant *value) * g_variant_get_data_as_bytes: * @value: a #GVariant * - * Returns a pointer to the serialised form of a #GVariant instance. + * Returns a pointer to the serialized form of a #GVariant instance. * The semantics of this function are exactly the same as * g_variant_get_data(), except that the returned #GBytes holds * a reference to the variant data. @@ -1043,7 +1043,7 @@ g_variant_n_children (GVariant *value) * * Note that values borrowed from the returned child are not guaranteed to * still be valid after the child is freed even if you still hold a reference - * to @value, if @value has not been serialised at the time this function is + * to @value, if @value has not been serialized at the time this function is * called. To avoid this, you can serialize @value by calling * g_variant_get_data() and optionally ignoring the return value. * @@ -1092,8 +1092,8 @@ g_variant_get_child_value (GVariant *value, GVariantSerialised s_child; GVariant *child; - /* get the serialiser to extract the serialised data for the child - * from the serialised data for the container + /* get the serializer to extract the serialized data for the child + * from the serialized data for the container */ s_child = g_variant_serialised_get_child (serialised, index_); @@ -1111,7 +1111,7 @@ g_variant_get_child_value (GVariant *value, return g_variant_new_tuple (NULL, 0); } - /* create a new serialised instance out of it */ + /* create a new serialized instance out of it */ child = g_slice_new (GVariant); child->type_info = s_child.type_info; child->state = (value->state & STATE_TRUSTED) | @@ -1130,17 +1130,17 @@ g_variant_get_child_value (GVariant *value, /** * g_variant_store: * @value: the #GVariant to store - * @data: (not nullable): the location to store the serialised data at + * @data: (not nullable): the location to store the serialized data at * - * Stores the serialised form of @value at @data. @data should be + * Stores the serialized form of @value at @data. @data should be * large enough. See g_variant_get_size(). * * The stored data is in machine native byte order but may not be in * fully-normalised form if read from an untrusted source. See * g_variant_get_normal_form() for a solution. * - * As with g_variant_get_data(), to be able to deserialise the - * serialised variant successfully, its type and (if the destination + * As with g_variant_get_data(), to be able to deserialize the + * serialized variant successfully, its type and (if the destination * machine might be different) its endianness must also be available. * * This function is approximately O(n) in the size of @data. @@ -1173,7 +1173,7 @@ g_variant_store (GVariant *value, * Checks if @value is in normal form. * * The main reason to do this is to detect if a given chunk of - * serialised data is in normal form: load the data into a #GVariant + * serialized data is in normal form: load the data into a #GVariant * using g_variant_new_from_data() and then use this function to * check. * diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c index 06f419fe4..832a8fdc2 100644 --- a/glib/gvariant-serialiser.c +++ b/glib/gvariant-serialiser.c @@ -44,26 +44,26 @@ * container and implements 5 functions for dealing with it: * * n_children: - * - determines (according to serialised data) how many child values + * - determines (according to serialized data) how many child values * are inside a particular container value. * * get_child: - * - gets the type of and the serialised data corresponding to a + * - gets the type of and the serialized data corresponding to a * given child value within the container value. * * needed_size: - * - determines how much space would be required to serialise a + * - determines how much space would be required to serialize a * container of this type, containing the given children so that - * buffers can be preallocated before serialising. + * buffers can be preallocated before serializing. * * serialise: - * - write the serialised data for a container of this type, + * - write the serialized data for a container of this type, * containing the given children, to a buffer. * * is_normal: * - check the given data to ensure that it is in normal form. For a * given set of child values, there is exactly one normal form for - * the serialised data of a container. Other forms are possible + * the serialized data of a container. Other forms are possible * while maintaining the same children (for example, by inserting * something other than zero bytes as padding) but only one form is * the normal form. @@ -72,7 +72,7 @@ * functions and logic to dispatch it to the handler for the appropriate * container type code. * - * The second part also contains a routine to byteswap serialised + * The second part also contains a routine to byteswap serialized * values. This code makes use of the n_children() and get_child() * functions above to do its work so no extra support is needed on a * per-container-type basis. @@ -90,17 +90,17 @@ /* < private > * GVariantSerialised: * @type_info: the #GVariantTypeInfo of this value - * @data: (nullable): the serialised data of this value, or %NULL + * @data: (nullable): the serialized data of this value, or %NULL * @size: the size of this value * - * A structure representing a GVariant in serialised form. This + * A structure representing a GVariant in serialized form. This * structure is used with #GVariantSerialisedFiller functions and as the - * primary interface to the serialiser. See #GVariantSerialisedFiller + * primary interface to the serializer. See #GVariantSerialisedFiller * for a description of its use there. * - * When used with the serialiser API functions, the following invariants + * When used with the serializer API functions, the following invariants * apply to all #GVariantTypeSerialised structures passed to and - * returned from the serialiser. + * returned from the serializer. * * @type_info must be non-%NULL. * @@ -117,7 +117,7 @@ * combination should be as if @data were a pointer to an * appropriately-sized zero-filled region. * - * @depth has no restrictions; the depth of a top-level serialised #GVariant is + * @depth has no restrictions; the depth of a top-level serialized #GVariant is * zero, and it increases for each level of nested child. */ @@ -185,9 +185,9 @@ g_variant_serialised_check (GVariantSerialised serialised) * from a partially-complete #GVariantSerialised. * * The @data parameter passed back to the function is one of the items - * that was passed to the serialiser in the @children array. It + * that was passed to the serializer in the @children array. It * represents a single child item of the container that is being - * serialised. The information filled in to @serialised is the + * serialized. The information filled in to @serialised is the * information for this child. * * If the @type_info field of @serialised is %NULL then the callback @@ -197,24 +197,24 @@ g_variant_serialised_check (GVariantSerialised serialised) * of the child. * * If the @size field is zero then the callback must fill it in with the - * required amount of space to store the serialised form of the child. + * required amount of space to store the serialized form of the child. * If it is non-zero then the callback should assert that it is equal to * the needed size of the child. * * If @data is non-%NULL then it points to a space that is properly - * aligned for and large enough to store the serialised data of the - * child. The callback must store the serialised form of the child at + * aligned for and large enough to store the serialized data of the + * child. The callback must store the serialized form of the child at * @data. * * If the child value is another container then the callback will likely - * recurse back into the serialiser by calling + * recurse back into the serializer by calling * g_variant_serialiser_needed_size() to determine @size and * g_variant_serialiser_serialise() to write to @data. */ /* PART 1: Container types {{{1 * - * This section contains the serialiser implementation functions for + * This section contains the serializer implementation functions for * each container type. */ @@ -235,7 +235,7 @@ g_variant_serialised_check (GVariantSerialised serialised) * size of the maybe value is zero corresponds to the "Nothing" case and * the case where the size of the maybe value is equal to the fixed size * of the element type corresponds to the "Just" case; in that case, the - * serialised data of the child value forms the entire serialised data + * serialized data of the child value forms the entire serialized data * of the maybe value. * * In the event that a fixed-sized maybe value is presented with a size @@ -331,11 +331,11 @@ gvs_fixed_sized_maybe_is_normal (GVariantSerialised value) * either 0 or strictly greater than 0. The case where the size of the * maybe value is zero corresponds to the "Nothing" case and the case * where the size of the maybe value is greater than zero corresponds to - * the "Just" case; in that case, the serialised data of the child value - * forms the first part of the serialised data of the maybe value and is + * the "Just" case; in that case, the serialized data of the child value + * forms the first part of the serialized data of the maybe value and is * followed by a single zero byte. This zero byte is always appended, * regardless of any zero bytes that may already be at the end of the - * serialised ata of the child value. + * serialized ata of the child value. */ static gsize @@ -424,8 +424,8 @@ gvs_variable_sized_maybe_is_normal (GVariantSerialised value) /* Fixed-sized Array {{{3 * - * For fixed sized arrays, the serialised data is simply a concatenation - * of the serialised data of each element, in order. Since fixed-sized + * For fixed sized arrays, the serialized data is simply a concatenation + * of the serialized data of each element, in order. Since fixed-sized * values always have a fixed size that is a multiple of their alignment * requirement no extra padding is required. * @@ -535,35 +535,35 @@ gvs_fixed_sized_array_is_normal (GVariantSerialised value) * record the end point of each element in the array. * * GVariant works in terms of "offsets". An offset is a pointer to a - * boundary between two bytes. In 4 bytes of serialised data, there + * boundary between two bytes. In 4 bytes of serialized data, there * would be 5 possible offsets: one at the start ('0'), one between each * pair of adjacent bytes ('1', '2', '3') and one at the end ('4'). * * The numeric value of an offset is an unsigned integer given relative - * to the start of the serialised data of the array. Offsets are always + * to the start of the serialized data of the array. Offsets are always * stored in little endian byte order and are always only as big as they - * need to be. For example, in 255 bytes of serialised data, there are + * need to be. For example, in 255 bytes of serialized data, there are * 256 offsets. All possibilities can be stored in an 8 bit unsigned - * integer. In 256 bytes of serialised data, however, there are 257 + * integer. In 256 bytes of serialized data, however, there are 257 * possible offsets so 16 bit integers must be used. The size of an * offset is always a power of 2. * - * The offsets are stored at the end of the serialised data of the + * The offsets are stored at the end of the serialized data of the * array. They are simply concatenated on without any particular * alignment. The size of the offsets is included in the size of the - * serialised data for purposes of determining the size of the offsets. + * serialized data for purposes of determining the size of the offsets. * This presents a possibly ambiguity; in certain cases, a particular - * value of array could have two different serialised forms. + * value of array could have two different serialized forms. * * Imagine an array containing a single string of 253 bytes in length * (so, 254 bytes including the nul terminator). Now the offset must be * written. If an 8 bit offset is written, it will bring the size of - * the array's serialised data to 255 -- which means that the use of an + * the array's serialized data to 255 -- which means that the use of an * 8 bit offset was valid. If a 16 bit offset is used then the total * size of the array will be 256 -- which means that the use of a 16 bit * offset was valid. Although both of these will be accepted by the - * deserialiser, only the smaller of the two is considered to be in - * normal form and that is the one that the serialiser must produce. + * deserializer, only the smaller of the two is considered to be in + * normal form and that is the one that the serializer must produce. */ /* bytes may be NULL if (size == 0). */ @@ -840,20 +840,20 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value) /* Tuples {{{2 * * Since tuples can contain a mix of variable- and fixed-sized items, - * they are, in terms of serialisation, a hybrid of variable-sized and + * they are, in terms of serialization, a hybrid of variable-sized and * fixed-sized arrays. * * Offsets are only stored for variable-sized items. Also, since the * number of items in a tuple is known from its type, we are able to - * know exactly how many offsets to expect in the serialised data (and + * know exactly how many offsets to expect in the serialized data (and * therefore how much space is taken up by the offset array). This - * means that we know where the end of the serialised data for the last + * means that we know where the end of the serialized data for the last * item is -- we can just subtract the size of the offset array from the * total size of the tuple. For this reason, the last item in the tuple * doesn't need an offset stored. * * Tuple offsets are stored in reverse. This design choice allows - * iterator-based deserialisers to be more efficient. + * iterator-based deserializers to be more efficient. * * Most of the "heavy lifting" here is handled by the GVariantTypeInfo * for the tuple. See the notes in gvarianttypeinfo.h. @@ -1158,7 +1158,7 @@ gvs_tuple_is_normal (GVariantSerialised value) /* Variants {{{2 * - * Variants are stored by storing the serialised data of the child, + * Variants are stored by storing the serialized data of the child, * followed by a '\0' character, followed by the type string of the * child. * @@ -1287,9 +1287,9 @@ gvs_variant_is_normal (GVariantSerialised value) -/* PART 2: Serialiser API {{{1 +/* PART 2: Serializer API {{{1 * - * This is the implementation of the API of the serialiser as advertised + * This is the implementation of the API of the serializer as advertised * in gvariant-serialiser.h. */ @@ -1338,9 +1338,9 @@ gvs_variant_is_normal (GVariantSerialised value) } \ } -/* Serialiser entry points {{{2 +/* Serializer entry points {{{2 * - * These are the functions that are called in order for the serialiser + * These are the functions that are called in order for the serializer * to do its thing. */ @@ -1348,7 +1348,7 @@ gvs_variant_is_normal (GVariantSerialised value) * g_variant_serialised_n_children: * @serialised: a #GVariantSerialised * - * For serialised data that represents a container value (maybes, + * For serialized data that represents a container value (maybes, * tuples, arrays, variants), determine how many child items are inside * that container. * @@ -1372,7 +1372,7 @@ g_variant_serialised_n_children (GVariantSerialised serialised) * @serialised: a #GVariantSerialised * @index_: the index of the child to fetch * - * Extracts a child from a serialised data representing a container + * Extracts a child from a serialized data representing a container * value. * * It is an error to call this function with an index out of bounds. @@ -1421,19 +1421,19 @@ g_variant_serialised_get_child (GVariantSerialised serialised, * @children: an array of child items * @n_children: the size of @children * - * Writes data in serialised form. + * Writes data in serialized form. * * The type_info field of @serialised must be filled in to type info for - * the type that we are serialising. + * the type that we are serializing. * * The size field of @serialised must be filled in with the value * returned by a previous call to g_variant_serialiser_needed_size(). * * The data field of @serialised must be a pointer to a properly-aligned - * memory region large enough to serialise into (ie: at least as big as + * memory region large enough to serialize into (ie: at least as big as * the size field). * - * This function is only resonsible for serialising the top-level + * This function is only resonsible for serializing the top-level * container. @gvs_filler is called on each child of the container in * order for all of the data of that child to be filled in. */ @@ -1457,12 +1457,12 @@ g_variant_serialiser_serialise (GVariantSerialised serialised, /* < private > * g_variant_serialiser_needed_size: - * @type_info: the type to serialise for + * @type_info: the type to serialize for * @gvs_filler: the filler function * @children: an array of child items * @n_children: the size of @children * - * Determines how much memory would be needed to serialise this value. + * Determines how much memory would be needed to serialize this value. * * This function is only resonsible for performing calculations for the * top-level container. @gvs_filler is called on each child of the @@ -1489,7 +1489,7 @@ g_variant_serialiser_needed_size (GVariantTypeInfo *type_info, * g_variant_serialised_byteswap: * @value: a #GVariantSerialised * - * Byte-swap serialised data. The result of this function is only + * Byte-swap serialized data. The result of this function is only * well-defined if the data is in normal form. */ void @@ -1577,9 +1577,9 @@ g_variant_serialised_byteswap (GVariantSerialised serialised) * @serialised: a #GVariantSerialised * * Determines, recursively if @serialised is in normal form. There is - * precisely one normal form of serialised data for each possible value. + * precisely one normal form of serialized data for each possible value. * - * It is possible that multiple byte sequences form the serialised data + * It is possible that multiple byte sequences form the serialized data * for a given value if, for example, the padding bytes are filled in * with something other than zeros, but only one form is the normal * form. diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h index 81343e9ca..859cb7bfe 100644 --- a/glib/gvariant-serialiser.h +++ b/glib/gvariant-serialiser.h @@ -31,14 +31,14 @@ typedef struct gsize depth; /* same semantics as GVariant.depth */ } GVariantSerialised; -/* deserialisation */ +/* deserialization */ GLIB_AVAILABLE_IN_ALL gsize g_variant_serialised_n_children (GVariantSerialised container); GLIB_AVAILABLE_IN_ALL GVariantSerialised g_variant_serialised_get_child (GVariantSerialised container, gsize index); -/* serialisation */ +/* serialization */ typedef void (*GVariantSerialisedFiller) (GVariantSerialised *serialised, gpointer data); diff --git a/glib/gvariant.c b/glib/gvariant.c index e48dec1ad..a9bb99c64 100644 --- a/glib/gvariant.c +++ b/glib/gvariant.c @@ -84,19 +84,19 @@ * concurrently accessed in any way from any number of threads without * problems. * - * #GVariant is heavily optimised for dealing with data in serialised + * #GVariant is heavily optimised for dealing with data in serialized * form. It works particularly well with data located in memory-mapped - * files. It can perform nearly all deserialisation operations in a + * files. It can perform nearly all deserialization operations in a * small constant time, usually touching only a single memory page. - * Serialised #GVariant data can also be sent over the network. + * Serialized #GVariant data can also be sent over the network. * * #GVariant is largely compatible with D-Bus. Almost all types of * #GVariant instances can be sent over D-Bus. See #GVariantType for - * exceptions. (However, #GVariant's serialisation format is not the same - * as the serialisation format of a D-Bus message body: use #GDBusMessage, + * exceptions. (However, #GVariant's serialization format is not the same + * as the serialization format of a D-Bus message body: use #GDBusMessage, * in the gio library, for those.) * - * For space-efficiency, the #GVariant serialisation format does not + * For space-efficiency, the #GVariant serialization format does not * automatically include the variant's length, type or endianness, * which must either be implied from context (such as knowledge that a * particular file format always contains a little-endian @@ -126,14 +126,14 @@ * in the future. * * The memory allocated by #GVariant can be grouped into 4 broad - * purposes: memory for serialised data, memory for the type + * purposes: memory for serialized data, memory for the type * information cache, buffer management memory and memory for the * #GVariant structure itself. * - * ## Serialised Data Memory + * ## Serialized Data Memory * * This is the memory that is used for storing GVariant data in - * serialised form. This is what would be sent over the network or + * serialized form. This is what would be sent over the network or * what would end up on disk, not counting any indicator of the * endianness, or of the length or type of the top-level variant. * @@ -167,7 +167,7 @@ * * As an example, consider a dictionary mapping strings to variants. * In the case that the dictionary is empty, 0 bytes are required for - * the serialisation. + * the serialization. * * If we add an item "width" that maps to the int32 value of 500 then * we will use 4 byte to store the int32 (so 6 for the variant @@ -193,7 +193,7 @@ * * For each GVariant type that currently exists in the program a type * information structure is kept in the type information cache. The - * type information structure is required for rapid deserialisation. + * type information structure is required for rapid deserialization. * * Continuing with the above example, if a #GVariant exists with the * type "a{sv}" then a type information struct will exist for @@ -238,14 +238,14 @@ * ## Buffer Management Memory * * #GVariant uses an internal buffer management structure to deal - * with the various different possible sources of serialised data + * with the various different possible sources of serialized data * that it uses. The buffer is responsible for ensuring that the * correct call is made when the data is no longer in use by * #GVariant. This may involve a g_free() or a g_slice_free() or * even g_mapped_file_unref(). * * One buffer management structure is used for each chunk of - * serialised data. The size of the buffer management structure + * serialized data. The size of the buffer management structure * is 4 * (void *). On 32-bit systems, that's 16 bytes. * * ## GVariant structure @@ -255,7 +255,7 @@ * * #GVariant structures only exist if they are explicitly created * with API calls. For example, if a #GVariant is constructed out of - * serialised data for the example given above (with the dictionary) + * serialized data for the example given above (with the dictionary) * then although there are 9 individual values that comprise the * entire dictionary (two keys, two values, two variants containing * the values, two dictionary entries, plus the dictionary itself), @@ -265,8 +265,8 @@ * If calls are made to start accessing the other values then * #GVariant instances will exist for those values only for as long * as they are in use (ie: until you call g_variant_unref()). The - * type information is shared. The serialised data and the buffer - * management structure for that serialised data is shared by the + * type information is shared. The serialized data and the buffer + * management structure for that serialized data is shared by the * child. * * ## Summary @@ -274,12 +274,12 @@ * To put the entire example together, for our dictionary mapping * strings to variants (with two entries, as given above), we are * using 91 bytes of memory for type information, 29 bytes of memory - * for the serialised data, 16 bytes for buffer management and 24 + * for the serialized data, 16 bytes for buffer management and 24 * bytes for the #GVariant instance, or a total of 160 bytes, plus * malloc overhead. If we were to use g_variant_get_child_value() to * access the two dictionary entries, we would use an additional 48 * bytes. If we were to have other dictionaries of the same type, we - * would use more memory for the serialised data and buffer + * would use more memory for the serialized data and buffer * management for those dictionaries, but the type information would * be shared. */ @@ -1095,7 +1095,7 @@ g_variant_lookup_value (GVariant *dictionary, * @n_elements: (out): a pointer to the location to store the number of items * @element_size: the size of each element * - * Provides access to the serialised data for an array of fixed-sized + * Provides access to the serialized data for an array of fixed-sized * items. * * @value must be an array with fixed-sized elements. Numeric types are @@ -1103,7 +1103,7 @@ g_variant_lookup_value (GVariant *dictionary, * * @element_size must be the size of a single element in the array, * as given by the section on - * [serialized data memory][gvariant-serialised-data-memory]. + * [serialized data memory][gvariant-serialized-data-memory]. * * In particular, arrays of these fixed-sized types can be interpreted * as an array of the given C type, with @element_size set to the size @@ -1116,7 +1116,7 @@ g_variant_lookup_value (GVariant *dictionary, * * For example, if calling this function for an array of 32-bit integers, * you might say `sizeof(gint32)`. This value isn't used except for the purpose - * of a double-check that the form of the serialised data matches the caller's + * of a double-check that the form of the serialized data matches the caller's * expectation. * * @n_elements, which must be non-%NULL, is set equal to the number of @@ -1191,7 +1191,7 @@ g_variant_get_fixed_array (GVariant *value, * @element_size must be the size of a single element in the array. * For example, if calling this function for an array of 32-bit integers, * you might say sizeof(gint32). This value isn't used except for the purpose - * of a double-check that the form of the serialised data matches the caller's + * of a double-check that the form of the serialized data matches the caller's * expectation. * * @n_elements must be the length of the @elements array. @@ -2745,8 +2745,8 @@ g_variant_equal (gconstpointer one, g_variant_get_type_info ((GVariant *) two)) return FALSE; - /* if both values are trusted to be in their canonical serialised form - * then a simple memcmp() of their serialised data will answer the + /* if both values are trusted to be in their canonical serialized form + * then a simple memcmp() of their serialized data will answer the * question. * * if not, then this might generate a false negative (since it is @@ -5793,7 +5793,7 @@ g_variant_iter_loop (GVariantIter *iter, return value != NULL; } -/* Serialised data {{{1 */ +/* Serialized data {{{1 */ static GVariant * g_variant_deep_copy (GVariant *value) { @@ -5882,7 +5882,7 @@ g_variant_deep_copy (GVariant *value) * #GVariant is created with the same value as @value. * * It makes sense to call this function if you've received #GVariant - * data from untrusted sources and you want to ensure your serialised + * data from untrusted sources and you want to ensure your serialized * output is definitely in normal form. * * If @value is already in normal form, a new reference will be returned @@ -5972,13 +5972,13 @@ g_variant_byteswap (GVariant *value) /** * g_variant_new_from_data: * @type: a definite #GVariantType - * @data: (array length=size) (element-type guint8): the serialised data + * @data: (array length=size) (element-type guint8): the serialized data * @size: the size of @data * @trusted: %TRUE if @data is definitely in normal form * @notify: (scope async): function to call when @data is no longer needed * @user_data: data for @notify * - * Creates a new #GVariant instance from serialised data. + * Creates a new #GVariant instance from serialized data. * * @type is the type of #GVariant instance that will be constructed. * The interpretation of @data depends on knowing the type. @@ -5988,8 +5988,8 @@ g_variant_byteswap (GVariant *value) * @user_data. If the contents of @data change before that time then * the result is undefined. * - * If @data is trusted to be serialised data in normal form then - * @trusted should be %TRUE. This applies to serialised data created + * If @data is trusted to be serialized data in normal form then + * @trusted should be %TRUE. This applies to serialized data created * within this process or read from a trusted location on the disk (such * as a file installed in /usr/lib alongside your application). You * should set trusted to %FALSE if @data is read from the network, a diff --git a/glib/gvarianttypeinfo.c b/glib/gvarianttypeinfo.c index 087294a09..6fdde8f8e 100644 --- a/glib/gvarianttypeinfo.c +++ b/glib/gvarianttypeinfo.c @@ -32,7 +32,7 @@ * GVariantTypeInfo: * * This structure contains the necessary information to facilitate the - * serialisation and fast deserialisation of a given type of GVariant + * serialization and fast deserialization of a given type of GVariant * value. A GVariant instance holds a pointer to one of these * structures to provide for efficient operation. * @@ -93,7 +93,7 @@ typedef struct } ArrayInfo; /* For 'tuple' and 'dict entry' types, we store extra information for - * each member -- its type and how to find it inside the serialised data + * each member -- its type and how to find it inside the serialized data * in O(1) time using 4 variables -- 'i', 'a', 'b', and 'c'. See the * comment on GVariantMemberInfo in gvarianttypeinfo.h. */ diff --git a/glib/gvarianttypeinfo.h b/glib/gvarianttypeinfo.h index 8663e2090..cff0dba6e 100644 --- a/glib/gvarianttypeinfo.h +++ b/glib/gvarianttypeinfo.h @@ -40,18 +40,18 @@ typedef struct _GVariantTypeInfo GVariantTypeInfo; * corresponding to a given child of a tuple or dictionary entry in a * very short constant time. It contains the typeinfo of the child, * along with 4 constants that allow the bounds of the child's - * serialised data within the container's serialised data to be found + * serialized data within the container's serialized data to be found * very efficiently. * - * Since dictionary entries are serialised as if they were tuples of 2 + * Since dictionary entries are serialized as if they were tuples of 2 * items, the term "tuple" will be used here in the general sense to * refer to tuples and dictionary entries. * * BACKGROUND: - * The serialised data for a tuple contains an array of "offsets" at + * The serialized data for a tuple contains an array of "offsets" at * the end. There is one "offset" in this array for each * variable-sized item in the tuple (except for the last one). The - * offset points to the end point of that item's serialised data. The + * offset points to the end point of that item's serialized data. The * procedure for finding the start point is described below. An * offset is not needed for the last item because the end point of the * last item is merely the end point of the container itself (after diff --git a/glib/gversionmacros.h b/glib/gversionmacros.h index 77486eafb..d052709cf 100644 --- a/glib/gversionmacros.h +++ b/glib/gversionmacros.h @@ -256,6 +256,16 @@ #define GLIB_VERSION_2_68 (G_ENCODE_VERSION (2, 68)) /** + * GLIB_VERSION_2_70: + * + * A macro that evaluates to the 2.70 version of GLib, in a format + * that can be used by the C pre-processor. + * + * Since: 2.70 + */ +#define GLIB_VERSION_2_70 (G_ENCODE_VERSION (2, 70)) + +/** * GLIB_VERSION_CUR_STABLE: * * A macro that evaluates to the current stable version of GLib, in a format @@ -1076,4 +1086,38 @@ # define GLIB_AVAILABLE_TYPE_IN_2_68 #endif +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_70 +# define GLIB_DEPRECATED_IN_2_70 GLIB_DEPRECATED +# define GLIB_DEPRECATED_IN_2_70_FOR(f) GLIB_DEPRECATED_FOR(f) +# define GLIB_DEPRECATED_MACRO_IN_2_70 GLIB_DEPRECATED_MACRO +# define GLIB_DEPRECATED_MACRO_IN_2_70_FOR(f) GLIB_DEPRECATED_MACRO_FOR(f) +# define GLIB_DEPRECATED_ENUMERATOR_IN_2_70 GLIB_DEPRECATED_ENUMERATOR +# define GLIB_DEPRECATED_ENUMERATOR_IN_2_70_FOR(f) GLIB_DEPRECATED_ENUMERATOR_FOR(f) +# define GLIB_DEPRECATED_TYPE_IN_2_70 GLIB_DEPRECATED_TYPE +# define GLIB_DEPRECATED_TYPE_IN_2_70_FOR(f) GLIB_DEPRECATED_TYPE_FOR(f) +#else +# define GLIB_DEPRECATED_IN_2_70 _GLIB_EXTERN +# define GLIB_DEPRECATED_IN_2_70_FOR(f) _GLIB_EXTERN +# define GLIB_DEPRECATED_MACRO_IN_2_70 +# define GLIB_DEPRECATED_MACRO_IN_2_70_FOR(f) +# define GLIB_DEPRECATED_ENUMERATOR_IN_2_70 +# define GLIB_DEPRECATED_ENUMERATOR_IN_2_70_FOR(f) +# define GLIB_DEPRECATED_TYPE_IN_2_70 +# define GLIB_DEPRECATED_TYPE_IN_2_70_FOR(f) +#endif + +#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_70 +# define GLIB_AVAILABLE_IN_2_70 GLIB_UNAVAILABLE(2, 70) +# define GLIB_AVAILABLE_STATIC_INLINE_IN_2_70 GLIB_UNAVAILABLE_STATIC_INLINE(2, 70) +# define GLIB_AVAILABLE_MACRO_IN_2_70 GLIB_UNAVAILABLE_MACRO(2, 70) +# define GLIB_AVAILABLE_ENUMERATOR_IN_2_70 GLIB_UNAVAILABLE_ENUMERATOR(2, 70) +# define GLIB_AVAILABLE_TYPE_IN_2_70 GLIB_UNAVAILABLE_TYPE(2, 70) +#else +# define GLIB_AVAILABLE_IN_2_70 _GLIB_EXTERN +# define GLIB_AVAILABLE_STATIC_INLINE_IN_2_70 +# define GLIB_AVAILABLE_MACRO_IN_2_70 +# define GLIB_AVAILABLE_ENUMERATOR_IN_2_70 +# define GLIB_AVAILABLE_TYPE_IN_2_70 +#endif + #endif /* __G_VERSION_MACROS_H__ */ diff --git a/glib/gwin32-private.c b/glib/gwin32-private.c index f7913b553..c28e92baa 100644 --- a/glib/gwin32-private.c +++ b/glib/gwin32-private.c @@ -18,16 +18,16 @@ /* Copy @cmdline into @debugger, and substitute @pid for `%p` * and @event for `%e`. - * If @debugger_size (in bytes) is overflowed, return %FALSE. + * If @debugger_size (in wchar_ts) is overflowed, return %FALSE. * Also returns %FALSE when `%` is followed by anything other * than `e` or `p`. */ static gboolean -_g_win32_subst_pid_and_event (char *debugger, - gsize debugger_size, - const char *cmdline, - DWORD pid, - guintptr event) +_g_win32_subst_pid_and_event_w (wchar_t *debugger, + gsize debugger_size, + const wchar_t *cmdline, + DWORD pid, + guintptr event) { gsize i = 0, dbg_i = 0; /* These are integers, and they can't be longer than 20 characters @@ -35,31 +35,31 @@ _g_win32_subst_pid_and_event (char *debugger, * Use 30 just to be sure. */ #define STR_BUFFER_SIZE 30 - char pid_str[STR_BUFFER_SIZE] = {0}; + wchar_t pid_str[STR_BUFFER_SIZE] = {0}; gsize pid_str_len; - char event_str[STR_BUFFER_SIZE] = {0}; + wchar_t event_str[STR_BUFFER_SIZE] = {0}; gsize event_str_len; - _snprintf_s (pid_str, STR_BUFFER_SIZE, G_N_ELEMENTS (pid_str), "%lu", pid); + _snwprintf_s (pid_str, STR_BUFFER_SIZE, G_N_ELEMENTS (pid_str), L"%lu", pid); pid_str[G_N_ELEMENTS (pid_str) - 1] = 0; - pid_str_len = strlen (pid_str); - _snprintf_s (event_str, STR_BUFFER_SIZE, G_N_ELEMENTS (pid_str), "%Iu", event); + pid_str_len = wcslen (pid_str); + _snwprintf_s (event_str, STR_BUFFER_SIZE, G_N_ELEMENTS (pid_str), L"%Iu", event); event_str[G_N_ELEMENTS (pid_str) - 1] = 0; - event_str_len = strlen (event_str); + event_str_len = wcslen (event_str); #undef STR_BUFFER_SIZE while (cmdline[i] != 0 && dbg_i < debugger_size) { - if (cmdline[i] != '%') + if (cmdline[i] != L'%') debugger[dbg_i++] = cmdline[i++]; - else if (cmdline[i + 1] == 'p') + else if (cmdline[i + 1] == L'p') { gsize j = 0; while (j < pid_str_len && dbg_i < debugger_size) debugger[dbg_i++] = pid_str[j++]; i += 2; } - else if (cmdline[i + 1] == 'e') + else if (cmdline[i + 1] == L'e') { gsize j = 0; while (j < event_str_len && dbg_i < debugger_size) diff --git a/glib/gwin32.c b/glib/gwin32.c index b62f19461..f4590916f 100644 --- a/glib/gwin32.c +++ b/glib/gwin32.c @@ -1035,10 +1035,32 @@ g_console_win32_init (void) * it will be non-NULL. Only used to later de-install the handler * on library de-initialization. */ -static void *WinVEH_handle = NULL; +static void *WinVEH_handle = NULL; + +#define DEBUGGER_BUFFER_SIZE (MAX_PATH + 1) +/* This is the debugger that we'll run on crash */ +static wchar_t debugger[DEBUGGER_BUFFER_SIZE]; + +static gsize number_of_exceptions_to_catch = 0; +static DWORD *exceptions_to_catch = NULL; + +static HANDLE debugger_wakeup_event = 0; +static DWORD debugger_spawn_flags = 0; #include "gwin32-private.c" +static char * +copy_chars (char *buffer, + gsize *buffer_size, + const char *to_copy) +{ + gsize copy_count = MIN (strlen (to_copy), *buffer_size - 1); + memset (buffer, 0x20, copy_count); + strncpy_s (buffer, *buffer_size, to_copy, _TRUNCATE); + *buffer_size -= copy_count; + return &buffer[copy_count]; +} + /* Handles exceptions (useful for debugging). * Issues a DebugBreak() call if the process is being debugged (not really * useful - if the process is being debugged, this handler won't be invoked @@ -1068,24 +1090,31 @@ static void *WinVEH_handle = NULL; * or for control flow. * * This function deliberately avoids calling any GLib code. + * This is done on purpose. This function can be called when the program + * is in a bad state (crashing). It can also be called very early, as soon + * as the handler is installed. Therefore, it's imperative that + * it does as little as possible. Preferably, all the work that can be + * done in advance (when the program is not crashing yet) should be done + * in advance. */ static LONG __stdcall g_win32_veh_handler (PEXCEPTION_POINTERS ExceptionInfo) { EXCEPTION_RECORD *er; - char debugger[MAX_PATH + 1]; - WCHAR *debugger_utf16; - const char *debugger_env = NULL; - const char *catch_list; - gboolean catch = FALSE; + gsize i; STARTUPINFOW si; PROCESS_INFORMATION pi; - HANDLE event; - SECURITY_ATTRIBUTES sa; +#define ITOA_BUFFER_SIZE 100 + char itoa_buffer[ITOA_BUFFER_SIZE]; +#define DEBUG_STRING_SIZE 1024 + gsize dbgs = DEBUG_STRING_SIZE; + char debug_string[DEBUG_STRING_SIZE]; + char *dbgp; if (ExceptionInfo == NULL || ExceptionInfo->ExceptionRecord == NULL || - IsDebuggerPresent ()) + IsDebuggerPresent () || + debugger[0] == 0) return EXCEPTION_CONTINUE_SEARCH; er = ExceptionInfo->ExceptionRecord; @@ -1097,102 +1126,22 @@ g_win32_veh_handler (PEXCEPTION_POINTERS ExceptionInfo) case EXCEPTION_ILLEGAL_INSTRUCTION: break; default: - catch_list = g_getenv ("G_VEH_CATCH"); + for (i = 0; i < number_of_exceptions_to_catch; i++) + if (exceptions_to_catch[i] == er->ExceptionCode) + break; - while (!catch && - catch_list != NULL && - catch_list[0] != 0) - { - unsigned long catch_code; - char *end; - errno = 0; - catch_code = strtoul (catch_list, &end, 16); - if (errno != NO_ERROR) - break; - catch_list = end; - if (catch_list != NULL && catch_list[0] == ',') - catch_list++; - if (catch_code == er->ExceptionCode) - catch = TRUE; - } - - if (catch) - break; + if (i == number_of_exceptions_to_catch) + return EXCEPTION_CONTINUE_SEARCH; - return EXCEPTION_CONTINUE_SEARCH; - } - - fprintf_s (stderr, - "Exception code=0x%lx flags=0x%lx at 0x%p", - er->ExceptionCode, - er->ExceptionFlags, - er->ExceptionAddress); - - switch (er->ExceptionCode) - { - case EXCEPTION_ACCESS_VIOLATION: - fprintf_s (stderr, - ". Access violation - attempting to %s at address 0x%p\n", - er->ExceptionInformation[0] == 0 ? "read data" : - er->ExceptionInformation[0] == 1 ? "write data" : - er->ExceptionInformation[0] == 8 ? "execute data" : - "do something bad", - (void *) er->ExceptionInformation[1]); - break; - case EXCEPTION_IN_PAGE_ERROR: - fprintf_s (stderr, - ". Page access violation - attempting to %s at address 0x%p with status %Ix\n", - er->ExceptionInformation[0] == 0 ? "read from an inaccessible page" : - er->ExceptionInformation[0] == 1 ? "write to an inaccessible page" : - er->ExceptionInformation[0] == 8 ? "execute data in page" : - "do something bad with a page", - (void *) er->ExceptionInformation[1], - er->ExceptionInformation[2]); - break; - default: - fprintf_s (stderr, "\n"); break; } - fflush (stderr); - - debugger_env = g_getenv ("G_DEBUGGER"); - - if (debugger_env == NULL) - return EXCEPTION_CONTINUE_SEARCH; - - /* Create an inheritable event */ memset (&si, 0, sizeof (si)); memset (&pi, 0, sizeof (pi)); - memset (&sa, 0, sizeof (sa)); si.cb = sizeof (si); - sa.nLength = sizeof (sa); - sa.bInheritHandle = TRUE; - event = CreateEvent (&sa, FALSE, FALSE, NULL); - - /* Put process ID and event handle into debugger commandline */ - if (!_g_win32_subst_pid_and_event (debugger, G_N_ELEMENTS (debugger), - debugger_env, GetCurrentProcessId (), - (guintptr) event)) - { - CloseHandle (event); - return EXCEPTION_CONTINUE_SEARCH; - } - debugger[MAX_PATH] = '\0'; - - debugger_utf16 = g_utf8_to_utf16 (debugger, -1, NULL, NULL, NULL); /* Run the debugger */ - if (0 != CreateProcessW (NULL, - debugger_utf16, - NULL, - NULL, - TRUE, - g_getenv ("G_DEBUGGER_OLD_CONSOLE") != NULL ? 0 : CREATE_NEW_CONSOLE, - NULL, - NULL, - &si, - &pi)) + if (0 != CreateProcessW (NULL, debugger, NULL, NULL, TRUE, debugger_spawn_flags, NULL, NULL, &si, &pi)) { CloseHandle (pi.hProcess); CloseHandle (pi.hThread); @@ -1202,12 +1151,66 @@ g_win32_veh_handler (PEXCEPTION_POINTERS ExceptionInfo) * up forever in case the debugger does not support * event signalling. */ - WaitForSingleObject (event, 60000); - } - - g_free (debugger_utf16); + WaitForSingleObject (debugger_wakeup_event, 60000); + + dbgp = &debug_string[0]; + + dbgp = copy_chars (dbgp, &dbgs, "Exception code=0x"); + itoa_buffer[0] = 0; + _ui64toa_s (er->ExceptionCode, itoa_buffer, ITOA_BUFFER_SIZE, 16); + dbgp = copy_chars (dbgp, &dbgs, itoa_buffer); + dbgp = copy_chars (dbgp, &dbgs, " flags=0x"); + itoa_buffer[0] = 0; + _ui64toa_s (er->ExceptionFlags, itoa_buffer, ITOA_BUFFER_SIZE, 16); + dbgp = copy_chars (dbgp, &dbgs, itoa_buffer); + dbgp = copy_chars (dbgp, &dbgs, " at 0x"); + itoa_buffer[0] = 0; + _ui64toa_s ((guintptr) er->ExceptionAddress, itoa_buffer, ITOA_BUFFER_SIZE, 16); + dbgp = copy_chars (dbgp, &dbgs, itoa_buffer); + + switch (er->ExceptionCode) + { + case EXCEPTION_ACCESS_VIOLATION: + dbgp = copy_chars (dbgp, &dbgs, ". Access violation - attempting to "); + if (er->ExceptionInformation[0] == 0) + dbgp = copy_chars (dbgp, &dbgs, "read data"); + else if (er->ExceptionInformation[0] == 1) + dbgp = copy_chars (dbgp, &dbgs, "write data"); + else if (er->ExceptionInformation[0] == 8) + dbgp = copy_chars (dbgp, &dbgs, "execute data"); + else + dbgp = copy_chars (dbgp, &dbgs, "do something bad"); + dbgp = copy_chars (dbgp, &dbgs, " at address 0x"); + itoa_buffer[0] = 0; + _ui64toa_s (er->ExceptionInformation[1], itoa_buffer, ITOA_BUFFER_SIZE, 16); + dbgp = copy_chars (dbgp, &dbgs, itoa_buffer); + break; + case EXCEPTION_IN_PAGE_ERROR: + dbgp = copy_chars (dbgp, &dbgs, ". Page access violation - attempting to "); + if (er->ExceptionInformation[0] == 0) + dbgp = copy_chars (dbgp, &dbgs, "read from an inaccessible page"); + else if (er->ExceptionInformation[0] == 1) + dbgp = copy_chars (dbgp, &dbgs, "write to an inaccessible page"); + else if (er->ExceptionInformation[0] == 8) + dbgp = copy_chars (dbgp, &dbgs, "execute data in page"); + else + dbgp = copy_chars (dbgp, &dbgs, "do something bad with a page"); + dbgp = copy_chars (dbgp, &dbgs, " at address 0x"); + itoa_buffer[0] = 0; + _ui64toa_s (er->ExceptionInformation[1], itoa_buffer, ITOA_BUFFER_SIZE, 16); + dbgp = copy_chars (dbgp, &dbgs, itoa_buffer); + dbgp = copy_chars (dbgp, &dbgs, " with status "); + itoa_buffer[0] = 0; + _ui64toa_s (er->ExceptionInformation[2], itoa_buffer, ITOA_BUFFER_SIZE, 16); + dbgp = copy_chars (dbgp, &dbgs, itoa_buffer); + break; + default: + break; + } - CloseHandle (event); + dbgp = copy_chars (dbgp, &dbgs, "\n"); + OutputDebugStringA (debug_string); + } /* Now the debugger is present, and we can try * resuming execution, re-triggering the exception, @@ -1219,20 +1222,88 @@ g_win32_veh_handler (PEXCEPTION_POINTERS ExceptionInfo) return EXCEPTION_CONTINUE_SEARCH; } +static gsize +parse_catch_list (const wchar_t *catch_buffer, + DWORD *exceptions, + gsize num_exceptions) +{ + const wchar_t *catch_list = catch_buffer; + gsize result = 0; + gsize i = 0; + + while (catch_list != NULL && + catch_list[0] != 0) + { + unsigned long catch_code; + wchar_t *end; + errno = 0; + catch_code = wcstoul (catch_list, &end, 16); + if (errno != NO_ERROR) + break; + catch_list = end; + if (catch_list != NULL && catch_list[0] == L',') + catch_list++; + if (exceptions && i < num_exceptions) + exceptions[i++] = catch_code; + } + + return result; +} + void g_crash_handler_win32_init (void) { + wchar_t debugger_env[DEBUGGER_BUFFER_SIZE]; +#define CATCH_BUFFER_SIZE 1024 + wchar_t catch_buffer[CATCH_BUFFER_SIZE]; + SECURITY_ATTRIBUTES sa; + if (WinVEH_handle != NULL) return; /* Do not register an exception handler if we're not supposed to catch any * exceptions. Exception handlers are considered dangerous to use, and can * break advanced exception handling such as in CLRs like C# or other managed - * code. See: https://blogs.msdn.microsoft.com/jmstall/2006/05/24/beware-of-the-vectored-exception-handler-and-managed-code/ + * code. See: http://www.windows-tech.info/13/785f590867bd6316.php */ - if (g_getenv ("G_DEBUGGER") == NULL && g_getenv("G_VEH_CATCH") == NULL) + debugger_env[0] = 0; + if (!GetEnvironmentVariableW (L"G_DEBUGGER", debugger_env, DEBUGGER_BUFFER_SIZE)) return; + /* Create an inheritable event */ + memset (&sa, 0, sizeof (sa)); + sa.nLength = sizeof (sa); + sa.bInheritHandle = TRUE; + debugger_wakeup_event = CreateEvent (&sa, FALSE, FALSE, NULL); + + /* Put process ID and event handle into debugger commandline */ + if (!_g_win32_subst_pid_and_event_w (debugger, G_N_ELEMENTS (debugger), + debugger_env, GetCurrentProcessId (), + (guintptr) debugger_wakeup_event)) + { + CloseHandle (debugger_wakeup_event); + debugger_wakeup_event = 0; + debugger[0] = 0; + return; + } + debugger[MAX_PATH] = L'\0'; + + catch_buffer[0] = 0; + if (GetEnvironmentVariableW (L"G_VEH_CATCH", catch_buffer, CATCH_BUFFER_SIZE)) + { + number_of_exceptions_to_catch = parse_catch_list (catch_buffer, NULL, 0); + if (number_of_exceptions_to_catch > 0) + { + exceptions_to_catch = g_new0 (DWORD, number_of_exceptions_to_catch); + parse_catch_list (catch_buffer, exceptions_to_catch, number_of_exceptions_to_catch); + } + } + + if (GetEnvironmentVariableW (L"G_DEBUGGER_OLD_CONSOLE", (wchar_t *) &debugger_spawn_flags, 1)) + debugger_spawn_flags = 0; + else + debugger_spawn_flags = CREATE_NEW_CONSOLE; + WinVEH_handle = AddVectoredExceptionHandler (0, &g_win32_veh_handler); } diff --git a/glib/meson.build b/glib/meson.build index 8c18e6de4..93600b29e 100644 --- a/glib/meson.build +++ b/glib/meson.build @@ -3,9 +3,6 @@ configure_file(input : 'glibconfig.h.in', output : 'glibconfig.h', configuration : glibconfig_conf) subdir('libcharset') -if not use_system_pcre - subdir('pcre') -endif # libsysprof-capture support libsysprof_capture_dep = dependency('sysprof-capture-4', version: '>= 3.38.0', @@ -23,7 +20,7 @@ libsysprof_capture_dep = dependency('sysprof-capture-4', version: '>= 3.38.0', ) glib_conf.set('HAVE_SYSPROF', libsysprof_capture_dep.found()) -# TODO: gnulib_objects, pcre_objects and pcre_deps are a workaround for +# TODO: gnulib_objects is a workaround for # <https://github.com/mesonbuild/meson/issues/3934> and # <https://github.com/mesonbuild/meson/issues/3937>. When we can depend # on a meson version where those are fixed, revert the commit that @@ -142,6 +139,7 @@ install_headers(glib_deprecated_headers, subdir : 'glib-2.0/glib/deprecated') glib_sub_headers = files( 'glib-autocleanups.h', + 'glib-typeof.h', 'galloca.h', 'garray.h', 'gasyncqueue.h', @@ -357,19 +355,11 @@ if use_pcre_static_flag pcre_static_args = ['-DPCRE_STATIC'] endif -if use_system_pcre - pcre_deps = [pcre] - pcre_objects = [] -else - pcre_deps = [] - pcre_objects = [libpcre.extract_all_objects()] -endif - glib_c_args = ['-DG_LOG_DOMAIN="GLib"', '-DGLIB_COMPILATION'] + pcre_static_args + glib_hidden_visibility_args libglib = library('glib-2.0', glib_dtrace_obj, glib_dtrace_hdr, sources : [deprecated_sources, glib_sources], - objects : [charset_lib.extract_all_objects()] + gnulib_objects + pcre_objects, + objects : [charset_lib.extract_all_objects()] + gnulib_objects, version : library_version, soversion : soversion, darwin_versions : darwin_versions, @@ -377,7 +367,7 @@ libglib = library('glib-2.0', # intl.lib is not compatible with SAFESEH link_args : [noseh_link_args, glib_link_flags, win32_ldflags], include_directories : configinc, - dependencies : pcre_deps + [thread_dep, librt] + libintl_deps + libiconv + platform_deps + [gnulib_libm_dependency, libm] + [libsysprof_capture_dep], + dependencies : [pcre, thread_dep, librt] + libintl_deps + libiconv + platform_deps + [gnulib_libm_dependency, libm] + [libsysprof_capture_dep], c_args : glib_c_args, objc_args : glib_c_args, ) diff --git a/glib/pcre/COPYING b/glib/pcre/COPYING deleted file mode 100644 index 58eed01b6..000000000 --- a/glib/pcre/COPYING +++ /dev/null @@ -1,5 +0,0 @@ -PCRE LICENCE - -Please see the file LICENCE in the PCRE distribution for licensing details. - -End diff --git a/glib/pcre/meson.build b/glib/pcre/meson.build deleted file mode 100644 index 5152ecd60..000000000 --- a/glib/pcre/meson.build +++ /dev/null @@ -1,50 +0,0 @@ -pcre_sources = [ - 'pcre_byte_order.c', - 'pcre_chartables.c', - 'pcre_compile.c', - 'pcre_config.c', - 'pcre_dfa_exec.c', - 'pcre_exec.c', - 'pcre_fullinfo.c', - 'pcre_get.c', - 'pcre_globals.c', - 'pcre_jit_compile.c', - 'pcre_newline.c', - 'pcre_ord2utf8.c', - 'pcre_string_utils.c', - 'pcre_study.c', - 'pcre_tables.c', - 'pcre_valid_utf8.c', - 'pcre_version.c', - 'pcre_xclass.c', - 'pcre.h', - 'pcre_internal.h', - 'ucp.h', -] - -libpcre = static_library('pcre', - sources : [pcre_sources], - include_directories : [configinc, glibinc], - pic : true, - c_args : [ - '-DG_LOG_DOMAIN="GLib-GRegex"', - '-DHAVE_MEMMOVE', - '-DSUPPORT_UCP', - '-DSUPPORT_UTF', - '-DSUPPORT_UTF8', - '-DNEWLINE=-1', - '-DMATCH_LIMIT=10000000', - '-DMATCH_LIMIT_RECURSION=8192', - '-DMAX_NAME_SIZE=32', - '-DMAX_NAME_COUNT=10000', - '-DMAX_DUPLENGTH=30000', - '-DLINK_SIZE=2', - '-DPOSIX_MALLOC_THRESHOLD=10', - '-DPCRE_STATIC', - '-UBSR_ANYCRLF', - '-UEBCDIC', - '-DGLIB_COMPILATION' - ] + glib_hidden_visibility_args -) - -pcre = declare_dependency(link_with : libpcre) diff --git a/glib/pcre/pcre.h b/glib/pcre/pcre.h deleted file mode 100644 index b71ead37a..000000000 --- a/glib/pcre/pcre.h +++ /dev/null @@ -1,507 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* This is the public header file for the PCRE library, to be #included by -applications that call the PCRE functions. - - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - -#ifndef _PCRE_H -#define _PCRE_H - -/* The current PCRE version information. */ - -#define PCRE_MAJOR 8 -#define PCRE_MINOR 31 -#define PCRE_PRERELEASE -#define PCRE_DATE 2012-07-06 - -/* When an application links to a PCRE DLL in Windows, the symbols that are -imported have to be identified as such. When building PCRE, the appropriate -export setting is defined in pcre_internal.h, which includes this file. So we -don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */ - -#if defined(_WIN32) && !defined(PCRE_STATIC) -# ifndef PCRE_EXP_DECL -# define PCRE_EXP_DECL extern __declspec(dllimport) -# endif -# ifdef __cplusplus -# ifndef PCRECPP_EXP_DECL -# define PCRECPP_EXP_DECL extern __declspec(dllimport) -# endif -# ifndef PCRECPP_EXP_DEFN -# define PCRECPP_EXP_DEFN __declspec(dllimport) -# endif -# endif -#endif - -/* By default, we use the standard "extern" declarations. */ - -#ifndef PCRE_EXP_DECL -# ifdef __cplusplus -# define PCRE_EXP_DECL extern "C" -# else -# define PCRE_EXP_DECL extern -# endif -#endif - -#ifdef __cplusplus -# ifndef PCRECPP_EXP_DECL -# define PCRECPP_EXP_DECL extern -# endif -# ifndef PCRECPP_EXP_DEFN -# define PCRECPP_EXP_DEFN -# endif -#endif - -/* Have to include stdlib.h in order to ensure that size_t is defined; -it is needed here for malloc. */ - -#include <stdlib.h> - -/* Allow for C++ users */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Options. Some are compile-time only, some are run-time only, and some are -both, so we keep them all distinct. However, almost all the bits in the options -word are now used. In the long run, we may have to re-use some of the -compile-time only bits for runtime options, or vice versa. In the comments -below, "compile", "exec", and "DFA exec" mean that the option is permitted to -be set for those functions; "used in" means that an option may be set only for -compile, but is subsequently referenced in exec and/or DFA exec. Any of the -compile-time options may be inspected during studying (and therefore JIT -compiling). */ - -#define PCRE_CASELESS 0x00000001 /* Compile */ -#define PCRE_MULTILINE 0x00000002 /* Compile */ -#define PCRE_DOTALL 0x00000004 /* Compile */ -#define PCRE_EXTENDED 0x00000008 /* Compile */ -#define PCRE_ANCHORED 0x00000010 /* Compile, exec, DFA exec */ -#define PCRE_DOLLAR_ENDONLY 0x00000020 /* Compile, used in exec, DFA exec */ -#define PCRE_EXTRA 0x00000040 /* Compile */ -#define PCRE_NOTBOL 0x00000080 /* Exec, DFA exec */ -#define PCRE_NOTEOL 0x00000100 /* Exec, DFA exec */ -#define PCRE_UNGREEDY 0x00000200 /* Compile */ -#define PCRE_NOTEMPTY 0x00000400 /* Exec, DFA exec */ -/* The next two are also used in exec and DFA exec */ -#define PCRE_UTF8 0x00000800 /* Compile (same as PCRE_UTF16) */ -#define PCRE_UTF16 0x00000800 /* Compile (same as PCRE_UTF8) */ -#define PCRE_NO_AUTO_CAPTURE 0x00001000 /* Compile */ -/* The next two are also used in exec and DFA exec */ -#define PCRE_NO_UTF8_CHECK 0x00002000 /* Compile (same as PCRE_NO_UTF16_CHECK) */ -#define PCRE_NO_UTF16_CHECK 0x00002000 /* Compile (same as PCRE_NO_UTF8_CHECK) */ -#define PCRE_AUTO_CALLOUT 0x00004000 /* Compile */ -#define PCRE_PARTIAL_SOFT 0x00008000 /* Exec, DFA exec */ -#define PCRE_PARTIAL 0x00008000 /* Backwards compatible synonym */ -#define PCRE_DFA_SHORTEST 0x00010000 /* DFA exec */ -#define PCRE_DFA_RESTART 0x00020000 /* DFA exec */ -#define PCRE_FIRSTLINE 0x00040000 /* Compile, used in exec, DFA exec */ -#define PCRE_DUPNAMES 0x00080000 /* Compile */ -#define PCRE_NEWLINE_CR 0x00100000 /* Compile, exec, DFA exec */ -#define PCRE_NEWLINE_LF 0x00200000 /* Compile, exec, DFA exec */ -#define PCRE_NEWLINE_CRLF 0x00300000 /* Compile, exec, DFA exec */ -#define PCRE_NEWLINE_ANY 0x00400000 /* Compile, exec, DFA exec */ -#define PCRE_NEWLINE_ANYCRLF 0x00500000 /* Compile, exec, DFA exec */ -#define PCRE_BSR_ANYCRLF 0x00800000 /* Compile, exec, DFA exec */ -#define PCRE_BSR_UNICODE 0x01000000 /* Compile, exec, DFA exec */ -#define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* Compile, used in exec */ -#define PCRE_NO_START_OPTIMIZE 0x04000000 /* Compile, exec, DFA exec */ -#define PCRE_NO_START_OPTIMISE 0x04000000 /* Synonym */ -#define PCRE_PARTIAL_HARD 0x08000000 /* Exec, DFA exec */ -#define PCRE_NOTEMPTY_ATSTART 0x10000000 /* Exec, DFA exec */ -#define PCRE_UCP 0x20000000 /* Compile, used in exec, DFA exec */ - -/* Exec-time and get/set-time error codes */ - -#define PCRE_ERROR_NOMATCH (-1) -#define PCRE_ERROR_NULL (-2) -#define PCRE_ERROR_BADOPTION (-3) -#define PCRE_ERROR_BADMAGIC (-4) -#define PCRE_ERROR_UNKNOWN_OPCODE (-5) -#define PCRE_ERROR_UNKNOWN_NODE (-5) /* For backward compatibility */ -#define PCRE_ERROR_NOMEMORY (-6) -#define PCRE_ERROR_NOSUBSTRING (-7) -#define PCRE_ERROR_MATCHLIMIT (-8) -#define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */ -#define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16 */ -#define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16 */ -#define PCRE_ERROR_BADUTF8_OFFSET (-11) /* Same for 8/16 */ -#define PCRE_ERROR_BADUTF16_OFFSET (-11) /* Same for 8/16 */ -#define PCRE_ERROR_PARTIAL (-12) -#define PCRE_ERROR_BADPARTIAL (-13) -#define PCRE_ERROR_INTERNAL (-14) -#define PCRE_ERROR_BADCOUNT (-15) -#define PCRE_ERROR_DFA_UITEM (-16) -#define PCRE_ERROR_DFA_UCOND (-17) -#define PCRE_ERROR_DFA_UMLIMIT (-18) -#define PCRE_ERROR_DFA_WSSIZE (-19) -#define PCRE_ERROR_DFA_RECURSE (-20) -#define PCRE_ERROR_RECURSIONLIMIT (-21) -#define PCRE_ERROR_NULLWSLIMIT (-22) /* No longer actually used */ -#define PCRE_ERROR_BADNEWLINE (-23) -#define PCRE_ERROR_BADOFFSET (-24) -#define PCRE_ERROR_SHORTUTF8 (-25) -#define PCRE_ERROR_SHORTUTF16 (-25) /* Same for 8/16 */ -#define PCRE_ERROR_RECURSELOOP (-26) -#define PCRE_ERROR_JIT_STACKLIMIT (-27) -#define PCRE_ERROR_BADMODE (-28) -#define PCRE_ERROR_BADENDIANNESS (-29) -#define PCRE_ERROR_DFA_BADRESTART (-30) - -/* Specific error codes for UTF-8 validity checks */ - -#define PCRE_UTF8_ERR0 0 -#define PCRE_UTF8_ERR1 1 -#define PCRE_UTF8_ERR2 2 -#define PCRE_UTF8_ERR3 3 -#define PCRE_UTF8_ERR4 4 -#define PCRE_UTF8_ERR5 5 -#define PCRE_UTF8_ERR6 6 -#define PCRE_UTF8_ERR7 7 -#define PCRE_UTF8_ERR8 8 -#define PCRE_UTF8_ERR9 9 -#define PCRE_UTF8_ERR10 10 -#define PCRE_UTF8_ERR11 11 -#define PCRE_UTF8_ERR12 12 -#define PCRE_UTF8_ERR13 13 -#define PCRE_UTF8_ERR14 14 -#define PCRE_UTF8_ERR15 15 -#define PCRE_UTF8_ERR16 16 -#define PCRE_UTF8_ERR17 17 -#define PCRE_UTF8_ERR18 18 -#define PCRE_UTF8_ERR19 19 -#define PCRE_UTF8_ERR20 20 -#define PCRE_UTF8_ERR21 21 - -/* Specific error codes for UTF-16 validity checks */ - -#define PCRE_UTF16_ERR0 0 -#define PCRE_UTF16_ERR1 1 -#define PCRE_UTF16_ERR2 2 -#define PCRE_UTF16_ERR3 3 -#define PCRE_UTF16_ERR4 4 - -/* Request types for pcre_fullinfo() */ - -#define PCRE_INFO_OPTIONS 0 -#define PCRE_INFO_SIZE 1 -#define PCRE_INFO_CAPTURECOUNT 2 -#define PCRE_INFO_BACKREFMAX 3 -#define PCRE_INFO_FIRSTBYTE 4 -#define PCRE_INFO_FIRSTCHAR 4 /* For backwards compatibility */ -#define PCRE_INFO_FIRSTTABLE 5 -#define PCRE_INFO_LASTLITERAL 6 -#define PCRE_INFO_NAMEENTRYSIZE 7 -#define PCRE_INFO_NAMECOUNT 8 -#define PCRE_INFO_NAMETABLE 9 -#define PCRE_INFO_STUDYSIZE 10 -#define PCRE_INFO_DEFAULT_TABLES 11 -#define PCRE_INFO_OKPARTIAL 12 -#define PCRE_INFO_JCHANGED 13 -#define PCRE_INFO_HASCRORLF 14 -#define PCRE_INFO_MINLENGTH 15 -#define PCRE_INFO_JIT 16 -#define PCRE_INFO_JITSIZE 17 -#define PCRE_INFO_MAXLOOKBEHIND 18 - -/* Request types for pcre_config(). Do not re-arrange, in order to remain -compatible. */ - -#define PCRE_CONFIG_UTF8 0 -#define PCRE_CONFIG_NEWLINE 1 -#define PCRE_CONFIG_LINK_SIZE 2 -#define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3 -#define PCRE_CONFIG_MATCH_LIMIT 4 -#define PCRE_CONFIG_STACKRECURSE 5 -#define PCRE_CONFIG_UNICODE_PROPERTIES 6 -#define PCRE_CONFIG_MATCH_LIMIT_RECURSION 7 -#define PCRE_CONFIG_BSR 8 -#define PCRE_CONFIG_JIT 9 -#define PCRE_CONFIG_UTF16 10 -#define PCRE_CONFIG_JITTARGET 11 - -/* Request types for pcre_study(). Do not re-arrange, in order to remain -compatible. */ - -#define PCRE_STUDY_JIT_COMPILE 0x0001 -#define PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE 0x0002 -#define PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE 0x0004 - -/* Bit flags for the pcre[16]_extra structure. Do not re-arrange or redefine -these bits, just add new ones on the end, in order to remain compatible. */ - -#define PCRE_EXTRA_STUDY_DATA 0x0001 -#define PCRE_EXTRA_MATCH_LIMIT 0x0002 -#define PCRE_EXTRA_CALLOUT_DATA 0x0004 -#define PCRE_EXTRA_TABLES 0x0008 -#define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0x0010 -#define PCRE_EXTRA_MARK 0x0020 -#define PCRE_EXTRA_EXECUTABLE_JIT 0x0040 - -/* Types */ - -struct real_pcre; /* declaration; the definition is private */ -typedef struct real_pcre pcre; - -struct real_pcre16; /* declaration; the definition is private */ -typedef struct real_pcre16 pcre16; - -struct real_pcre_jit_stack; /* declaration; the definition is private */ -typedef struct real_pcre_jit_stack pcre_jit_stack; - -struct real_pcre16_jit_stack; /* declaration; the definition is private */ -typedef struct real_pcre16_jit_stack pcre16_jit_stack; - -/* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must contain -a 16 bit wide signed data type. Otherwise it can be a dummy data type since -pcre16 functions are not implemented. There is a check for this in pcre_internal.h. */ -#ifndef PCRE_UCHAR16 -#define PCRE_UCHAR16 unsigned short -#endif - -#ifndef PCRE_SPTR16 -#define PCRE_SPTR16 const PCRE_UCHAR16 * -#endif - -/* When PCRE is compiled as a C++ library, the subject pointer type can be -replaced with a custom type. For conventional use, the public interface is a -const char *. */ - -#ifndef PCRE_SPTR -#define PCRE_SPTR const char * -#endif - -/* The structure for passing additional data to pcre_exec(). This is defined in -such as way as to be extensible. Always add new fields at the end, in order to -remain compatible. */ - -typedef struct pcre_extra { - unsigned long int flags; /* Bits for which fields are set */ - void *study_data; /* Opaque data from pcre_study() */ - unsigned long int match_limit; /* Maximum number of calls to match() */ - void *callout_data; /* Data passed back in callouts */ - const unsigned char *tables; /* Pointer to character tables */ - unsigned long int match_limit_recursion; /* Max recursive calls to match() */ - unsigned char **mark; /* For passing back a mark pointer */ - void *executable_jit; /* Contains a pointer to a compiled jit code */ -} pcre_extra; - -/* Same structure as above, but with 16 bit char pointers. */ - -typedef struct pcre16_extra { - unsigned long int flags; /* Bits for which fields are set */ - void *study_data; /* Opaque data from pcre_study() */ - unsigned long int match_limit; /* Maximum number of calls to match() */ - void *callout_data; /* Data passed back in callouts */ - const unsigned char *tables; /* Pointer to character tables */ - unsigned long int match_limit_recursion; /* Max recursive calls to match() */ - PCRE_UCHAR16 **mark; /* For passing back a mark pointer */ - void *executable_jit; /* Contains a pointer to a compiled jit code */ -} pcre16_extra; - -/* The structure for passing out data via the pcre_callout_function. We use a -structure so that new fields can be added on the end in future versions, -without changing the API of the function, thereby allowing old clients to work -without modification. */ - -typedef struct pcre_callout_block { - int version; /* Identifies version of block */ - /* ------------------------ Version 0 ------------------------------- */ - int callout_number; /* Number compiled into pattern */ - int *offset_vector; /* The offset vector */ - PCRE_SPTR subject; /* The subject being matched */ - int subject_length; /* The length of the subject */ - int start_match; /* Offset to start of this match attempt */ - int current_position; /* Where we currently are in the subject */ - int capture_top; /* Max current capture */ - int capture_last; /* Most recently closed capture */ - void *callout_data; /* Data passed in with the call */ - /* ------------------- Added for Version 1 -------------------------- */ - int pattern_position; /* Offset to next item in the pattern */ - int next_item_length; /* Length of next item in the pattern */ - /* ------------------- Added for Version 2 -------------------------- */ - const unsigned char *mark; /* Pointer to current mark or NULL */ - /* ------------------------------------------------------------------ */ -} pcre_callout_block; - -/* Same structure as above, but with 16 bit char pointers. */ - -typedef struct pcre16_callout_block { - int version; /* Identifies version of block */ - /* ------------------------ Version 0 ------------------------------- */ - int callout_number; /* Number compiled into pattern */ - int *offset_vector; /* The offset vector */ - PCRE_SPTR16 subject; /* The subject being matched */ - int subject_length; /* The length of the subject */ - int start_match; /* Offset to start of this match attempt */ - int current_position; /* Where we currently are in the subject */ - int capture_top; /* Max current capture */ - int capture_last; /* Most recently closed capture */ - void *callout_data; /* Data passed in with the call */ - /* ------------------- Added for Version 1 -------------------------- */ - int pattern_position; /* Offset to next item in the pattern */ - int next_item_length; /* Length of next item in the pattern */ - /* ------------------- Added for Version 2 -------------------------- */ - const PCRE_UCHAR16 *mark; /* Pointer to current mark or NULL */ - /* ------------------------------------------------------------------ */ -} pcre16_callout_block; - -/* Indirection for store get and free functions. These can be set to -alternative malloc/free functions if required. Special ones are used in the -non-recursive case for "frames". There is also an optional callout function -that is triggered by the (?) regex item. For Virtual Pascal, these definitions -have to take another form. */ - -#ifndef VPCOMPAT -PCRE_EXP_DECL void *(*pcre_malloc)(size_t); -PCRE_EXP_DECL void (*pcre_free)(void *); -PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t); -PCRE_EXP_DECL void (*pcre_stack_free)(void *); -PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *); - -PCRE_EXP_DECL void *(*pcre16_malloc)(size_t); -PCRE_EXP_DECL void (*pcre16_free)(void *); -PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t); -PCRE_EXP_DECL void (*pcre16_stack_free)(void *); -PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *); -#else /* VPCOMPAT */ -PCRE_EXP_DECL void *pcre_malloc(size_t); -PCRE_EXP_DECL void pcre_free(void *); -PCRE_EXP_DECL void *pcre_stack_malloc(size_t); -PCRE_EXP_DECL void pcre_stack_free(void *); -PCRE_EXP_DECL int pcre_callout(pcre_callout_block *); - -PCRE_EXP_DECL void *pcre16_malloc(size_t); -PCRE_EXP_DECL void pcre16_free(void *); -PCRE_EXP_DECL void *pcre16_stack_malloc(size_t); -PCRE_EXP_DECL void pcre16_stack_free(void *); -PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *); -#endif /* VPCOMPAT */ - -/* User defined callback which provides a stack just before the match starts. */ - -typedef pcre_jit_stack *(*pcre_jit_callback)(void *); -typedef pcre16_jit_stack *(*pcre16_jit_callback)(void *); - -/* Exported PCRE functions */ - -PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *, - const unsigned char *); -PCRE_EXP_DECL pcre16 *pcre16_compile(PCRE_SPTR16, int, const char **, int *, - const unsigned char *); -PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **, - int *, const unsigned char *); -PCRE_EXP_DECL pcre16 *pcre16_compile2(PCRE_SPTR16, int, int *, const char **, - int *, const unsigned char *); -PCRE_EXP_DECL int pcre_config(int, void *); -PCRE_EXP_DECL int pcre16_config(int, void *); -PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *, - int *, int, const char *, char *, int); -PCRE_EXP_DECL int pcre16_copy_named_substring(const pcre16 *, PCRE_SPTR16, - int *, int, PCRE_SPTR16, PCRE_UCHAR16 *, int); -PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int, - char *, int); -PCRE_EXP_DECL int pcre16_copy_substring(PCRE_SPTR16, int *, int, int, - PCRE_UCHAR16 *, int); -PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *, - const char *, int, int, int, int *, int , int *, int); -PCRE_EXP_DECL int pcre16_dfa_exec(const pcre16 *, const pcre16_extra *, - PCRE_SPTR16, int, int, int, int *, int , int *, int); -PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR, - int, int, int, int *, int); -PCRE_EXP_DECL int pcre16_exec(const pcre16 *, const pcre16_extra *, - PCRE_SPTR16, int, int, int, int *, int); -PCRE_EXP_DECL void pcre_free_substring(const char *); -PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16); -PCRE_EXP_DECL void pcre_free_substring_list(const char **); -PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *); -PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int, - void *); -PCRE_EXP_DECL int pcre16_fullinfo(const pcre16 *, const pcre16_extra *, int, - void *); -PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *, - int *, int, const char *, const char **); -PCRE_EXP_DECL int pcre16_get_named_substring(const pcre16 *, PCRE_SPTR16, - int *, int, PCRE_SPTR16, PCRE_SPTR16 *); -PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *); -PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16); -PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *, - char **, char **); -PCRE_EXP_DECL int pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR16, - PCRE_UCHAR16 **, PCRE_UCHAR16 **); -PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int, - const char **); -PCRE_EXP_DECL int pcre16_get_substring(PCRE_SPTR16, int *, int, int, - PCRE_SPTR16 *); -PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int, - const char ***); -PCRE_EXP_DECL int pcre16_get_substring_list(PCRE_SPTR16, int *, int, - PCRE_SPTR16 **); -PCRE_EXP_DECL const unsigned char *pcre_maketables(void); -PCRE_EXP_DECL const unsigned char *pcre16_maketables(void); -PCRE_EXP_DECL int pcre_refcount(pcre *, int); -PCRE_EXP_DECL int pcre16_refcount(pcre16 *, int); -PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **); -PCRE_EXP_DECL pcre16_extra *pcre16_study(const pcre16 *, int, const char **); -PCRE_EXP_DECL void pcre_free_study(pcre_extra *); -PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *); -PCRE_EXP_DECL const char *pcre_version(void); -PCRE_EXP_DECL const char *pcre16_version(void); - -/* Utility functions for byte order swaps. */ -PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *, pcre_extra *, - const unsigned char *); -PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *, pcre16_extra *, - const unsigned char *); -PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *, - PCRE_SPTR16, int, int *, int); - -/* JIT compiler related functions. */ - -PCRE_EXP_DECL pcre_jit_stack *pcre_jit_stack_alloc(int, int); -PCRE_EXP_DECL pcre16_jit_stack *pcre16_jit_stack_alloc(int, int); -PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *); -PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *); -PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *, - pcre_jit_callback, void *); -PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *, - pcre16_jit_callback, void *); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* End of pcre.h */ diff --git a/glib/pcre/pcre_byte_order.c b/glib/pcre/pcre_byte_order.c deleted file mode 100644 index 4f21433c1..000000000 --- a/glib/pcre/pcre_byte_order.c +++ /dev/null @@ -1,286 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains an internal function that tests a compiled pattern to -see if it was compiled with the opposite endianness. If so, it uses an -auxiliary local function to flip the appropriate bytes. */ - - -#include "config.h" - -#include "pcre_internal.h" - - -/************************************************* -* Swap byte functions * -*************************************************/ - -/* The following functions swap the bytes of a pcre_uint16 -and pcre_uint32 value. - -Arguments: - value any number - -Returns: the byte swapped value -*/ - -static pcre_uint32 -swap_uint32(pcre_uint32 value) -{ -return ((value & 0x000000ff) << 24) | - ((value & 0x0000ff00) << 8) | - ((value & 0x00ff0000) >> 8) | - (value >> 24); -} - -static pcre_uint16 -swap_uint16(pcre_uint16 value) -{ -return (value >> 8) | (value << 8); -} - - -/************************************************* -* Test for a byte-flipped compiled regex * -*************************************************/ - -/* This function swaps the bytes of a compiled pattern usually -loaded form the disk. It also sets the tables pointer, which -is likely an invalid pointer after reload. - -Arguments: - argument_re points to the compiled expression - extra_data points to extra data or is NULL - tables points to the character tables or NULL - -Returns: 0 if the swap is successful, negative on error -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *argument_re, - pcre_extra *extra_data, const unsigned char *tables) -#else -PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *argument_re, - pcre16_extra *extra_data, const unsigned char *tables) -#endif -{ -REAL_PCRE *re = (REAL_PCRE *)argument_re; -pcre_study_data *study; -#ifndef COMPILE_PCRE8 -pcre_uchar *ptr; -int length; -#ifdef SUPPORT_UTF -BOOL utf; -BOOL utf16_char; -#endif /* SUPPORT_UTF */ -#endif /* !COMPILE_PCRE8 */ - -if (re == NULL) return PCRE_ERROR_NULL; -if (re->magic_number == MAGIC_NUMBER) - { - if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; - re->tables = tables; - return 0; - } - -if (re->magic_number != REVERSED_MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; -if ((swap_uint16(re->flags) & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; - -re->magic_number = MAGIC_NUMBER; -re->size = swap_uint32(re->size); -re->options = swap_uint32(re->options); -re->flags = swap_uint16(re->flags); -re->top_bracket = swap_uint16(re->top_bracket); -re->top_backref = swap_uint16(re->top_backref); -re->first_char = swap_uint16(re->first_char); -re->req_char = swap_uint16(re->req_char); -re->name_table_offset = swap_uint16(re->name_table_offset); -re->name_entry_size = swap_uint16(re->name_entry_size); -re->name_count = swap_uint16(re->name_count); -re->ref_count = swap_uint16(re->ref_count); -re->tables = tables; - -if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0) - { - study = (pcre_study_data *)extra_data->study_data; - study->size = swap_uint32(study->size); - study->flags = swap_uint32(study->flags); - study->minlength = swap_uint32(study->minlength); - } - -#ifndef COMPILE_PCRE8 -ptr = (pcre_uchar *)re + re->name_table_offset; -length = re->name_count * re->name_entry_size; -#ifdef SUPPORT_UTF -utf = (re->options & PCRE_UTF16) != 0; -utf16_char = FALSE; -#endif - -while(TRUE) - { - /* Swap previous characters. */ - while (length-- > 0) - { - *ptr = swap_uint16(*ptr); - ptr++; - } -#ifdef SUPPORT_UTF - if (utf16_char) - { - if (HAS_EXTRALEN(ptr[-1])) - { - /* We know that there is only one extra character in UTF-16. */ - *ptr = swap_uint16(*ptr); - ptr++; - } - } - utf16_char = FALSE; -#endif /* SUPPORT_UTF */ - - /* Get next opcode. */ - length = 0; - *ptr = swap_uint16(*ptr); - switch (*ptr) - { - case OP_END: - return 0; - -#ifdef SUPPORT_UTF - case OP_CHAR: - case OP_CHARI: - case OP_NOT: - case OP_NOTI: - case OP_STAR: - case OP_MINSTAR: - case OP_PLUS: - case OP_MINPLUS: - case OP_QUERY: - case OP_MINQUERY: - case OP_UPTO: - case OP_MINUPTO: - case OP_EXACT: - case OP_POSSTAR: - case OP_POSPLUS: - case OP_POSQUERY: - case OP_POSUPTO: - case OP_STARI: - case OP_MINSTARI: - case OP_PLUSI: - case OP_MINPLUSI: - case OP_QUERYI: - case OP_MINQUERYI: - case OP_UPTOI: - case OP_MINUPTOI: - case OP_EXACTI: - case OP_POSSTARI: - case OP_POSPLUSI: - case OP_POSQUERYI: - case OP_POSUPTOI: - case OP_NOTSTAR: - case OP_NOTMINSTAR: - case OP_NOTPLUS: - case OP_NOTMINPLUS: - case OP_NOTQUERY: - case OP_NOTMINQUERY: - case OP_NOTUPTO: - case OP_NOTMINUPTO: - case OP_NOTEXACT: - case OP_NOTPOSSTAR: - case OP_NOTPOSPLUS: - case OP_NOTPOSQUERY: - case OP_NOTPOSUPTO: - case OP_NOTSTARI: - case OP_NOTMINSTARI: - case OP_NOTPLUSI: - case OP_NOTMINPLUSI: - case OP_NOTQUERYI: - case OP_NOTMINQUERYI: - case OP_NOTUPTOI: - case OP_NOTMINUPTOI: - case OP_NOTEXACTI: - case OP_NOTPOSSTARI: - case OP_NOTPOSPLUSI: - case OP_NOTPOSQUERYI: - case OP_NOTPOSUPTOI: - if (utf) utf16_char = TRUE; -#endif - /* Fall through. */ - - default: - length = PRIV(OP_lengths)[*ptr] - 1; - break; - - case OP_CLASS: - case OP_NCLASS: - /* Skip the character bit map. */ - ptr += 32/sizeof(pcre_uchar); - length = 0; - break; - - case OP_XCLASS: - /* Reverse the size of the XCLASS instance. */ - ptr++; - *ptr = swap_uint16(*ptr); - if (LINK_SIZE > 1) - { - /* LINK_SIZE can be 1 or 2 in 16 bit mode. */ - ptr++; - *ptr = swap_uint16(*ptr); - } - ptr++; - length = (GET(ptr, -LINK_SIZE)) - (1 + LINK_SIZE + 1); - *ptr = swap_uint16(*ptr); - if ((*ptr & XCL_MAP) != 0) - { - /* Skip the character bit map. */ - ptr += 32/sizeof(pcre_uchar); - length -= 32/sizeof(pcre_uchar); - } - break; - } - ptr++; - } -/* Control should never reach here in 16 bit mode. */ -#endif /* !COMPILE_PCRE8 */ - -return 0; -} - -/* End of pcre_byte_order.c */ diff --git a/glib/pcre/pcre_chartables.c b/glib/pcre/pcre_chartables.c deleted file mode 100644 index 293b16b32..000000000 --- a/glib/pcre/pcre_chartables.c +++ /dev/null @@ -1,196 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* This file contains character tables that are used when no external tables -are passed to PCRE by the application that calls it. The tables are used only -for characters whose code values are less than 256. - -This is a default version of the tables that assumes ASCII encoding. A program -called dftables (which is distributed with PCRE) can be used to build -alternative versions of this file. This is necessary if you are running in an -EBCDIC environment, or if you want to default to a different encoding, for -example ISO-8859-1. When dftables is run, it creates these tables in the -current locale. If PCRE is configured with --enable-rebuild-chartables, this -happens automatically. - -The following #includes are present because without them gcc 4.x may remove the -array definition from the final binary if PCRE is built into a static library -and dead code stripping is activated. This leads to link errors. Pulling in the -header ensures that the array gets flagged as "someone outside this compilation -unit might reference this" and so it will always be supplied to the linker. */ - -#include "config.h" - -#include "pcre_internal.h" - -const pcre_uint8 PRIV(default_tables)[] = { - -/* This table is a lower casing table. */ - - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, - 64, 97, 98, 99,100,101,102,103, - 104,105,106,107,108,109,110,111, - 112,113,114,115,116,117,118,119, - 120,121,122, 91, 92, 93, 94, 95, - 96, 97, 98, 99,100,101,102,103, - 104,105,106,107,108,109,110,111, - 112,113,114,115,116,117,118,119, - 120,121,122,123,124,125,126,127, - 128,129,130,131,132,133,134,135, - 136,137,138,139,140,141,142,143, - 144,145,146,147,148,149,150,151, - 152,153,154,155,156,157,158,159, - 160,161,162,163,164,165,166,167, - 168,169,170,171,172,173,174,175, - 176,177,178,179,180,181,182,183, - 184,185,186,187,188,189,190,191, - 192,193,194,195,196,197,198,199, - 200,201,202,203,204,205,206,207, - 208,209,210,211,212,213,214,215, - 216,217,218,219,220,221,222,223, - 224,225,226,227,228,229,230,231, - 232,233,234,235,236,237,238,239, - 240,241,242,243,244,245,246,247, - 248,249,250,251,252,253,254,255, - -/* This table is a case flipping table. */ - - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, - 64, 97, 98, 99,100,101,102,103, - 104,105,106,107,108,109,110,111, - 112,113,114,115,116,117,118,119, - 120,121,122, 91, 92, 93, 94, 95, - 96, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90,123,124,125,126,127, - 128,129,130,131,132,133,134,135, - 136,137,138,139,140,141,142,143, - 144,145,146,147,148,149,150,151, - 152,153,154,155,156,157,158,159, - 160,161,162,163,164,165,166,167, - 168,169,170,171,172,173,174,175, - 176,177,178,179,180,181,182,183, - 184,185,186,187,188,189,190,191, - 192,193,194,195,196,197,198,199, - 200,201,202,203,204,205,206,207, - 208,209,210,211,212,213,214,215, - 216,217,218,219,220,221,222,223, - 224,225,226,227,228,229,230,231, - 232,233,234,235,236,237,238,239, - 240,241,242,243,244,245,246,247, - 248,249,250,251,252,253,254,255, - -/* This table contains bit maps for various character classes. Each map is 32 -bytes long and the bits run from the least significant end of each byte. The -classes that have their own maps are: space, xdigit, digit, upper, lower, word, -graph, print, punct, and cntrl. Other classes are built from combinations. */ - - 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, - 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, - 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - - 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - - 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - - 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc, - 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - -/* This table identifies various classes of character by individual bits: - 0x01 white space character - 0x02 letter - 0x04 decimal digit - 0x08 hexadecimal digit - 0x10 alphanumeric or '_' - 0x80 regular expression metacharacter or binary zero -*/ - - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ - 0x00,0x01,0x01,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ - 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */ - 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */ - 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ - 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */ - 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */ - 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */ - 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */ - 0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /* X - _ */ - 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */ - 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */ - 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */ - 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ - -/* End of pcre_chartables.c */ diff --git a/glib/pcre/pcre_compile.c b/glib/pcre/pcre_compile.c deleted file mode 100644 index 12e09c4ef..000000000 --- a/glib/pcre/pcre_compile.c +++ /dev/null @@ -1,8213 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains the external function pcre_compile(), along with -supporting internal functions that are not used by other modules. */ - - -#include "config.h" - -#define NLBLOCK cd /* Block containing newline information */ -#define PSSTART start_pattern /* Field containing processed string start */ -#define PSEND end_pattern /* Field containing processed string end */ - -#include "pcre_internal.h" - -#ifdef GLIB_COMPILATION -#include "gstrfuncs.h" -#else -#include <glib.h> -#endif - -/* When PCRE_DEBUG is defined, we need the pcre(16)_printint() function, which -is also used by pcretest. PCRE_DEBUG is not defined when building a production -library. We do not need to select pcre16_printint.c specially, because the -COMPILE_PCREx macro will already be appropriately set. */ - -#ifdef PCRE_DEBUG -/* pcre_printint.c should not include any headers */ -#define PCRE_INCLUDED -#include "pcre_printint.c" -#undef PCRE_INCLUDED -#endif - - -/* Macro for setting individual bits in class bitmaps. */ - -#define SETBIT(a,b) a[b/8] |= (1 << (b%8)) - -/* Maximum length value to check against when making sure that the integer that -holds the compiled pattern length does not overflow. We make it a bit less than -INT_MAX to allow for adding in group terminating bytes, so that we don't have -to check them every time. */ - -#define OFLOW_MAX (INT_MAX - 20) - - -/************************************************* -* Code parameters and static tables * -*************************************************/ - -/* This value specifies the size of stack workspace that is used during the -first pre-compile phase that determines how much memory is required. The regex -is partly compiled into this space, but the compiled parts are discarded as -soon as they can be, so that hopefully there will never be an overrun. The code -does, however, check for an overrun. The largest amount I've seen used is 218, -so this number is very generous. - -The same workspace is used during the second, actual compile phase for -remembering forward references to groups so that they can be filled in at the -end. Each entry in this list occupies LINK_SIZE bytes, so even when LINK_SIZE -is 4 there is plenty of room for most patterns. However, the memory can get -filled up by repetitions of forward references, for example patterns like -/(?1){0,1999}(b)/, and one user did hit the limit. The code has been changed so -that the workspace is expanded using malloc() in this situation. The value -below is therefore a minimum, and we put a maximum on it for safety. The -minimum is now also defined in terms of LINK_SIZE so that the use of malloc() -kicks in at the same number of forward references in all cases. */ - -#define COMPILE_WORK_SIZE (2048*LINK_SIZE) -#define COMPILE_WORK_SIZE_MAX (100*COMPILE_WORK_SIZE) - -/* The overrun tests check for a slightly smaller size so that they detect the -overrun before it actually does run off the end of the data block. */ - -#define WORK_SIZE_SAFETY_MARGIN (100) - -/* Private flags added to firstchar and reqchar. */ - -#define REQ_CASELESS 0x10000000l /* Indicates caselessness */ -#define REQ_VARY 0x20000000l /* Reqchar followed non-literal item */ - -/* Repeated character flags. */ - -#define UTF_LENGTH 0x10000000l /* The char contains its length. */ - -/* Table for handling escaped characters in the range '0'-'z'. Positive returns -are simple data values; negative values are for special things like \d and so -on. Zero means further processing is needed (for things like \x), or the escape -is invalid. */ - -#ifndef EBCDIC - -/* This is the "normal" table for ASCII systems or for EBCDIC systems running -in UTF-8 mode. */ - -static const short int escapes[] = { - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - CHAR_COLON, CHAR_SEMICOLON, - CHAR_LESS_THAN_SIGN, CHAR_EQUALS_SIGN, - CHAR_GREATER_THAN_SIGN, CHAR_QUESTION_MARK, - CHAR_COMMERCIAL_AT, -ESC_A, - -ESC_B, -ESC_C, - -ESC_D, -ESC_E, - 0, -ESC_G, - -ESC_H, 0, - 0, -ESC_K, - 0, 0, - -ESC_N, 0, - -ESC_P, -ESC_Q, - -ESC_R, -ESC_S, - 0, 0, - -ESC_V, -ESC_W, - -ESC_X, 0, - -ESC_Z, CHAR_LEFT_SQUARE_BRACKET, - CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET, - CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE, - CHAR_GRAVE_ACCENT, 7, - -ESC_b, 0, - -ESC_d, ESC_e, - ESC_f, 0, - -ESC_h, 0, - 0, -ESC_k, - 0, 0, - ESC_n, 0, - -ESC_p, 0, - ESC_r, -ESC_s, - ESC_tee, 0, - -ESC_v, -ESC_w, - 0, 0, - -ESC_z -}; - -#else - -/* This is the "abnormal" table for EBCDIC systems without UTF-8 support. */ - -static const short int escapes[] = { -/* 48 */ 0, 0, 0, '.', '<', '(', '+', '|', -/* 50 */ '&', 0, 0, 0, 0, 0, 0, 0, -/* 58 */ 0, 0, '!', '$', '*', ')', ';', '~', -/* 60 */ '-', '/', 0, 0, 0, 0, 0, 0, -/* 68 */ 0, 0, '|', ',', '%', '_', '>', '?', -/* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, -/* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"', -/* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, -/* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0, -/* 90 */ 0, 0, -ESC_k, 'l', 0, ESC_n, 0, -ESC_p, -/* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0, -/* A0 */ 0, '~', -ESC_s, ESC_tee, 0,-ESC_v, -ESC_w, 0, -/* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0, -/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0, -/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-', -/* C0 */ '{',-ESC_A, -ESC_B, -ESC_C, -ESC_D,-ESC_E, 0, -ESC_G, -/* C8 */-ESC_H, 0, 0, 0, 0, 0, 0, 0, -/* D0 */ '}', 0, -ESC_K, 0, 0,-ESC_N, 0, -ESC_P, -/* D8 */-ESC_Q,-ESC_R, 0, 0, 0, 0, 0, 0, -/* E0 */ '\\', 0, -ESC_S, 0, 0,-ESC_V, -ESC_W, -ESC_X, -/* E8 */ 0,-ESC_Z, 0, 0, 0, 0, 0, 0, -/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, -/* F8 */ 0, 0, 0, 0, 0, 0, 0, 0 -}; -#endif - - -/* Table of special "verbs" like (*PRUNE). This is a short table, so it is -searched linearly. Put all the names into a single string, in order to reduce -the number of relocations when a shared library is dynamically linked. The -string is built from string macros so that it works in UTF-8 mode on EBCDIC -platforms. */ - -typedef struct verbitem { - int len; /* Length of verb name */ - int op; /* Op when no arg, or -1 if arg mandatory */ - int op_arg; /* Op when arg present, or -1 if not allowed */ -} verbitem; - -static const char verbnames[] = - "\0" /* Empty name is a shorthand for MARK */ - STRING_MARK0 - STRING_ACCEPT0 - STRING_COMMIT0 - STRING_F0 - STRING_FAIL0 - STRING_PRUNE0 - STRING_SKIP0 - STRING_THEN; - -static const verbitem verbs[] = { - { 0, -1, OP_MARK }, - { 4, -1, OP_MARK }, - { 6, OP_ACCEPT, -1 }, - { 6, OP_COMMIT, -1 }, - { 1, OP_FAIL, -1 }, - { 4, OP_FAIL, -1 }, - { 5, OP_PRUNE, OP_PRUNE_ARG }, - { 4, OP_SKIP, OP_SKIP_ARG }, - { 4, OP_THEN, OP_THEN_ARG } -}; - -static const int verbcount = sizeof(verbs)/sizeof(verbitem); - - -/* Tables of names of POSIX character classes and their lengths. The names are -now all in a single string, to reduce the number of relocations when a shared -library is dynamically loaded. The list of lengths is terminated by a zero -length entry. The first three must be alpha, lower, upper, as this is assumed -for handling case independence. */ - -static const char posix_names[] = - STRING_alpha0 STRING_lower0 STRING_upper0 STRING_alnum0 - STRING_ascii0 STRING_blank0 STRING_cntrl0 STRING_digit0 - STRING_graph0 STRING_print0 STRING_punct0 STRING_space0 - STRING_word0 STRING_xdigit; - -static const pcre_uint8 posix_name_lengths[] = { - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 }; - -/* Table of class bit maps for each POSIX class. Each class is formed from a -base map, with an optional addition or removal of another map. Then, for some -classes, there is some additional tweaking: for [:blank:] the vertical space -characters are removed, and for [:alpha:] and [:alnum:] the underscore -character is removed. The triples in the table consist of the base map offset, -second map offset or -1 if no second map, and a non-negative value for map -addition or a negative value for map subtraction (if there are two maps). The -absolute value of the third field has these meanings: 0 => no tweaking, 1 => -remove vertical space characters, 2 => remove underscore. */ - -static const int posix_class_maps[] = { - cbit_word, cbit_digit, -2, /* alpha */ - cbit_lower, -1, 0, /* lower */ - cbit_upper, -1, 0, /* upper */ - cbit_word, -1, 2, /* alnum - word without underscore */ - cbit_print, cbit_cntrl, 0, /* ascii */ - cbit_space, -1, 1, /* blank - a GNU extension */ - cbit_cntrl, -1, 0, /* cntrl */ - cbit_digit, -1, 0, /* digit */ - cbit_graph, -1, 0, /* graph */ - cbit_print, -1, 0, /* print */ - cbit_punct, -1, 0, /* punct */ - cbit_space, -1, 0, /* space */ - cbit_word, -1, 0, /* word - a Perl extension */ - cbit_xdigit,-1, 0 /* xdigit */ -}; - -/* Table of substitutes for \d etc when PCRE_UCP is set. The POSIX class -substitutes must be in the order of the names, defined above, and there are -both positive and negative cases. NULL means no substitute. */ - -#ifdef SUPPORT_UCP -static const pcre_uchar string_PNd[] = { - CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, - CHAR_N, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_pNd[] = { - CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, - CHAR_N, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_PXsp[] = { - CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, - CHAR_X, CHAR_s, CHAR_p, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_pXsp[] = { - CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, - CHAR_X, CHAR_s, CHAR_p, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_PXwd[] = { - CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, - CHAR_X, CHAR_w, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_pXwd[] = { - CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, - CHAR_X, CHAR_w, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' }; - -static const pcre_uchar *substitutes[] = { - string_PNd, /* \D */ - string_pNd, /* \d */ - string_PXsp, /* \S */ /* NOTE: Xsp is Perl space */ - string_pXsp, /* \s */ - string_PXwd, /* \W */ - string_pXwd /* \w */ -}; - -static const pcre_uchar string_pL[] = { - CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, - CHAR_L, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_pLl[] = { - CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, - CHAR_L, CHAR_l, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_pLu[] = { - CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, - CHAR_L, CHAR_u, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_pXan[] = { - CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, - CHAR_X, CHAR_a, CHAR_n, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_h[] = { - CHAR_BACKSLASH, CHAR_h, '\0' }; -static const pcre_uchar string_pXps[] = { - CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, - CHAR_X, CHAR_p, CHAR_s, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_PL[] = { - CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, - CHAR_L, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_PLl[] = { - CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, - CHAR_L, CHAR_l, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_PLu[] = { - CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, - CHAR_L, CHAR_u, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_PXan[] = { - CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, - CHAR_X, CHAR_a, CHAR_n, CHAR_RIGHT_CURLY_BRACKET, '\0' }; -static const pcre_uchar string_H[] = { - CHAR_BACKSLASH, CHAR_H, '\0' }; -static const pcre_uchar string_PXps[] = { - CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, - CHAR_X, CHAR_p, CHAR_s, CHAR_RIGHT_CURLY_BRACKET, '\0' }; - -static const pcre_uchar *posix_substitutes[] = { - string_pL, /* alpha */ - string_pLl, /* lower */ - string_pLu, /* upper */ - string_pXan, /* alnum */ - NULL, /* ascii */ - string_h, /* blank */ - NULL, /* cntrl */ - string_pNd, /* digit */ - NULL, /* graph */ - NULL, /* print */ - NULL, /* punct */ - string_pXps, /* space */ /* NOTE: Xps is POSIX space */ - string_pXwd, /* word */ - NULL, /* xdigit */ - /* Negated cases */ - string_PL, /* ^alpha */ - string_PLl, /* ^lower */ - string_PLu, /* ^upper */ - string_PXan, /* ^alnum */ - NULL, /* ^ascii */ - string_H, /* ^blank */ - NULL, /* ^cntrl */ - string_PNd, /* ^digit */ - NULL, /* ^graph */ - NULL, /* ^print */ - NULL, /* ^punct */ - string_PXps, /* ^space */ /* NOTE: Xps is POSIX space */ - string_PXwd, /* ^word */ - NULL /* ^xdigit */ -}; -#define POSIX_SUBSIZE (sizeof(posix_substitutes) / sizeof(pcre_uchar *)) -#endif - -#define STRING(a) # a -#define XSTRING(s) STRING(s) - -/* The texts of compile-time error messages. These are "char *" because they -are passed to the outside world. Do not ever re-use any error number, because -they are documented. Always add a new error instead. Messages marked DEAD below -are no longer used. This used to be a table of strings, but in order to reduce -the number of relocations needed when a shared library is loaded dynamically, -it is now one long string. We cannot use a table of offsets, because the -lengths of inserts such as XSTRING(MAX_NAME_SIZE) are not known. Instead, we -simply count through to the one we want - this isn't a performance issue -because these strings are used only when there is a compilation error. - -Each substring ends with \0 to insert a null character. This includes the final -substring, so that the whole string ends with \0\0, which can be detected when -counting through. */ - -static const char error_texts[] = - "no error\0" - "\\ at end of pattern\0" - "\\c at end of pattern\0" - "unrecognized character follows \\\0" - "numbers out of order in {} quantifier\0" - /* 5 */ - "number too big in {} quantifier\0" - "missing terminating ] for character class\0" - "invalid escape sequence in character class\0" - "range out of order in character class\0" - "nothing to repeat\0" - /* 10 */ - "operand of unlimited repeat could match the empty string\0" /** DEAD **/ - "internal error: unexpected repeat\0" - "unrecognized character after (? or (?-\0" - "POSIX named classes are supported only within a class\0" - "missing )\0" - /* 15 */ - "reference to non-existent subpattern\0" - "erroffset passed as NULL\0" - "unknown option bit(s) set\0" - "missing ) after comment\0" - "parentheses nested too deeply\0" /** DEAD **/ - /* 20 */ - "regular expression is too large\0" - "failed to get memory\0" - "unmatched parentheses\0" - "internal error: code overflow\0" - "unrecognized character after (?<\0" - /* 25 */ - "lookbehind assertion is not fixed length\0" - "malformed number or name after (?(\0" - "conditional group contains more than two branches\0" - "assertion expected after (?(\0" - "(?R or (?[+-]digits must be followed by )\0" - /* 30 */ - "unknown POSIX class name\0" - "POSIX collating elements are not supported\0" - "this version of PCRE is compiled without UTF support\0" - "spare error\0" /** DEAD **/ - "character value in \\x{...} sequence is too large\0" - /* 35 */ - "invalid condition (?(0)\0" - "\\C not allowed in lookbehind assertion\0" - "PCRE does not support \\L, \\l, \\N{name}, \\U, or \\u\0" - "number after (?C is > 255\0" - "closing ) for (?C expected\0" - /* 40 */ - "recursive call could loop indefinitely\0" - "unrecognized character after (?P\0" - "syntax error in subpattern name (missing terminator)\0" - "two named subpatterns have the same name\0" - "invalid UTF-8 string\0" - /* 45 */ - "support for \\P, \\p, and \\X has not been compiled\0" - "malformed \\P or \\p sequence\0" - "unknown property name after \\P or \\p\0" - "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " characters)\0" - "too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")\0" - /* 50 */ - "repeated subpattern is too long\0" /** DEAD **/ - "octal value is greater than \\377 in 8-bit non-UTF-8 mode\0" - "internal error: overran compiling workspace\0" - "internal error: previously-checked referenced subpattern not found\0" - "DEFINE group contains more than one branch\0" - /* 55 */ - "repeating a DEFINE group is not allowed\0" /** DEAD **/ - "inconsistent NEWLINE options\0" - "\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number\0" - "a numbered reference must not be zero\0" - "an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)\0" - /* 60 */ - "(*VERB) not recognized\0" - "number is too big\0" - "subpattern name expected\0" - "digit expected after (?+\0" - "] is an invalid data character in JavaScript compatibility mode\0" - /* 65 */ - "different names for subpatterns of the same number are not allowed\0" - "(*MARK) must have an argument\0" - "this version of PCRE is not compiled with Unicode property support\0" - "\\c must be followed by an ASCII character\0" - "\\k is not followed by a braced, angle-bracketed, or quoted name\0" - /* 70 */ - "internal error: unknown opcode in find_fixedlength()\0" - "\\N is not supported in a class\0" - "too many forward references\0" - "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)\0" - "invalid UTF-16 string\0" - /* 75 */ - "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)\0" - "character value in \\u.... sequence is too large\0" - ; - -/* Table to identify digits and hex digits. This is used when compiling -patterns. Note that the tables in chartables are dependent on the locale, and -may mark arbitrary characters as digits - but the PCRE compiling code expects -to handle only 0-9, a-z, and A-Z as digits when compiling. That is why we have -a private table here. It costs 256 bytes, but it is a lot faster than doing -character value tests (at least in some simple cases I timed), and in some -applications one wants PCRE to compile efficiently as well as match -efficiently. - -For convenience, we use the same bit definitions as in chartables: - - 0x04 decimal digit - 0x08 hexadecimal digit - -Then we can use ctype_digit and ctype_xdigit in the code. */ - -/* Using a simple comparison for decimal numbers rather than a memory read -is much faster, and the resulting code is simpler (the compiler turns it -into a subtraction and unsigned comparison). */ - -#define IS_DIGIT(x) ((x) >= CHAR_0 && (x) <= CHAR_9) - -#if 0 -#ifndef EBCDIC - -/* This is the "normal" case, for ASCII systems, and EBCDIC systems running in -UTF-8 mode. */ - -static const pcre_uint8 digitab[] = - { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - ' */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ( - / */ - 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 */ - 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */ - 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* @ - G */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H - O */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* P - W */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* X - _ */ - 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* ` - g */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h - o */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p - w */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x -127 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ - -#else - -/* This is the "abnormal" case, for EBCDIC systems not running in UTF-8 mode. */ - -static const pcre_uint8 digitab[] = - { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 0 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 10 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32- 39 20 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 30 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 40 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 72- | */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 50 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 88- 95 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 60 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 104- ? */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 70 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */ - 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* 128- g 80 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144- p 90 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160- x A0 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 B0 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ - 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* { - G C0 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* } - P D0 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* \ - X E0 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */ - 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 F0 */ - 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ - -static const pcre_uint8 ebcdic_chartab[] = { /* chartable partial dup */ - 0x80,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 0- 7 */ - 0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */ - 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 16- 23 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ - 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 32- 39 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */ - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 */ - 0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80, /* 72- | */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 */ - 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, /* 88- 95 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 */ - 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x80, /* 104- ? */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */ - 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* 128- g */ - 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */ - 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* 144- p */ - 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */ - 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* 160- x */ - 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */ - 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 */ - 0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ - 0x80,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* { - G */ - 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */ - 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* } - P */ - 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */ - 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* \ - X */ - 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */ - 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ - 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ -#endif -#endif /* 0 */ - -/* Definition to allow mutual recursion */ - -static BOOL - compile_regex(int, pcre_uchar **, const pcre_uchar **, int *, BOOL, BOOL, int, int, - int *, int *, branch_chain *, compile_data *, int *); - - - -/************************************************* -* Find an error text * -*************************************************/ - -/* The error texts are now all in one long string, to save on relocations. As -some of the text is of unknown length, we can't use a table of offsets. -Instead, just count through the strings. This is not a performance issue -because it happens only when there has been a compilation error. - -Argument: the error number -Returns: pointer to the error string -*/ - -static const char * -find_error_text(int n) -{ -const char *s = error_texts; -for (; n > 0; n--) - { - while (*s++ != 0) {}; - if (*s == 0) return "Error text not found (please report)"; - } -return s; -} - - -/************************************************* -* Expand the workspace * -*************************************************/ - -/* This function is called during the second compiling phase, if the number of -forward references fills the existing workspace, which is originally a block on -the stack. A larger block is obtained from malloc() unless the ultimate limit -has been reached or the increase will be rather small. - -Argument: pointer to the compile data block -Returns: 0 if all went well, else an error number -*/ - -static int -expand_workspace(compile_data *cd) -{ -pcre_uchar *newspace; -int newsize = cd->workspace_size * 2; - -if (newsize > COMPILE_WORK_SIZE_MAX) newsize = COMPILE_WORK_SIZE_MAX; -if (cd->workspace_size >= COMPILE_WORK_SIZE_MAX || - newsize - cd->workspace_size < WORK_SIZE_SAFETY_MARGIN) - return ERR72; - -newspace = (PUBL(malloc))(IN_UCHARS(newsize)); -if (newspace == NULL) return ERR21; -memcpy(newspace, cd->start_workspace, cd->workspace_size * sizeof(pcre_uchar)); -cd->hwm = (pcre_uchar *)newspace + (cd->hwm - cd->start_workspace); -if (cd->workspace_size > COMPILE_WORK_SIZE) - (PUBL(free))((void *)cd->start_workspace); -cd->start_workspace = newspace; -cd->workspace_size = newsize; -return 0; -} - - - -/************************************************* -* Check for counted repeat * -*************************************************/ - -/* This function is called when a '{' is encountered in a place where it might -start a quantifier. It looks ahead to see if it really is a quantifier or not. -It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd} -where the ddds are digits. - -Arguments: - p pointer to the first char after '{' - -Returns: TRUE or FALSE -*/ - -static BOOL -is_counted_repeat(const pcre_uchar *p) -{ -if (!IS_DIGIT(*p)) return FALSE; -p++; -while (IS_DIGIT(*p)) p++; -if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE; - -if (*p++ != CHAR_COMMA) return FALSE; -if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE; - -if (!IS_DIGIT(*p)) return FALSE; -p++; -while (IS_DIGIT(*p)) p++; - -return (*p == CHAR_RIGHT_CURLY_BRACKET); -} - - - -/************************************************* -* Handle escapes * -*************************************************/ - -/* This function is called when a \ has been encountered. It either returns a -positive value for a simple escape such as \n, or a negative value which -encodes one of the more complicated things such as \d. A backreference to group -n is returned as -(ESC_REF + n); ESC_REF is the highest ESC_xxx macro. When -UTF-8 is enabled, a positive value greater than 255 may be returned. On entry, -ptr is pointing at the \. On exit, it is on the final character of the escape -sequence. - -Arguments: - ptrptr points to the pattern position pointer - errorcodeptr points to the errorcode variable - bracount number of previous extracting brackets - options the options bits - isclass TRUE if inside a character class - -Returns: zero or positive => a data character - negative => a special escape sequence - on error, errorcodeptr is set -*/ - -static int -check_escape(const pcre_uchar **ptrptr, int *errorcodeptr, int bracount, - int options, BOOL isclass) -{ -/* PCRE_UTF16 has the same value as PCRE_UTF8. */ -BOOL utf = (options & PCRE_UTF8) != 0; -const pcre_uchar *ptr = *ptrptr + 1; -pcre_int32 c; -int i; - -GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */ -ptr--; /* Set pointer back to the last byte */ - -/* If backslash is at the end of the pattern, it's an error. */ - -if (c == 0) *errorcodeptr = ERR1; - -/* Non-alphanumerics are literals. For digits or letters, do an initial lookup -in a table. A non-zero result is something that can be returned immediately. -Otherwise further processing may be required. */ - -#ifndef EBCDIC /* ASCII/UTF-8 coding */ -/* Not alphanumeric */ -else if (c < CHAR_0 || c > CHAR_z) {} -else if ((i = escapes[c - CHAR_0]) != 0) c = i; - -#else /* EBCDIC coding */ -/* Not alphanumeric */ -else if (c < 'a' || (!MAX_255(c) || (ebcdic_chartab[c] & 0x0E) == 0)) {} -else if ((i = escapes[c - 0x48]) != 0) c = i; -#endif - -/* Escapes that need further processing, or are illegal. */ - -else - { - const pcre_uchar *oldptr; - BOOL braced, negated; - - switch (c) - { - /* A number of Perl escapes are not handled by PCRE. We give an explicit - error. */ - - case CHAR_l: - case CHAR_L: - *errorcodeptr = ERR37; - break; - - case CHAR_u: - if ((options & PCRE_JAVASCRIPT_COMPAT) != 0) - { - /* In JavaScript, \u must be followed by four hexadecimal numbers. - Otherwise it is a lowercase u letter. */ - if (MAX_255(ptr[1]) && g_ascii_isxdigit(ptr[1]) != 0 - && MAX_255(ptr[2]) && g_ascii_isxdigit(ptr[2]) != 0 - && MAX_255(ptr[3]) && g_ascii_isxdigit(ptr[3]) != 0 - && MAX_255(ptr[4]) && g_ascii_isxdigit(ptr[4]) != 0) - { - c = 0; - for (i = 0; i < 4; ++i) - { - int cc = *(++ptr); -#ifndef EBCDIC /* ASCII/UTF-8 coding */ - if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ - c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); -#else /* EBCDIC coding */ - if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */ - c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); -#endif - } - -#ifdef COMPILE_PCRE8 - if (c > (utf ? 0x10ffff : 0xff)) -#else -#ifdef COMPILE_PCRE16 - if (c > (utf ? 0x10ffff : 0xffff)) -#endif -#endif - { - *errorcodeptr = ERR76; - } - else if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73; - } - } - else - *errorcodeptr = ERR37; - break; - - case CHAR_U: - /* In JavaScript, \U is an uppercase U letter. */ - if ((options & PCRE_JAVASCRIPT_COMPAT) == 0) *errorcodeptr = ERR37; - break; - - /* In a character class, \g is just a literal "g". Outside a character - class, \g must be followed by one of a number of specific things: - - (1) A number, either plain or braced. If positive, it is an absolute - backreference. If negative, it is a relative backreference. This is a Perl - 5.10 feature. - - (2) Perl 5.10 also supports \g{name} as a reference to a named group. This - is part of Perl's movement towards a unified syntax for back references. As - this is synonymous with \k{name}, we fudge it up by pretending it really - was \k. - - (3) For Oniguruma compatibility we also support \g followed by a name or a - number either in angle brackets or in single quotes. However, these are - (possibly recursive) subroutine calls, _not_ backreferences. Just return - the -ESC_g code (cf \k). */ - - case CHAR_g: - if (isclass) break; - if (ptr[1] == CHAR_LESS_THAN_SIGN || ptr[1] == CHAR_APOSTROPHE) - { - c = -ESC_g; - break; - } - - /* Handle the Perl-compatible cases */ - - if (ptr[1] == CHAR_LEFT_CURLY_BRACKET) - { - const pcre_uchar *p; - for (p = ptr+2; *p != 0 && *p != CHAR_RIGHT_CURLY_BRACKET; p++) - if (*p != CHAR_MINUS && !IS_DIGIT(*p)) break; - if (*p != 0 && *p != CHAR_RIGHT_CURLY_BRACKET) - { - c = -ESC_k; - break; - } - braced = TRUE; - ptr++; - } - else braced = FALSE; - - if (ptr[1] == CHAR_MINUS) - { - negated = TRUE; - ptr++; - } - else negated = FALSE; - - /* The integer range is limited by the machine's int representation. */ - c = 0; - while (IS_DIGIT(ptr[1])) - { - if (((unsigned int)c) > INT_MAX / 10) /* Integer overflow */ - { - c = -1; - break; - } - c = c * 10 + *(++ptr) - CHAR_0; - } - if (((unsigned int)c) > INT_MAX) /* Integer overflow */ - { - while (IS_DIGIT(ptr[1])) - ptr++; - *errorcodeptr = ERR61; - break; - } - - if (braced && *(++ptr) != CHAR_RIGHT_CURLY_BRACKET) - { - *errorcodeptr = ERR57; - break; - } - - if (c == 0) - { - *errorcodeptr = ERR58; - break; - } - - if (negated) - { - if (c > bracount) - { - *errorcodeptr = ERR15; - break; - } - c = bracount - (c - 1); - } - - c = -(ESC_REF + c); - break; - - /* The handling of escape sequences consisting of a string of digits - starting with one that is not zero is not straightforward. By experiment, - the way Perl works seems to be as follows: - - Outside a character class, the digits are read as a decimal number. If the - number is less than 10, or if there are that many previous extracting - left brackets, then it is a back reference. Otherwise, up to three octal - digits are read to form an escaped byte. Thus \123 is likely to be octal - 123 (cf \0123, which is octal 012 followed by the literal 3). If the octal - value is greater than 377, the least significant 8 bits are taken. Inside a - character class, \ followed by a digit is always an octal number. */ - - case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: case CHAR_5: - case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9: - - if (!isclass) - { - oldptr = ptr; - /* The integer range is limited by the machine's int representation. */ - c -= CHAR_0; - while (IS_DIGIT(ptr[1])) - { - if (((unsigned int)c) > INT_MAX / 10) /* Integer overflow */ - { - c = -1; - break; - } - c = c * 10 + *(++ptr) - CHAR_0; - } - if (((unsigned int)c) > INT_MAX) /* Integer overflow */ - { - while (IS_DIGIT(ptr[1])) - ptr++; - *errorcodeptr = ERR61; - break; - } - if (c < 10 || c <= bracount) - { - c = -(ESC_REF + c); - break; - } - ptr = oldptr; /* Put the pointer back and fall through */ - } - - /* Handle an octal number following \. If the first digit is 8 or 9, Perl - generates a binary zero byte and treats the digit as a following literal. - Thus we have to pull back the pointer by one. */ - - if ((c = *ptr) >= CHAR_8) - { - ptr--; - c = 0; - break; - } - - /* \0 always starts an octal number, but we may drop through to here with a - larger first octal digit. The original code used just to take the least - significant 8 bits of octal numbers (I think this is what early Perls used - to do). Nowadays we allow for larger numbers in UTF-8 mode and 16-bit mode, - but no more than 3 octal digits. */ - - case CHAR_0: - c -= CHAR_0; - while(i++ < 2 && ptr[1] >= CHAR_0 && ptr[1] <= CHAR_7) - c = c * 8 + *(++ptr) - CHAR_0; -#ifdef COMPILE_PCRE8 - if (!utf && c > 0xff) *errorcodeptr = ERR51; -#endif - break; - - /* \x is complicated. \x{ddd} is a character number which can be greater - than 0xff in utf or non-8bit mode, but only if the ddd are hex digits. - If not, { is treated as a data character. */ - - case CHAR_x: - if ((options & PCRE_JAVASCRIPT_COMPAT) != 0) - { - /* In JavaScript, \x must be followed by two hexadecimal numbers. - Otherwise it is a lowercase x letter. */ - if (MAX_255(ptr[1]) && g_ascii_isxdigit(ptr[1]) != 0 - && MAX_255(ptr[2]) && g_ascii_isxdigit(ptr[2]) != 0) - { - c = 0; - for (i = 0; i < 2; ++i) - { - int cc = *(++ptr); -#ifndef EBCDIC /* ASCII/UTF-8 coding */ - if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ - c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); -#else /* EBCDIC coding */ - if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */ - c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); -#endif - } - } - break; - } - - if (ptr[1] == CHAR_LEFT_CURLY_BRACKET) - { - const pcre_uchar *pt = ptr + 2; - - c = 0; - while (MAX_255(*pt) && g_ascii_isxdigit(*pt) != 0) - { - int cc = *pt++; - if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */ - -#ifndef EBCDIC /* ASCII/UTF-8 coding */ - if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ - c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); -#else /* EBCDIC coding */ - if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */ - c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); -#endif - -#ifdef COMPILE_PCRE8 - if (c > (utf ? 0x10ffff : 0xff)) { c = -1; break; } -#else -#ifdef COMPILE_PCRE16 - if (c > (utf ? 0x10ffff : 0xffff)) { c = -1; break; } -#endif -#endif - } - - if (c < 0) - { - while (MAX_255(*pt) && g_ascii_isxdigit(*pt) != 0) pt++; - *errorcodeptr = ERR34; - } - - if (*pt == CHAR_RIGHT_CURLY_BRACKET) - { - if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73; - ptr = pt; - break; - } - - /* If the sequence of hex digits does not end with '}', then we don't - recognize this construct; fall through to the normal \x handling. */ - } - - /* Read just a single-byte hex-defined char */ - - c = 0; - while (i++ < 2 && MAX_255(ptr[1]) && g_ascii_isxdigit(ptr[1]) != 0) - { - int cc; /* Some compilers don't like */ - cc = *(++ptr); /* ++ in initializers */ -#ifndef EBCDIC /* ASCII/UTF-8 coding */ - if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ - c = c * 16 + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); -#else /* EBCDIC coding */ - if (cc <= CHAR_z) cc += 64; /* Convert to upper case */ - c = c * 16 + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); -#endif - } - break; - - /* For \c, a following letter is upper-cased; then the 0x40 bit is flipped. - An error is given if the byte following \c is not an ASCII character. This - coding is ASCII-specific, but then the whole concept of \cx is - ASCII-specific. (However, an EBCDIC equivalent has now been added.) */ - - case CHAR_c: - c = *(++ptr); - if (c == 0) - { - *errorcodeptr = ERR2; - break; - } -#ifndef EBCDIC /* ASCII/UTF-8 coding */ - if (c > 127) /* Excludes all non-ASCII in either mode */ - { - *errorcodeptr = ERR68; - break; - } - if (c >= CHAR_a && c <= CHAR_z) c -= 32; - c ^= 0x40; -#else /* EBCDIC coding */ - if (c >= CHAR_a && c <= CHAR_z) c += 64; - c ^= 0xC0; -#endif - break; - - /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any - other alphanumeric following \ is an error if PCRE_EXTRA was set; - otherwise, for Perl compatibility, it is a literal. This code looks a bit - odd, but there used to be some cases other than the default, and there may - be again in future, so I haven't "optimized" it. */ - - default: - if ((options & PCRE_EXTRA) != 0) switch(c) - { - default: - *errorcodeptr = ERR3; - break; - } - break; - } - } - -/* Perl supports \N{name} for character names, as well as plain \N for "not -newline". PCRE does not support \N{name}. However, it does support -quantification such as \N{2,3}. */ - -if (c == -ESC_N && ptr[1] == CHAR_LEFT_CURLY_BRACKET && - !is_counted_repeat(ptr+2)) - *errorcodeptr = ERR37; - -/* If PCRE_UCP is set, we change the values for \d etc. */ - -if ((options & PCRE_UCP) != 0 && c <= -ESC_D && c >= -ESC_w) - c -= (ESC_DU - ESC_D); - -/* Set the pointer to the final character before returning. */ - -*ptrptr = ptr; -return c; -} - - - -#ifdef SUPPORT_UCP -/************************************************* -* Handle \P and \p * -*************************************************/ - -/* This function is called after \P or \p has been encountered, provided that -PCRE is compiled with support for Unicode properties. On entry, ptrptr is -pointing at the P or p. On exit, it is pointing at the final character of the -escape sequence. - -Argument: - ptrptr points to the pattern position pointer - negptr points to a boolean that is set TRUE for negation else FALSE - dptr points to an int that is set to the detailed property value - errorcodeptr points to the error code variable - -Returns: type value from ucp_type_table, or -1 for an invalid type -*/ - -static int -get_ucp(const pcre_uchar **ptrptr, BOOL *negptr, int *dptr, int *errorcodeptr) -{ -int c, i, bot, top; -const pcre_uchar *ptr = *ptrptr; -pcre_uchar name[32]; - -c = *(++ptr); -if (c == 0) goto ERROR_RETURN; - -*negptr = FALSE; - -/* \P or \p can be followed by a name in {}, optionally preceded by ^ for -negation. */ - -if (c == CHAR_LEFT_CURLY_BRACKET) - { - if (ptr[1] == CHAR_CIRCUMFLEX_ACCENT) - { - *negptr = TRUE; - ptr++; - } - for (i = 0; i < (int)(sizeof(name) / sizeof(pcre_uchar)) - 1; i++) - { - c = *(++ptr); - if (c == 0) goto ERROR_RETURN; - if (c == CHAR_RIGHT_CURLY_BRACKET) break; - name[i] = c; - } - if (c != CHAR_RIGHT_CURLY_BRACKET) goto ERROR_RETURN; - name[i] = 0; - } - -/* Otherwise there is just one following character */ - -else - { - name[0] = c; - name[1] = 0; - } - -*ptrptr = ptr; - -/* Search for a recognized property name using binary chop */ - -bot = 0; -top = PRIV(utt_size); - -while (bot < top) - { - i = (bot + top) >> 1; - c = STRCMP_UC_C8(name, PRIV(utt_names) + PRIV(utt)[i].name_offset); - if (c == 0) - { - *dptr = PRIV(utt)[i].value; - return PRIV(utt)[i].type; - } - if (c > 0) bot = i + 1; else top = i; - } - -*errorcodeptr = ERR47; -*ptrptr = ptr; -return -1; - -ERROR_RETURN: -*errorcodeptr = ERR46; -*ptrptr = ptr; -return -1; -} -#endif - - - - -/************************************************* -* Read repeat counts * -*************************************************/ - -/* Read an item of the form {n,m} and return the values. This is called only -after is_counted_repeat() has confirmed that a repeat-count quantifier exists, -so the syntax is guaranteed to be correct, but we need to check the values. - -Arguments: - p pointer to first char after '{' - minp pointer to int for min - maxp pointer to int for max - returned as -1 if no max - errorcodeptr points to error code variable - -Returns: pointer to '}' on success; - current ptr on error, with errorcodeptr set non-zero -*/ - -static const pcre_uchar * -read_repeat_counts(const pcre_uchar *p, int *minp, int *maxp, int *errorcodeptr) -{ -int min = 0; -int max = -1; - -/* Read the minimum value and do a paranoid check: a negative value indicates -an integer overflow. */ - -while (IS_DIGIT(*p)) min = min * 10 + *p++ - CHAR_0; -if (min < 0 || min > 65535) - { - *errorcodeptr = ERR5; - return p; - } - -/* Read the maximum value if there is one, and again do a paranoid on its size. -Also, max must not be less than min. */ - -if (*p == CHAR_RIGHT_CURLY_BRACKET) max = min; else - { - if (*(++p) != CHAR_RIGHT_CURLY_BRACKET) - { - max = 0; - while(IS_DIGIT(*p)) max = max * 10 + *p++ - CHAR_0; - if (max < 0 || max > 65535) - { - *errorcodeptr = ERR5; - return p; - } - if (max < min) - { - *errorcodeptr = ERR4; - return p; - } - } - } - -/* Fill in the required variables, and pass back the pointer to the terminating -'}'. */ - -*minp = min; -*maxp = max; -return p; -} - - - -/************************************************* -* Subroutine for finding forward reference * -*************************************************/ - -/* This recursive function is called only from find_parens() below. The -top-level call starts at the beginning of the pattern. All other calls must -start at a parenthesis. It scans along a pattern's text looking for capturing -subpatterns, and counting them. If it finds a named pattern that matches the -name it is given, it returns its number. Alternatively, if the name is NULL, it -returns when it reaches a given numbered subpattern. Recursion is used to keep -track of subpatterns that reset the capturing group numbers - the (?| feature. - -This function was originally called only from the second pass, in which we know -that if (?< or (?' or (?P< is encountered, the name will be correctly -terminated because that is checked in the first pass. There is now one call to -this function in the first pass, to check for a recursive back reference by -name (so that we can make the whole group atomic). In this case, we need check -only up to the current position in the pattern, and that is still OK because -and previous occurrences will have been checked. To make this work, the test -for "end of pattern" is a check against cd->end_pattern in the main loop, -instead of looking for a binary zero. This means that the special first-pass -call can adjust cd->end_pattern temporarily. (Checks for binary zero while -processing items within the loop are OK, because afterwards the main loop will -terminate.) - -Arguments: - ptrptr address of the current character pointer (updated) - cd compile background data - name name to seek, or NULL if seeking a numbered subpattern - lorn name length, or subpattern number if name is NULL - xmode TRUE if we are in /x mode - utf TRUE if we are in UTF-8 / UTF-16 mode - count pointer to the current capturing subpattern number (updated) - -Returns: the number of the named subpattern, or -1 if not found -*/ - -static int -find_parens_sub(pcre_uchar **ptrptr, compile_data *cd, const pcre_uchar *name, int lorn, - BOOL xmode, BOOL utf, int *count) -{ -pcre_uchar *ptr = *ptrptr; -int start_count = *count; -int hwm_count = start_count; -BOOL dup_parens = FALSE; - -/* If the first character is a parenthesis, check on the type of group we are -dealing with. The very first call may not start with a parenthesis. */ - -if (ptr[0] == CHAR_LEFT_PARENTHESIS) - { - /* Handle specials such as (*SKIP) or (*UTF8) etc. */ - - if (ptr[1] == CHAR_ASTERISK) ptr += 2; - - /* Handle a normal, unnamed capturing parenthesis. */ - - else if (ptr[1] != CHAR_QUESTION_MARK) - { - *count += 1; - if (name == NULL && *count == lorn) return *count; - ptr++; - } - - /* All cases now have (? at the start. Remember when we are in a group - where the parenthesis numbers are duplicated. */ - - else if (ptr[2] == CHAR_VERTICAL_LINE) - { - ptr += 3; - dup_parens = TRUE; - } - - /* Handle comments; all characters are allowed until a ket is reached. */ - - else if (ptr[2] == CHAR_NUMBER_SIGN) - { - for (ptr += 3; *ptr != 0; ptr++) if (*ptr == CHAR_RIGHT_PARENTHESIS) break; - goto FAIL_EXIT; - } - - /* Handle a condition. If it is an assertion, just carry on so that it - is processed as normal. If not, skip to the closing parenthesis of the - condition (there can't be any nested parens). */ - - else if (ptr[2] == CHAR_LEFT_PARENTHESIS) - { - ptr += 2; - if (ptr[1] != CHAR_QUESTION_MARK) - { - while (*ptr != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; - if (*ptr != 0) ptr++; - } - } - - /* Start with (? but not a condition. */ - - else - { - ptr += 2; - if (*ptr == CHAR_P) ptr++; /* Allow optional P */ - - /* We have to disambiguate (?<! and (?<= from (?<name> for named groups */ - - if ((*ptr == CHAR_LESS_THAN_SIGN && ptr[1] != CHAR_EXCLAMATION_MARK && - ptr[1] != CHAR_EQUALS_SIGN) || *ptr == CHAR_APOSTROPHE) - { - int term; - const pcre_uchar *thisname; - *count += 1; - if (name == NULL && *count == lorn) return *count; - term = *ptr++; - if (term == CHAR_LESS_THAN_SIGN) term = CHAR_GREATER_THAN_SIGN; - thisname = ptr; - while (*ptr != term) ptr++; - if (name != NULL && lorn == ptr - thisname && - STRNCMP_UC_UC(name, thisname, lorn) == 0) - return *count; - term++; - } - } - } - -/* Past any initial parenthesis handling, scan for parentheses or vertical -bars. Stop if we get to cd->end_pattern. Note that this is important for the -first-pass call when this value is temporarily adjusted to stop at the current -position. So DO NOT change this to a test for binary zero. */ - -for (; ptr < cd->end_pattern; ptr++) - { - /* Skip over backslashed characters and also entire \Q...\E */ - - if (*ptr == CHAR_BACKSLASH) - { - if (*(++ptr) == 0) goto FAIL_EXIT; - if (*ptr == CHAR_Q) for (;;) - { - while (*(++ptr) != 0 && *ptr != CHAR_BACKSLASH) {}; - if (*ptr == 0) goto FAIL_EXIT; - if (*(++ptr) == CHAR_E) break; - } - continue; - } - - /* Skip over character classes; this logic must be similar to the way they - are handled for real. If the first character is '^', skip it. Also, if the - first few characters (either before or after ^) are \Q\E or \E we skip them - too. This makes for compatibility with Perl. Note the use of STR macros to - encode "Q\\E" so that it works in UTF-8 on EBCDIC platforms. */ - - if (*ptr == CHAR_LEFT_SQUARE_BRACKET) - { - BOOL negate_class = FALSE; - for (;;) - { - if (ptr[1] == CHAR_BACKSLASH) - { - if (ptr[2] == CHAR_E) - ptr+= 2; - else if (STRNCMP_UC_C8(ptr + 2, - STR_Q STR_BACKSLASH STR_E, 3) == 0) - ptr += 4; - else - break; - } - else if (!negate_class && ptr[1] == CHAR_CIRCUMFLEX_ACCENT) - { - negate_class = TRUE; - ptr++; - } - else break; - } - - /* If the next character is ']', it is a data character that must be - skipped, except in JavaScript compatibility mode. */ - - if (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET && - (cd->external_options & PCRE_JAVASCRIPT_COMPAT) == 0) - ptr++; - - while (*(++ptr) != CHAR_RIGHT_SQUARE_BRACKET) - { - if (*ptr == 0) return -1; - if (*ptr == CHAR_BACKSLASH) - { - if (*(++ptr) == 0) goto FAIL_EXIT; - if (*ptr == CHAR_Q) for (;;) - { - while (*(++ptr) != 0 && *ptr != CHAR_BACKSLASH) {}; - if (*ptr == 0) goto FAIL_EXIT; - if (*(++ptr) == CHAR_E) break; - } - continue; - } - } - continue; - } - - /* Skip comments in /x mode */ - - if (xmode && *ptr == CHAR_NUMBER_SIGN) - { - ptr++; - while (*ptr != 0) - { - if (IS_NEWLINE(ptr)) { ptr += cd->nllen - 1; break; } - ptr++; -#ifdef SUPPORT_UTF - if (utf) FORWARDCHAR(ptr); -#endif - } - if (*ptr == 0) goto FAIL_EXIT; - continue; - } - - /* Check for the special metacharacters */ - - if (*ptr == CHAR_LEFT_PARENTHESIS) - { - int rc = find_parens_sub(&ptr, cd, name, lorn, xmode, utf, count); - if (rc > 0) return rc; - if (*ptr == 0) goto FAIL_EXIT; - } - - else if (*ptr == CHAR_RIGHT_PARENTHESIS) - { - if (dup_parens && *count < hwm_count) *count = hwm_count; - goto FAIL_EXIT; - } - - else if (*ptr == CHAR_VERTICAL_LINE && dup_parens) - { - if (*count > hwm_count) hwm_count = *count; - *count = start_count; - } - } - -FAIL_EXIT: -*ptrptr = ptr; -return -1; -} - - - - -/************************************************* -* Find forward referenced subpattern * -*************************************************/ - -/* This function scans along a pattern's text looking for capturing -subpatterns, and counting them. If it finds a named pattern that matches the -name it is given, it returns its number. Alternatively, if the name is NULL, it -returns when it reaches a given numbered subpattern. This is used for forward -references to subpatterns. We used to be able to start this scan from the -current compiling point, using the current count value from cd->bracount, and -do it all in a single loop, but the addition of the possibility of duplicate -subpattern numbers means that we have to scan from the very start, in order to -take account of such duplicates, and to use a recursive function to keep track -of the different types of group. - -Arguments: - cd compile background data - name name to seek, or NULL if seeking a numbered subpattern - lorn name length, or subpattern number if name is NULL - xmode TRUE if we are in /x mode - utf TRUE if we are in UTF-8 / UTF-16 mode - -Returns: the number of the found subpattern, or -1 if not found -*/ - -static int -find_parens(compile_data *cd, const pcre_uchar *name, int lorn, BOOL xmode, - BOOL utf) -{ -pcre_uchar *ptr = (pcre_uchar *)cd->start_pattern; -int count = 0; -int rc; - -/* If the pattern does not start with an opening parenthesis, the first call -to find_parens_sub() will scan right to the end (if necessary). However, if it -does start with a parenthesis, find_parens_sub() will return when it hits the -matching closing parens. That is why we have to have a loop. */ - -for (;;) - { - rc = find_parens_sub(&ptr, cd, name, lorn, xmode, utf, &count); - if (rc > 0 || *ptr++ == 0) break; - } - -return rc; -} - - - - -/************************************************* -* Find first significant op code * -*************************************************/ - -/* This is called by several functions that scan a compiled expression looking -for a fixed first character, or an anchoring op code etc. It skips over things -that do not influence this. For some calls, it makes sense to skip negative -forward and all backward assertions, and also the \b assertion; for others it -does not. - -Arguments: - code pointer to the start of the group - skipassert TRUE if certain assertions are to be skipped - -Returns: pointer to the first significant opcode -*/ - -static const pcre_uchar* -first_significant_code(const pcre_uchar *code, BOOL skipassert) -{ -for (;;) - { - switch ((int)*code) - { - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - if (!skipassert) return code; - do code += GET(code, 1); while (*code == OP_ALT); - code += PRIV(OP_lengths)[*code]; - break; - - case OP_WORD_BOUNDARY: - case OP_NOT_WORD_BOUNDARY: - if (!skipassert) return code; - /* Fall through */ - - case OP_CALLOUT: - case OP_CREF: - case OP_NCREF: - case OP_RREF: - case OP_NRREF: - case OP_DEF: - code += PRIV(OP_lengths)[*code]; - break; - - default: - return code; - } - } -/* Control never reaches here */ -} - - - - -/************************************************* -* Find the fixed length of a branch * -*************************************************/ - -/* Scan a branch and compute the fixed length of subject that will match it, -if the length is fixed. This is needed for dealing with backward assertions. -In UTF8 mode, the result is in characters rather than bytes. The branch is -temporarily terminated with OP_END when this function is called. - -This function is called when a backward assertion is encountered, so that if it -fails, the error message can point to the correct place in the pattern. -However, we cannot do this when the assertion contains subroutine calls, -because they can be forward references. We solve this by remembering this case -and doing the check at the end; a flag specifies which mode we are running in. - -Arguments: - code points to the start of the pattern (the bracket) - utf TRUE in UTF-8 / UTF-16 mode - atend TRUE if called when the pattern is complete - cd the "compile data" structure - -Returns: the fixed length, - or -1 if there is no fixed length, - or -2 if \C was encountered (in UTF-8 mode only) - or -3 if an OP_RECURSE item was encountered and atend is FALSE - or -4 if an unknown opcode was encountered (internal error) -*/ - -static int -find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd) -{ -int length = -1; - -int branchlength = 0; -pcre_uchar *cc = code + 1 + LINK_SIZE; - -/* Scan along the opcodes for this branch. If we get to the end of the -branch, check the length against that of the other branches. */ - -for (;;) - { - int d; - pcre_uchar *ce, *cs; - int op = *cc; - - switch (op) - { - /* We only need to continue for OP_CBRA (normal capturing bracket) and - OP_BRA (normal non-capturing bracket) because the other variants of these - opcodes are all concerned with unlimited repeated groups, which of course - are not of fixed length. */ - - case OP_CBRA: - case OP_BRA: - case OP_ONCE: - case OP_ONCE_NC: - case OP_COND: - d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd); - if (d < 0) return d; - branchlength += d; - do cc += GET(cc, 1); while (*cc == OP_ALT); - cc += 1 + LINK_SIZE; - break; - - /* Reached end of a branch; if it's a ket it is the end of a nested call. - If it's ALT it is an alternation in a nested call. An ACCEPT is effectively - an ALT. If it is END it's the end of the outer call. All can be handled by - the same code. Note that we must not include the OP_KETRxxx opcodes here, - because they all imply an unlimited repeat. */ - - case OP_ALT: - case OP_KET: - case OP_END: - case OP_ACCEPT: - case OP_ASSERT_ACCEPT: - if (length < 0) length = branchlength; - else if (length != branchlength) return -1; - if (*cc != OP_ALT) return length; - cc += 1 + LINK_SIZE; - branchlength = 0; - break; - - /* A true recursion implies not fixed length, but a subroutine call may - be OK. If the subroutine is a forward reference, we can't deal with - it until the end of the pattern, so return -3. */ - - case OP_RECURSE: - if (!atend) return -3; - cs = ce = (pcre_uchar *)cd->start_code + GET(cc, 1); /* Start subpattern */ - do ce += GET(ce, 1); while (*ce == OP_ALT); /* End subpattern */ - if (cc > cs && cc < ce) return -1; /* Recursion */ - d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd); - if (d < 0) return d; - branchlength += d; - cc += 1 + LINK_SIZE; - break; - - /* Skip over assertive subpatterns */ - - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - do cc += GET(cc, 1); while (*cc == OP_ALT); - cc += PRIV(OP_lengths)[*cc]; - break; - - /* Skip over things that don't match chars */ - - case OP_MARK: - case OP_PRUNE_ARG: - case OP_SKIP_ARG: - case OP_THEN_ARG: - cc += cc[1] + PRIV(OP_lengths)[*cc]; - break; - - case OP_CALLOUT: - case OP_CIRC: - case OP_CIRCM: - case OP_CLOSE: - case OP_COMMIT: - case OP_CREF: - case OP_DEF: - case OP_DOLL: - case OP_DOLLM: - case OP_EOD: - case OP_EODN: - case OP_FAIL: - case OP_NCREF: - case OP_NRREF: - case OP_NOT_WORD_BOUNDARY: - case OP_PRUNE: - case OP_REVERSE: - case OP_RREF: - case OP_SET_SOM: - case OP_SKIP: - case OP_SOD: - case OP_SOM: - case OP_THEN: - case OP_WORD_BOUNDARY: - cc += PRIV(OP_lengths)[*cc]; - break; - - /* Handle literal characters */ - - case OP_CHAR: - case OP_CHARI: - case OP_NOT: - case OP_NOTI: - branchlength++; - cc += 2; -#ifdef SUPPORT_UTF - if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); -#endif - break; - - /* Handle exact repetitions. The count is already in characters, but we - need to skip over a multibyte character in UTF8 mode. */ - - case OP_EXACT: - case OP_EXACTI: - case OP_NOTEXACT: - case OP_NOTEXACTI: - branchlength += GET2(cc,1); - cc += 2 + IMM2_SIZE; -#ifdef SUPPORT_UTF - if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); -#endif - break; - - case OP_TYPEEXACT: - branchlength += GET2(cc,1); - if (cc[1 + IMM2_SIZE] == OP_PROP || cc[1 + IMM2_SIZE] == OP_NOTPROP) cc += 2; - cc += 1 + IMM2_SIZE + 1; - break; - - /* Handle single-char matchers */ - - case OP_PROP: - case OP_NOTPROP: - cc += 2; - /* Fall through */ - - case OP_HSPACE: - case OP_VSPACE: - case OP_NOT_HSPACE: - case OP_NOT_VSPACE: - case OP_NOT_DIGIT: - case OP_DIGIT: - case OP_NOT_WHITESPACE: - case OP_WHITESPACE: - case OP_NOT_WORDCHAR: - case OP_WORDCHAR: - case OP_ANY: - case OP_ALLANY: - branchlength++; - cc++; - break; - - /* The single-byte matcher isn't allowed. This only happens in UTF-8 mode; - otherwise \C is coded as OP_ALLANY. */ - - case OP_ANYBYTE: - return -2; - - /* Check a class for variable quantification */ - -#if defined SUPPORT_UTF || defined COMPILE_PCRE16 - case OP_XCLASS: - cc += GET(cc, 1) - PRIV(OP_lengths)[OP_CLASS]; - /* Fall through */ -#endif - - case OP_CLASS: - case OP_NCLASS: - cc += PRIV(OP_lengths)[OP_CLASS]; - - switch (*cc) - { - case OP_CRPLUS: - case OP_CRMINPLUS: - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRQUERY: - case OP_CRMINQUERY: - return -1; - - case OP_CRRANGE: - case OP_CRMINRANGE: - if (GET2(cc,1) != GET2(cc,1+IMM2_SIZE)) return -1; - branchlength += GET2(cc,1); - cc += 1 + 2 * IMM2_SIZE; - break; - - default: - branchlength++; - } - break; - - /* Anything else is variable length */ - - case OP_ANYNL: - case OP_BRAMINZERO: - case OP_BRAPOS: - case OP_BRAPOSZERO: - case OP_BRAZERO: - case OP_CBRAPOS: - case OP_EXTUNI: - case OP_KETRMAX: - case OP_KETRMIN: - case OP_KETRPOS: - case OP_MINPLUS: - case OP_MINPLUSI: - case OP_MINQUERY: - case OP_MINQUERYI: - case OP_MINSTAR: - case OP_MINSTARI: - case OP_MINUPTO: - case OP_MINUPTOI: - case OP_NOTMINPLUS: - case OP_NOTMINPLUSI: - case OP_NOTMINQUERY: - case OP_NOTMINQUERYI: - case OP_NOTMINSTAR: - case OP_NOTMINSTARI: - case OP_NOTMINUPTO: - case OP_NOTMINUPTOI: - case OP_NOTPLUS: - case OP_NOTPLUSI: - case OP_NOTPOSPLUS: - case OP_NOTPOSPLUSI: - case OP_NOTPOSQUERY: - case OP_NOTPOSQUERYI: - case OP_NOTPOSSTAR: - case OP_NOTPOSSTARI: - case OP_NOTPOSUPTO: - case OP_NOTPOSUPTOI: - case OP_NOTQUERY: - case OP_NOTQUERYI: - case OP_NOTSTAR: - case OP_NOTSTARI: - case OP_NOTUPTO: - case OP_NOTUPTOI: - case OP_PLUS: - case OP_PLUSI: - case OP_POSPLUS: - case OP_POSPLUSI: - case OP_POSQUERY: - case OP_POSQUERYI: - case OP_POSSTAR: - case OP_POSSTARI: - case OP_POSUPTO: - case OP_POSUPTOI: - case OP_QUERY: - case OP_QUERYI: - case OP_REF: - case OP_REFI: - case OP_SBRA: - case OP_SBRAPOS: - case OP_SCBRA: - case OP_SCBRAPOS: - case OP_SCOND: - case OP_SKIPZERO: - case OP_STAR: - case OP_STARI: - case OP_TYPEMINPLUS: - case OP_TYPEMINQUERY: - case OP_TYPEMINSTAR: - case OP_TYPEMINUPTO: - case OP_TYPEPLUS: - case OP_TYPEPOSPLUS: - case OP_TYPEPOSQUERY: - case OP_TYPEPOSSTAR: - case OP_TYPEPOSUPTO: - case OP_TYPEQUERY: - case OP_TYPESTAR: - case OP_TYPEUPTO: - case OP_UPTO: - case OP_UPTOI: - return -1; - - /* Catch unrecognized opcodes so that when new ones are added they - are not forgotten, as has happened in the past. */ - - default: - return -4; - } - } -/* Control never gets here */ -} - - - - -/************************************************* -* Scan compiled regex for specific bracket * -*************************************************/ - -/* This little function scans through a compiled pattern until it finds a -capturing bracket with the given number, or, if the number is negative, an -instance of OP_REVERSE for a lookbehind. The function is global in the C sense -so that it can be called from pcre_study() when finding the minimum matching -length. - -Arguments: - code points to start of expression - utf TRUE in UTF-8 / UTF-16 mode - number the required bracket number or negative to find a lookbehind - -Returns: pointer to the opcode for the bracket, or NULL if not found -*/ - -const pcre_uchar * -PRIV(find_bracket)(const pcre_uchar *code, BOOL utf, int number) -{ -for (;;) - { - int c = *code; - - if (c == OP_END) return NULL; - - /* XCLASS is used for classes that cannot be represented just by a bit - map. This includes negated single high-valued characters. The length in - the table is zero; the actual length is stored in the compiled code. */ - - if (c == OP_XCLASS) code += GET(code, 1); - - /* Handle recursion */ - - else if (c == OP_REVERSE) - { - if (number < 0) return (pcre_uchar *)code; - code += PRIV(OP_lengths)[c]; - } - - /* Handle capturing bracket */ - - else if (c == OP_CBRA || c == OP_SCBRA || - c == OP_CBRAPOS || c == OP_SCBRAPOS) - { - int n = GET2(code, 1+LINK_SIZE); - if (n == number) return (pcre_uchar *)code; - code += PRIV(OP_lengths)[c]; - } - - /* Otherwise, we can get the item's length from the table, except that for - repeated character types, we have to test for \p and \P, which have an extra - two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we - must add in its length. */ - - else - { - switch(c) - { - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEQUERY: - case OP_TYPEMINQUERY: - case OP_TYPEPOSSTAR: - case OP_TYPEPOSPLUS: - case OP_TYPEPOSQUERY: - if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2; - break; - - case OP_TYPEUPTO: - case OP_TYPEMINUPTO: - case OP_TYPEEXACT: - case OP_TYPEPOSUPTO: - if (code[1 + IMM2_SIZE] == OP_PROP - || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2; - break; - - case OP_MARK: - case OP_PRUNE_ARG: - case OP_SKIP_ARG: - code += code[1]; - break; - - case OP_THEN_ARG: - code += code[1]; - break; - } - - /* Add in the fixed length from the table */ - - code += PRIV(OP_lengths)[c]; - - /* In UTF-8 mode, opcodes that are followed by a character may be followed by - a multi-byte character. The length in the table is a minimum, so we have to - arrange to skip the extra bytes. */ - -#ifdef SUPPORT_UTF - if (utf) switch(c) - { - case OP_CHAR: - case OP_CHARI: - case OP_EXACT: - case OP_EXACTI: - case OP_UPTO: - case OP_UPTOI: - case OP_MINUPTO: - case OP_MINUPTOI: - case OP_POSUPTO: - case OP_POSUPTOI: - case OP_STAR: - case OP_STARI: - case OP_MINSTAR: - case OP_MINSTARI: - case OP_POSSTAR: - case OP_POSSTARI: - case OP_PLUS: - case OP_PLUSI: - case OP_MINPLUS: - case OP_MINPLUSI: - case OP_POSPLUS: - case OP_POSPLUSI: - case OP_QUERY: - case OP_QUERYI: - case OP_MINQUERY: - case OP_MINQUERYI: - case OP_POSQUERY: - case OP_POSQUERYI: - if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]); - break; - } -#else - (void)(utf); /* Keep compiler happy by referencing function argument */ -#endif - } - } -} - - - -/************************************************* -* Scan compiled regex for recursion reference * -*************************************************/ - -/* This little function scans through a compiled pattern until it finds an -instance of OP_RECURSE. - -Arguments: - code points to start of expression - utf TRUE in UTF-8 / UTF-16 mode - -Returns: pointer to the opcode for OP_RECURSE, or NULL if not found -*/ - -static const pcre_uchar * -find_recurse(const pcre_uchar *code, BOOL utf) -{ -for (;;) - { - int c = *code; - if (c == OP_END) return NULL; - if (c == OP_RECURSE) return code; - - /* XCLASS is used for classes that cannot be represented just by a bit - map. This includes negated single high-valued characters. The length in - the table is zero; the actual length is stored in the compiled code. */ - - if (c == OP_XCLASS) code += GET(code, 1); - - /* Otherwise, we can get the item's length from the table, except that for - repeated character types, we have to test for \p and \P, which have an extra - two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we - must add in its length. */ - - else - { - switch(c) - { - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEQUERY: - case OP_TYPEMINQUERY: - case OP_TYPEPOSSTAR: - case OP_TYPEPOSPLUS: - case OP_TYPEPOSQUERY: - if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2; - break; - - case OP_TYPEPOSUPTO: - case OP_TYPEUPTO: - case OP_TYPEMINUPTO: - case OP_TYPEEXACT: - if (code[1 + IMM2_SIZE] == OP_PROP - || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2; - break; - - case OP_MARK: - case OP_PRUNE_ARG: - case OP_SKIP_ARG: - code += code[1]; - break; - - case OP_THEN_ARG: - code += code[1]; - break; - } - - /* Add in the fixed length from the table */ - - code += PRIV(OP_lengths)[c]; - - /* In UTF-8 mode, opcodes that are followed by a character may be followed - by a multi-byte character. The length in the table is a minimum, so we have - to arrange to skip the extra bytes. */ - -#ifdef SUPPORT_UTF - if (utf) switch(c) - { - case OP_CHAR: - case OP_CHARI: - case OP_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 - } - } -} - - - -/************************************************* -* Scan compiled branch for non-emptiness * -*************************************************/ - -/* This function scans through a branch of a compiled pattern to see whether it -can match the empty string or not. It is called from could_be_empty() -below and from compile_branch() when checking for an unlimited repeat of a -group that can match nothing. Note that first_significant_code() skips over -backward and negative forward assertions when its final argument is TRUE. If we -hit an unclosed bracket, we return "empty" - this means we've struck an inner -bracket whose current branch will already have been scanned. - -Arguments: - code points to start of search - endcode points to where to stop - utf TRUE if in UTF-8 / UTF-16 mode - cd contains pointers to tables etc. - -Returns: TRUE if what is matched could be empty -*/ - -static BOOL -could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode, - BOOL utf, compile_data *cd) -{ -int c; -for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE); - code < endcode; - code = first_significant_code(code + PRIV(OP_lengths)[c], TRUE)) - { - const pcre_uchar *ccode; - - c = *code; - - /* Skip over forward assertions; the other assertions are skipped by - first_significant_code() with a TRUE final argument. */ - - if (c == OP_ASSERT) - { - do code += GET(code, 1); while (*code == OP_ALT); - c = *code; - continue; - } - - /* For a recursion/subroutine call, if its end has been reached, which - implies a backward reference subroutine call, we can scan it. If it's a - forward reference subroutine call, we can't. To detect forward reference - we have to scan up the list that is kept in the workspace. This function is - called only when doing the real compile, not during the pre-compile that - measures the size of the compiled pattern. */ - - if (c == OP_RECURSE) - { - const pcre_uchar *scode; - BOOL empty_branch; - - /* Test for forward reference */ - - for (scode = cd->start_workspace; scode < cd->hwm; scode += LINK_SIZE) - if (GET(scode, 0) == code + 1 - cd->start_code) return TRUE; - - /* Not a forward reference, test for completed backward reference */ - - empty_branch = FALSE; - scode = cd->start_code + GET(code, 1); - if (GET(scode, 1) == 0) return TRUE; /* Unclosed */ - - /* Completed backwards reference */ - - do - { - if (could_be_empty_branch(scode, endcode, utf, cd)) - { - empty_branch = TRUE; - break; - } - scode += GET(scode, 1); - } - while (*scode == OP_ALT); - - if (!empty_branch) return FALSE; /* All branches are non-empty */ - continue; - } - - /* Groups with zero repeats can of course be empty; skip them. */ - - if (c == OP_BRAZERO || c == OP_BRAMINZERO || c == OP_SKIPZERO || - c == OP_BRAPOSZERO) - { - code += PRIV(OP_lengths)[c]; - do code += GET(code, 1); while (*code == OP_ALT); - c = *code; - continue; - } - - /* A nested group that is already marked as "could be empty" can just be - skipped. */ - - if (c == OP_SBRA || c == OP_SBRAPOS || - c == OP_SCBRA || c == OP_SCBRAPOS) - { - do code += GET(code, 1); while (*code == OP_ALT); - c = *code; - continue; - } - - /* For other groups, scan the branches. */ - - if (c == OP_BRA || c == OP_BRAPOS || - c == OP_CBRA || c == OP_CBRAPOS || - c == OP_ONCE || c == OP_ONCE_NC || - c == OP_COND) - { - BOOL empty_branch; - if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */ - - /* If a conditional group has only one branch, there is a second, implied, - empty branch, so just skip over the conditional, because it could be empty. - Otherwise, scan the individual branches of the group. */ - - if (c == OP_COND && code[GET(code, 1)] != OP_ALT) - code += GET(code, 1); - else - { - empty_branch = FALSE; - do - { - if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd)) - empty_branch = TRUE; - code += GET(code, 1); - } - while (*code == OP_ALT); - if (!empty_branch) return FALSE; /* All branches are non-empty */ - } - - c = *code; - continue; - } - - /* Handle the other opcodes */ - - switch (c) - { - /* Check for quantifiers after a class. XCLASS is used for classes that - cannot be represented just by a bit map. This includes negated single - high-valued characters. The length in PRIV(OP_lengths)[] is zero; the - actual length is stored in the compiled code, so we must update "code" - here. */ - -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - case OP_XCLASS: - ccode = code += GET(code, 1); - goto CHECK_CLASS_REPEAT; -#endif - - case OP_CLASS: - case OP_NCLASS: - ccode = code + PRIV(OP_lengths)[OP_CLASS]; - -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - CHECK_CLASS_REPEAT: -#endif - - switch (*ccode) - { - case OP_CRSTAR: /* These could be empty; continue */ - case OP_CRMINSTAR: - case OP_CRQUERY: - case OP_CRMINQUERY: - break; - - default: /* Non-repeat => class must match */ - case OP_CRPLUS: /* These repeats aren't empty */ - case OP_CRMINPLUS: - return FALSE; - - case OP_CRRANGE: - case OP_CRMINRANGE: - if (GET2(ccode, 1) > 0) return FALSE; /* Minimum > 0 */ - break; - } - break; - - /* Opcodes that must match a character */ - - case OP_PROP: - case OP_NOTPROP: - case OP_EXTUNI: - case OP_NOT_DIGIT: - case OP_DIGIT: - case OP_NOT_WHITESPACE: - case OP_WHITESPACE: - case OP_NOT_WORDCHAR: - case OP_WORDCHAR: - case OP_ANY: - case OP_ALLANY: - case OP_ANYBYTE: - case OP_CHAR: - case OP_CHARI: - case OP_NOT: - case OP_NOTI: - case OP_PLUS: - case OP_MINPLUS: - case OP_POSPLUS: - case OP_EXACT: - case OP_NOTPLUS: - case OP_NOTMINPLUS: - case OP_NOTPOSPLUS: - case OP_NOTEXACT: - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEPOSPLUS: - case OP_TYPEEXACT: - return FALSE; - - /* These are going to continue, as they may be empty, but we have to - fudge the length for the \p and \P cases. */ - - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEPOSSTAR: - case OP_TYPEQUERY: - case OP_TYPEMINQUERY: - case OP_TYPEPOSQUERY: - if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2; - break; - - /* Same for these */ - - case OP_TYPEUPTO: - case OP_TYPEMINUPTO: - case OP_TYPEPOSUPTO: - if (code[1 + IMM2_SIZE] == OP_PROP - || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2; - break; - - /* End of branch */ - - case OP_KET: - case OP_KETRMAX: - case OP_KETRMIN: - case OP_KETRPOS: - case OP_ALT: - return TRUE; - - /* In UTF-8 mode, STAR, MINSTAR, POSSTAR, QUERY, MINQUERY, POSQUERY, UPTO, - MINUPTO, and POSUPTO may be followed by a multibyte character */ - -#ifdef SUPPORT_UTF - case OP_STAR: - case OP_STARI: - case OP_MINSTAR: - case OP_MINSTARI: - case OP_POSSTAR: - case OP_POSSTARI: - case OP_QUERY: - case OP_QUERYI: - case OP_MINQUERY: - case OP_MINQUERYI: - case OP_POSQUERY: - case OP_POSQUERYI: - if (utf && HAS_EXTRALEN(code[1])) code += GET_EXTRALEN(code[1]); - break; - - case OP_UPTO: - case OP_UPTOI: - case OP_MINUPTO: - case OP_MINUPTOI: - case OP_POSUPTO: - case OP_POSUPTOI: - if (utf && HAS_EXTRALEN(code[1 + IMM2_SIZE])) code += GET_EXTRALEN(code[1 + IMM2_SIZE]); - break; -#endif - - /* MARK, and PRUNE/SKIP/THEN with an argument must skip over the argument - string. */ - - case OP_MARK: - case OP_PRUNE_ARG: - case OP_SKIP_ARG: - code += code[1]; - break; - - case OP_THEN_ARG: - code += code[1]; - break; - - /* None of the remaining opcodes are required to match a character. */ - - default: - break; - } - } - -return TRUE; -} - - - -/************************************************* -* Scan compiled regex for non-emptiness * -*************************************************/ - -/* This function is called to check for left recursive calls. We want to check -the current branch of the current pattern to see if it could match the empty -string. If it could, we must look outwards for branches at other levels, -stopping when we pass beyond the bracket which is the subject of the recursion. -This function is called only during the real compile, not during the -pre-compile. - -Arguments: - code points to start of the recursion - endcode points to where to stop (current RECURSE item) - bcptr points to the chain of current (unclosed) branch starts - utf TRUE if in UTF-8 / UTF-16 mode - cd pointers to tables etc - -Returns: TRUE if what is matched could be empty -*/ - -static BOOL -could_be_empty(const pcre_uchar *code, const pcre_uchar *endcode, - branch_chain *bcptr, BOOL utf, compile_data *cd) -{ -while (bcptr != NULL && bcptr->current_branch >= code) - { - if (!could_be_empty_branch(bcptr->current_branch, endcode, utf, cd)) - return FALSE; - bcptr = bcptr->outer; - } -return TRUE; -} - - - -/************************************************* -* Check for POSIX class syntax * -*************************************************/ - -/* This function is called when the sequence "[:" or "[." or "[=" is -encountered in a character class. It checks whether this is followed by a -sequence of characters terminated by a matching ":]" or ".]" or "=]". If we -reach an unescaped ']' without the special preceding character, return FALSE. - -Originally, this function only recognized a sequence of letters between the -terminators, but it seems that Perl recognizes any sequence of characters, -though of course unknown POSIX names are subsequently rejected. Perl gives an -"Unknown POSIX class" error for [:f\oo:] for example, where previously PCRE -didn't consider this to be a POSIX class. Likewise for [:1234:]. - -The problem in trying to be exactly like Perl is in the handling of escapes. We -have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX -class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code -below handles the special case of \], but does not try to do any other escape -processing. This makes it different from Perl for cases such as [:l\ower:] -where Perl recognizes it as the POSIX class "lower" but PCRE does not recognize -"l\ower". This is a lesser evil that not diagnosing bad classes when Perl does, -I think. - -A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not. -It seems that the appearance of a nested POSIX class supersedes an apparent -external class. For example, [:a[:digit:]b:] matches "a", "b", ":", or -a digit. - -In Perl, unescaped square brackets may also appear as part of class names. For -example, [:a[:abc]b:] gives unknown POSIX class "[:abc]b:]". However, for -[:a[:abc]b][b:] it gives unknown POSIX class "[:abc]b][b:]", which does not -seem right at all. PCRE does not allow closing square brackets in POSIX class -names. - -Arguments: - ptr pointer to the initial [ - endptr where to return the end pointer - -Returns: TRUE or FALSE -*/ - -static BOOL -check_posix_syntax(const pcre_uchar *ptr, const pcre_uchar **endptr) -{ -int terminator; /* Don't combine these lines; the Solaris cc */ -terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */ -for (++ptr; *ptr != 0; ptr++) - { - if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) - ptr++; - else if (*ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE; - else - { - if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) - { - *endptr = ptr; - return TRUE; - } - if (*ptr == CHAR_LEFT_SQUARE_BRACKET && - (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT || - ptr[1] == CHAR_EQUALS_SIGN) && - check_posix_syntax(ptr, endptr)) - return FALSE; - } - } -return FALSE; -} - - - - -/************************************************* -* Check POSIX class name * -*************************************************/ - -/* This function is called to check the name given in a POSIX-style class entry -such as [:alnum:]. - -Arguments: - ptr points to the first letter - len the length of the name - -Returns: a value representing the name, or -1 if unknown -*/ - -static int -check_posix_name(const pcre_uchar *ptr, int len) -{ -const char *pn = posix_names; -int yield = 0; -while (posix_name_lengths[yield] != 0) - { - if (len == posix_name_lengths[yield] && - STRNCMP_UC_C8(ptr, pn, len) == 0) return yield; - pn += posix_name_lengths[yield] + 1; - yield++; - } -return -1; -} - - -/************************************************* -* Adjust OP_RECURSE items in repeated group * -*************************************************/ - -/* OP_RECURSE items contain an offset from the start of the regex to the group -that is referenced. This means that groups can be replicated for fixed -repetition simply by copying (because the recursion is allowed to refer to -earlier groups that are outside the current group). However, when a group is -optional (i.e. the minimum quantifier is zero), OP_BRAZERO or OP_SKIPZERO is -inserted before it, after it has been compiled. This means that any OP_RECURSE -items within it that refer to the group itself or any contained groups have to -have their offsets adjusted. That one of the jobs of this function. Before it -is called, the partially compiled regex must be temporarily terminated with -OP_END. - -This function has been extended with the possibility of forward references for -recursions and subroutine calls. It must also check the list of such references -for the group we are dealing with. If it finds that one of the recursions in -the current group is on this list, it adjusts the offset in the list, not the -value in the reference (which is a group number). - -Arguments: - group points to the start of the group - adjust the amount by which the group is to be moved - utf TRUE in UTF-8 / UTF-16 mode - cd contains pointers to tables etc. - save_hwm the hwm forward reference pointer at the start of the group - -Returns: nothing -*/ - -static void -adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd, - pcre_uchar *save_hwm) -{ -pcre_uchar *ptr = group; - -while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL) - { - int offset; - pcre_uchar *hc; - - /* See if this recursion is on the forward reference list. If so, adjust the - reference. */ - - for (hc = save_hwm; hc < cd->hwm; hc += LINK_SIZE) - { - offset = GET(hc, 0); - if (cd->start_code + offset == ptr + 1) - { - PUT(hc, 0, offset + adjust); - break; - } - } - - /* Otherwise, adjust the recursion offset if it's after the start of this - group. */ - - if (hc >= cd->hwm) - { - offset = GET(ptr, 1); - if (cd->start_code + offset >= group) PUT(ptr, 1, offset + adjust); - } - - ptr += 1 + LINK_SIZE; - } -} - - - -/************************************************* -* Insert an automatic callout point * -*************************************************/ - -/* This function is called when the PCRE_AUTO_CALLOUT option is set, to insert -callout points before each pattern item. - -Arguments: - code current code pointer - ptr current pattern pointer - cd pointers to tables etc - -Returns: new code pointer -*/ - -static pcre_uchar * -auto_callout(pcre_uchar *code, const pcre_uchar *ptr, compile_data *cd) -{ -*code++ = OP_CALLOUT; -*code++ = 255; -PUT(code, 0, (int)(ptr - cd->start_pattern)); /* Pattern offset */ -PUT(code, LINK_SIZE, 0); /* Default length */ -return code + 2 * LINK_SIZE; -} - - - -/************************************************* -* Complete a callout item * -*************************************************/ - -/* A callout item contains the length of the next item in the pattern, which -we can't fill in till after we have reached the relevant point. This is used -for both automatic and manual callouts. - -Arguments: - previous_callout points to previous callout item - ptr current pattern pointer - cd pointers to tables etc - -Returns: nothing -*/ - -static void -complete_callout(pcre_uchar *previous_callout, const pcre_uchar *ptr, compile_data *cd) -{ -int length = (int)(ptr - cd->start_pattern - GET(previous_callout, 2)); -PUT(previous_callout, 2 + LINK_SIZE, length); -} - - - -#ifdef SUPPORT_UCP -/************************************************* -* Get othercase range * -*************************************************/ - -/* This function is passed the start and end of a class range, in UTF-8 mode -with UCP support. It searches up the characters, looking for internal ranges of -characters in the "other" case. Each call returns the next one, updating the -start address. - -Arguments: - cptr points to starting character value; updated - d end value - ocptr where to put start of othercase range - odptr where to put end of othercase range - -Yield: TRUE when range returned; FALSE when no more -*/ - -static BOOL -get_othercase_range(unsigned int *cptr, unsigned int d, unsigned int *ocptr, - unsigned int *odptr) -{ -unsigned int c, othercase, next; - -for (c = *cptr; c <= d; c++) - { if ((othercase = UCD_OTHERCASE(c)) != c) break; } - -if (c > d) return FALSE; - -*ocptr = othercase; -next = othercase + 1; - -for (++c; c <= d; c++) - { - if (UCD_OTHERCASE(c) != next) break; - next++; - } - -*odptr = next - 1; -*cptr = c; - -return TRUE; -} - - - -/************************************************* -* Check a character and a property * -*************************************************/ - -/* This function is called by check_auto_possessive() when a property item -is adjacent to a fixed character. - -Arguments: - c the character - ptype the property type - pdata the data for the type - negated TRUE if it's a negated property (\P or \p{^) - -Returns: TRUE if auto-possessifying is OK -*/ - -static BOOL -check_char_prop(int c, int ptype, int pdata, BOOL negated) -{ -const pcre_uint8 chartype = UCD_CHARTYPE(c); -switch(ptype) - { - case PT_LAMP: - return (chartype == ucp_Lu || - chartype == ucp_Ll || - chartype == ucp_Lt) == negated; - - case PT_GC: - return (pdata == PRIV(ucp_gentype)[chartype]) == negated; - - case PT_PC: - return (pdata == chartype) == negated; - - case PT_SC: - return (pdata == UCD_SCRIPT(c)) == negated; - - /* These are specials */ - - case PT_ALNUM: - return (PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N) == negated; - - case PT_SPACE: /* Perl space */ - return (PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR) - == negated; - - case PT_PXSPACE: /* POSIX space */ - return (PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR) - == negated; - - case PT_WORD: - return (PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N || - c == CHAR_UNDERSCORE) == negated; - } -return FALSE; -} -#endif /* SUPPORT_UCP */ - - - -/************************************************* -* Check if auto-possessifying is possible * -*************************************************/ - -/* This function is called for unlimited repeats of certain items, to see -whether the next thing could possibly match the repeated item. If not, it makes -sense to automatically possessify the repeated item. - -Arguments: - previous pointer to the repeated opcode - utf TRUE in UTF-8 / UTF-16 mode - ptr next character in pattern - options options bits - cd contains pointers to tables etc. - -Returns: TRUE if possessifying is wanted -*/ - -static BOOL -check_auto_possessive(const pcre_uchar *previous, BOOL utf, - const pcre_uchar *ptr, int options, compile_data *cd) -{ -pcre_int32 c, next; -int op_code = *previous++; - -/* Skip whitespace and comments in extended mode */ - -if ((options & PCRE_EXTENDED) != 0) - { - for (;;) - { - while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_space) != 0) ptr++; - if (*ptr == CHAR_NUMBER_SIGN) - { - ptr++; - while (*ptr != 0) - { - if (IS_NEWLINE(ptr)) { ptr += cd->nllen; break; } - ptr++; -#ifdef SUPPORT_UTF - if (utf) FORWARDCHAR(ptr); -#endif - } - } - else break; - } - } - -/* If the next item is one that we can handle, get its value. A non-negative -value is a character, a negative value is an escape value. */ - -if (*ptr == CHAR_BACKSLASH) - { - int temperrorcode = 0; - next = check_escape(&ptr, &temperrorcode, cd->bracount, options, FALSE); - if (temperrorcode != 0) return FALSE; - ptr++; /* Point after the escape sequence */ - } -else if (!MAX_255(*ptr) || (cd->ctypes[*ptr] & ctype_meta) == 0) - { -#ifdef SUPPORT_UTF - if (utf) { GETCHARINC(next, ptr); } else -#endif - next = *ptr++; - } -else return FALSE; - -/* Skip whitespace and comments in extended mode */ - -if ((options & PCRE_EXTENDED) != 0) - { - for (;;) - { - while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_space) != 0) ptr++; - if (*ptr == CHAR_NUMBER_SIGN) - { - ptr++; - while (*ptr != 0) - { - if (IS_NEWLINE(ptr)) { ptr += cd->nllen; break; } - ptr++; -#ifdef SUPPORT_UTF - if (utf) FORWARDCHAR(ptr); -#endif - } - } - else break; - } - } - -/* If the next thing is itself optional, we have to give up. */ - -if (*ptr == CHAR_ASTERISK || *ptr == CHAR_QUESTION_MARK || - STRNCMP_UC_C8(ptr, STR_LEFT_CURLY_BRACKET STR_0 STR_COMMA, 3) == 0) - return FALSE; - -/* Now compare the next item with the previous opcode. First, handle cases when -the next item is a character. */ - -if (next >= 0) switch(op_code) - { - case OP_CHAR: -#ifdef SUPPORT_UTF - GETCHARTEST(c, previous); -#else - c = *previous; -#endif - return c != next; - - /* For CHARI (caseless character) we must check the other case. If we have - Unicode property support, we can use it to test the other case of - high-valued characters. */ - - case OP_CHARI: -#ifdef SUPPORT_UTF - GETCHARTEST(c, previous); -#else - c = *previous; -#endif - if (c == next) return FALSE; -#ifdef SUPPORT_UTF - if (utf) - { - unsigned int othercase; - if (next < 128) othercase = cd->fcc[next]; else -#ifdef SUPPORT_UCP - othercase = UCD_OTHERCASE((unsigned int)next); -#else - othercase = NOTACHAR; -#endif - return (unsigned int)c != othercase; - } - else -#endif /* SUPPORT_UTF */ - return (c != TABLE_GET((unsigned int)next, cd->fcc, next)); /* Non-UTF-8 mode */ - - case OP_NOT: -#ifdef SUPPORT_UTF - GETCHARTEST(c, previous); -#else - c = *previous; -#endif - return c == next; - - case OP_NOTI: -#ifdef SUPPORT_UTF - GETCHARTEST(c, previous); -#else - c = *previous; -#endif - if (c == next) return TRUE; -#ifdef SUPPORT_UTF - if (utf) - { - unsigned int othercase; - if (next < 128) othercase = cd->fcc[next]; else -#ifdef SUPPORT_UCP - othercase = UCD_OTHERCASE((unsigned int)next); -#else - othercase = NOTACHAR; -#endif - return (unsigned int)c == othercase; - } - else -#endif /* SUPPORT_UTF */ - return (c == TABLE_GET((unsigned int)next, cd->fcc, next)); /* Non-UTF-8 mode */ - - /* Note that OP_DIGIT etc. are generated only when PCRE_UCP is *not* set. - When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */ - - case OP_DIGIT: - return next > 255 || (cd->ctypes[next] & ctype_digit) == 0; - - case OP_NOT_DIGIT: - return next <= 255 && (cd->ctypes[next] & ctype_digit) != 0; - - case OP_WHITESPACE: - return next > 255 || (cd->ctypes[next] & ctype_space) == 0; - - case OP_NOT_WHITESPACE: - return next <= 255 && (cd->ctypes[next] & ctype_space) != 0; - - case OP_WORDCHAR: - return next > 255 || (cd->ctypes[next] & ctype_word) == 0; - - case OP_NOT_WORDCHAR: - return next <= 255 && (cd->ctypes[next] & ctype_word) != 0; - - case OP_HSPACE: - case OP_NOT_HSPACE: - switch(next) - { - case 0x09: - case 0x20: - case 0xa0: - case 0x1680: - case 0x180e: - case 0x2000: - case 0x2001: - case 0x2002: - case 0x2003: - case 0x2004: - case 0x2005: - case 0x2006: - case 0x2007: - case 0x2008: - case 0x2009: - case 0x200A: - case 0x202f: - case 0x205f: - case 0x3000: - return op_code == OP_NOT_HSPACE; - default: - return op_code != OP_NOT_HSPACE; - } - - case OP_ANYNL: - case OP_VSPACE: - case OP_NOT_VSPACE: - switch(next) - { - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x85: - case 0x2028: - case 0x2029: - return op_code == OP_NOT_VSPACE; - default: - return op_code != OP_NOT_VSPACE; - } - -#ifdef SUPPORT_UCP - case OP_PROP: - return check_char_prop(next, previous[0], previous[1], FALSE); - - case OP_NOTPROP: - return check_char_prop(next, previous[0], previous[1], TRUE); -#endif - - default: - return FALSE; - } - - -/* Handle the case when the next item is \d, \s, etc. Note that when PCRE_UCP -is set, \d turns into ESC_du rather than ESC_d, etc., so ESC_d etc. are -generated only when PCRE_UCP is *not* set, that is, when only ASCII -characteristics are recognized. Similarly, the opcodes OP_DIGIT etc. are -replaced by OP_PROP codes when PCRE_UCP is set. */ - -switch(op_code) - { - case OP_CHAR: - case OP_CHARI: -#ifdef SUPPORT_UTF - GETCHARTEST(c, previous); -#else - c = *previous; -#endif - switch(-next) - { - case ESC_d: - return c > 255 || (cd->ctypes[c] & ctype_digit) == 0; - - case ESC_D: - return c <= 255 && (cd->ctypes[c] & ctype_digit) != 0; - - case ESC_s: - return c > 255 || (cd->ctypes[c] & ctype_space) == 0; - - case ESC_S: - return c <= 255 && (cd->ctypes[c] & ctype_space) != 0; - - case ESC_w: - return c > 255 || (cd->ctypes[c] & ctype_word) == 0; - - case ESC_W: - return c <= 255 && (cd->ctypes[c] & ctype_word) != 0; - - case ESC_h: - case ESC_H: - switch(c) - { - case 0x09: - case 0x20: - case 0xa0: - case 0x1680: - case 0x180e: - case 0x2000: - case 0x2001: - case 0x2002: - case 0x2003: - case 0x2004: - case 0x2005: - case 0x2006: - case 0x2007: - case 0x2008: - case 0x2009: - case 0x200A: - case 0x202f: - case 0x205f: - case 0x3000: - return -next != ESC_h; - default: - return -next == ESC_h; - } - - case ESC_v: - case ESC_V: - switch(c) - { - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x85: - case 0x2028: - case 0x2029: - return -next != ESC_v; - default: - return -next == ESC_v; - } - - /* When PCRE_UCP is set, these values get generated for \d etc. Find - their substitutions and process them. The result will always be either - -ESC_p or -ESC_P. Then fall through to process those values. */ - -#ifdef SUPPORT_UCP - case ESC_du: - case ESC_DU: - case ESC_wu: - case ESC_WU: - case ESC_su: - case ESC_SU: - { - int temperrorcode = 0; - ptr = substitutes[-next - ESC_DU]; - next = check_escape(&ptr, &temperrorcode, 0, options, FALSE); - if (temperrorcode != 0) return FALSE; - ptr++; /* For compatibility */ - } - /* Fall through */ - - case ESC_p: - case ESC_P: - { - int ptype, pdata, errorcodeptr; - BOOL negated; - - ptr--; /* Make ptr point at the p or P */ - ptype = get_ucp(&ptr, &negated, &pdata, &errorcodeptr); - if (ptype < 0) return FALSE; - ptr++; /* Point past the final curly ket */ - - /* If the property item is optional, we have to give up. (When generated - from \d etc by PCRE_UCP, this test will have been applied much earlier, - to the original \d etc. At this point, ptr will point to a zero byte. */ - - if (*ptr == CHAR_ASTERISK || *ptr == CHAR_QUESTION_MARK || - STRNCMP_UC_C8(ptr, STR_LEFT_CURLY_BRACKET STR_0 STR_COMMA, 3) == 0) - return FALSE; - - /* Do the property check. */ - - return check_char_prop(c, ptype, pdata, (next == -ESC_P) != negated); - } -#endif - - default: - return FALSE; - } - - /* In principle, support for Unicode properties should be integrated here as - well. It means re-organizing the above code so as to get hold of the property - values before switching on the op-code. However, I wonder how many patterns - combine ASCII \d etc with Unicode properties? (Note that if PCRE_UCP is set, - these op-codes are never generated.) */ - - case OP_DIGIT: - return next == -ESC_D || next == -ESC_s || next == -ESC_W || - next == -ESC_h || next == -ESC_v || next == -ESC_R; - - case OP_NOT_DIGIT: - return next == -ESC_d; - - case OP_WHITESPACE: - return next == -ESC_S || next == -ESC_d || next == -ESC_w; - - case OP_NOT_WHITESPACE: - return next == -ESC_s || next == -ESC_h || next == -ESC_v || next == -ESC_R; - - case OP_HSPACE: - return next == -ESC_S || next == -ESC_H || next == -ESC_d || - next == -ESC_w || next == -ESC_v || next == -ESC_R; - - case OP_NOT_HSPACE: - return next == -ESC_h; - - /* Can't have \S in here because VT matches \S (Perl anomaly) */ - case OP_ANYNL: - case OP_VSPACE: - return next == -ESC_V || next == -ESC_d || next == -ESC_w; - - case OP_NOT_VSPACE: - return next == -ESC_v || next == -ESC_R; - - case OP_WORDCHAR: - return next == -ESC_W || next == -ESC_s || next == -ESC_h || - next == -ESC_v || next == -ESC_R; - - case OP_NOT_WORDCHAR: - return next == -ESC_w || next == -ESC_d; - - default: - return FALSE; - } - -/* Control does not reach here */ -} - - - -/************************************************* -* Compile one branch * -*************************************************/ - -/* Scan the pattern, compiling it into the a vector. If the options are -changed during the branch, the pointer is used to change the external options -bits. This function is used during the pre-compile phase when we are trying -to find out the amount of memory needed, as well as during the real compile -phase. The value of lengthptr distinguishes the two phases. - -Arguments: - optionsptr pointer to the option bits - codeptr points to the pointer to the current code point - ptrptr points to the current pattern pointer - errorcodeptr points to error code variable - firstcharptr set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE) - reqcharptr set to the last literal character required, else < 0 - bcptr points to current branch chain - cond_depth conditional nesting depth - cd contains pointers to tables etc. - lengthptr NULL during the real compile phase - points to length accumulator during pre-compile phase - -Returns: TRUE on success - FALSE, with *errorcodeptr set non-zero on error -*/ - -static BOOL -compile_branch(int *optionsptr, pcre_uchar **codeptr, - const pcre_uchar **ptrptr, int *errorcodeptr, pcre_int32 *firstcharptr, - pcre_int32 *reqcharptr, branch_chain *bcptr, int cond_depth, - compile_data *cd, int *lengthptr) -{ -int repeat_type, op_type; -int repeat_min = 0, repeat_max = 0; /* To please picky compilers */ -int bravalue = 0; -int greedy_default, greedy_non_default; -pcre_int32 firstchar, reqchar; -pcre_int32 zeroreqchar, zerofirstchar; -pcre_int32 req_caseopt, reqvary, tempreqvary; -int options = *optionsptr; /* May change dynamically */ -int after_manual_callout = 0; -int length_prevgroup = 0; -int c; -pcre_uchar *code = *codeptr; -pcre_uchar *last_code = code; -pcre_uchar *orig_code = code; -pcre_uchar *tempcode; -BOOL inescq = FALSE; -BOOL groupsetfirstchar = FALSE; -const pcre_uchar *ptr = *ptrptr; -const pcre_uchar *tempptr; -const pcre_uchar *nestptr = NULL; -pcre_uchar *previous = NULL; -pcre_uchar *previous_callout = NULL; -pcre_uchar *save_hwm = NULL; -pcre_uint8 classbits[32]; - -/* We can fish out the UTF-8 setting once and for all into a BOOL, but we -must not do this for other options (e.g. PCRE_EXTENDED) because they may change -dynamically as we process the pattern. */ - -#ifdef SUPPORT_UTF -/* PCRE_UTF16 has the same value as PCRE_UTF8. */ -BOOL utf = (options & PCRE_UTF8) != 0; -pcre_uchar utf_chars[6]; -#else -BOOL utf = FALSE; -#endif - -/* Helper variables for OP_XCLASS opcode (for characters > 255). */ - -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 -BOOL xclass; -pcre_uchar *class_uchardata; -pcre_uchar *class_uchardata_base; -#endif - -#ifdef PCRE_DEBUG -if (lengthptr != NULL) DPRINTF((">> start branch\n")); -#endif - -/* Set up the default and non-default settings for greediness */ - -greedy_default = ((options & PCRE_UNGREEDY) != 0); -greedy_non_default = greedy_default ^ 1; - -/* Initialize no first byte, no required byte. REQ_UNSET means "no char -matching encountered yet". It gets changed to REQ_NONE if we hit something that -matches a non-fixed char first char; reqchar just remains unset if we never -find one. - -When we hit a repeat whose minimum is zero, we may have to adjust these values -to take the zero repeat into account. This is implemented by setting them to -zerofirstbyte and zeroreqchar when such a repeat is encountered. The individual -item types that can be repeated set these backoff variables appropriately. */ - -firstchar = reqchar = zerofirstchar = zeroreqchar = REQ_UNSET; - -/* The variable req_caseopt contains either the REQ_CASELESS value -or zero, according to the current setting of the caseless flag. The -REQ_CASELESS leaves the lower 28 bit empty. It is added into the -firstchar or reqchar variables to record the case status of the -value. This is used only for ASCII characters. */ - -req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS:0; - -/* Switch on next character until the end of the branch */ - -for (;; ptr++) - { - BOOL negate_class; - BOOL should_flip_negation; - BOOL possessive_quantifier; - BOOL is_quantifier; - BOOL is_recurse; - BOOL reset_bracount; - int class_has_8bitchar; - int class_single_char; - int newoptions; - int recno; - int refsign; - int skipbytes; - int subreqchar; - int subfirstchar; - int terminator; - int mclength; - int tempbracount; - pcre_uchar mcbuffer[8]; - - /* Get next character in the pattern */ - - c = *ptr; - - /* If we are at the end of a nested substitution, revert to the outer level - string. Nesting only happens one level deep. */ - - if (c == 0 && nestptr != NULL) - { - ptr = nestptr; - nestptr = NULL; - c = *ptr; - } - - /* If we are in the pre-compile phase, accumulate the length used for the - previous cycle of this loop. */ - - if (lengthptr != NULL) - { -#ifdef PCRE_DEBUG - if (code > cd->hwm) cd->hwm = code; /* High water info */ -#endif - if (code > cd->start_workspace + cd->workspace_size - - WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */ - { - *errorcodeptr = ERR52; - goto FAILED; - } - - /* There is at least one situation where code goes backwards: this is the - case of a zero quantifier after a class (e.g. [ab]{0}). At compile time, - the class is simply eliminated. However, it is created first, so we have to - allow memory for it. Therefore, don't ever reduce the length at this point. - */ - - if (code < last_code) code = last_code; - - /* Paranoid check for integer overflow */ - - if (OFLOW_MAX - *lengthptr < code - last_code) - { - *errorcodeptr = ERR20; - goto FAILED; - } - - *lengthptr += (int)(code - last_code); - DPRINTF(("length=%d added %d c=%c (0x%x)\n", *lengthptr, - (int)(code - last_code), c, c)); - - /* If "previous" is set and it is not at the start of the work space, move - it back to there, in order to avoid filling up the work space. Otherwise, - if "previous" is NULL, reset the current code pointer to the start. */ - - if (previous != NULL) - { - if (previous > orig_code) - { - memmove(orig_code, previous, IN_UCHARS(code - previous)); - code -= previous - orig_code; - previous = orig_code; - } - } - else code = orig_code; - - /* Remember where this code item starts so we can pick up the length - next time round. */ - - last_code = code; - } - - /* In the real compile phase, just check the workspace used by the forward - reference list. */ - - else if (cd->hwm > cd->start_workspace + cd->workspace_size - - WORK_SIZE_SAFETY_MARGIN) - { - *errorcodeptr = ERR52; - goto FAILED; - } - - /* If in \Q...\E, check for the end; if not, we have a literal */ - - if (inescq && c != 0) - { - if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E) - { - inescq = FALSE; - ptr++; - continue; - } - else - { - if (previous_callout != NULL) - { - if (lengthptr == NULL) /* Don't attempt in pre-compile phase */ - complete_callout(previous_callout, ptr, cd); - previous_callout = NULL; - } - if ((options & PCRE_AUTO_CALLOUT) != 0) - { - previous_callout = code; - code = auto_callout(code, ptr, cd); - } - goto NORMAL_CHAR; - } - } - - /* Fill in length of a previous callout, except when the next thing is - a quantifier. */ - - is_quantifier = - c == CHAR_ASTERISK || c == CHAR_PLUS || c == CHAR_QUESTION_MARK || - (c == CHAR_LEFT_CURLY_BRACKET && is_counted_repeat(ptr+1)); - - if (!is_quantifier && previous_callout != NULL && - after_manual_callout-- <= 0) - { - if (lengthptr == NULL) /* Don't attempt in pre-compile phase */ - complete_callout(previous_callout, ptr, cd); - previous_callout = NULL; - } - - /* In extended mode, skip white space and comments. */ - - if ((options & PCRE_EXTENDED) != 0) - { - if (MAX_255(*ptr) && (cd->ctypes[c] & ctype_space) != 0) continue; - if (c == CHAR_NUMBER_SIGN) - { - ptr++; - while (*ptr != 0) - { - if (IS_NEWLINE(ptr)) { ptr += cd->nllen - 1; break; } - ptr++; -#ifdef SUPPORT_UTF - if (utf) FORWARDCHAR(ptr); -#endif - } - if (*ptr != 0) continue; - - /* Else fall through to handle end of string */ - c = 0; - } - } - - /* No auto callout for quantifiers. */ - - if ((options & PCRE_AUTO_CALLOUT) != 0 && !is_quantifier) - { - previous_callout = code; - code = auto_callout(code, ptr, cd); - } - - switch(c) - { - /* ===================================================================*/ - case 0: /* The branch terminates at string end */ - case CHAR_VERTICAL_LINE: /* or | or ) */ - case CHAR_RIGHT_PARENTHESIS: - *firstcharptr = firstchar; - *reqcharptr = reqchar; - *codeptr = code; - *ptrptr = ptr; - if (lengthptr != NULL) - { - if (OFLOW_MAX - *lengthptr < code - last_code) - { - *errorcodeptr = ERR20; - goto FAILED; - } - *lengthptr += (int)(code - last_code); /* To include callout length */ - DPRINTF((">> end branch\n")); - } - return TRUE; - - - /* ===================================================================*/ - /* Handle single-character metacharacters. In multiline mode, ^ disables - the setting of any following char as a first character. */ - - case CHAR_CIRCUMFLEX_ACCENT: - previous = NULL; - if ((options & PCRE_MULTILINE) != 0) - { - if (firstchar == REQ_UNSET) firstchar = REQ_NONE; - *code++ = OP_CIRCM; - } - else *code++ = OP_CIRC; - break; - - case CHAR_DOLLAR_SIGN: - previous = NULL; - *code++ = ((options & PCRE_MULTILINE) != 0)? OP_DOLLM : OP_DOLL; - break; - - /* There can never be a first char if '.' is first, whatever happens about - repeats. The value of reqchar doesn't change either. */ - - case CHAR_DOT: - if (firstchar == REQ_UNSET) firstchar = REQ_NONE; - zerofirstchar = firstchar; - zeroreqchar = reqchar; - previous = code; - *code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY; - break; - - - /* ===================================================================*/ - /* Character classes. If the included characters are all < 256, we build a - 32-byte bitmap of the permitted characters, except in the special case - where there is only one such character. For negated classes, we build the - map as usual, then invert it at the end. However, we use a different opcode - so that data characters > 255 can be handled correctly. - - If the class contains characters outside the 0-255 range, a different - opcode is compiled. It may optionally have a bit map for characters < 256, - but those above are are explicitly listed afterwards. A flag byte tells - whether the bitmap is present, and whether this is a negated class or not. - - In JavaScript compatibility mode, an isolated ']' causes an error. In - default (Perl) mode, it is treated as a data character. */ - - case CHAR_RIGHT_SQUARE_BRACKET: - if ((cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0) - { - *errorcodeptr = ERR64; - goto FAILED; - } - goto NORMAL_CHAR; - - case CHAR_LEFT_SQUARE_BRACKET: - previous = code; - - /* PCRE supports POSIX class stuff inside a class. Perl gives an error if - they are encountered at the top level, so we'll do that too. */ - - if ((ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT || - ptr[1] == CHAR_EQUALS_SIGN) && - check_posix_syntax(ptr, &tempptr)) - { - *errorcodeptr = (ptr[1] == CHAR_COLON)? ERR13 : ERR31; - goto FAILED; - } - - /* If the first character is '^', set the negation flag and skip it. Also, - if the first few characters (either before or after ^) are \Q\E or \E we - skip them too. This makes for compatibility with Perl. */ - - negate_class = FALSE; - for (;;) - { - c = *(++ptr); - if (c == CHAR_BACKSLASH) - { - if (ptr[1] == CHAR_E) - ptr++; - else if (STRNCMP_UC_C8(ptr + 1, STR_Q STR_BACKSLASH STR_E, 3) == 0) - ptr += 3; - else - break; - } - else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT) - negate_class = TRUE; - else break; - } - - /* Empty classes are allowed in JavaScript compatibility mode. Otherwise, - an initial ']' is taken as a data character -- the code below handles - that. In JS mode, [] must always fail, so generate OP_FAIL, whereas - [^] must match any character, so generate OP_ALLANY. */ - - if (c == CHAR_RIGHT_SQUARE_BRACKET && - (cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0) - { - *code++ = negate_class? OP_ALLANY : OP_FAIL; - if (firstchar == REQ_UNSET) firstchar = REQ_NONE; - zerofirstchar = firstchar; - break; - } - - /* If a class contains a negative special such as \S, we need to flip the - negation flag at the end, so that support for characters > 255 works - correctly (they are all included in the class). */ - - should_flip_negation = FALSE; - - /* For optimization purposes, we track some properties of the class. - class_has_8bitchar will be non-zero, if the class contains at least one - < 256 character. class_single_char will be 1 if the class contains only - a single character. */ - - class_has_8bitchar = 0; - class_single_char = 0; - - /* Initialize the 32-char bit map to all zeros. We build the map in a - temporary bit of memory, in case the class contains only 1 character (less - than 256), because in that case the compiled code doesn't use the bit map. - */ - - memset(classbits, 0, 32 * sizeof(pcre_uint8)); - -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - xclass = FALSE; /* No chars >= 256 */ - class_uchardata = code + LINK_SIZE + 2; /* For UTF-8 items */ - class_uchardata_base = class_uchardata; /* For resetting in pass 1 */ -#endif - - /* Process characters until ] is reached. By writing this as a "do" it - means that an initial ] is taken as a data character. At the start of the - loop, c contains the first byte of the character. */ - - if (c != 0) do - { - const pcre_uchar *oldptr; - -#ifdef SUPPORT_UTF - if (utf && HAS_EXTRALEN(c)) - { /* Braces are required because the */ - GETCHARLEN(c, ptr, ptr); /* macro generates multiple statements */ - } -#endif - -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - /* In the pre-compile phase, accumulate the length of any extra - data and reset the pointer. This is so that very large classes that - contain a zillion > 255 characters no longer overwrite the work space - (which is on the stack). */ - - if (lengthptr != NULL) - { - *lengthptr += class_uchardata - class_uchardata_base; - class_uchardata = class_uchardata_base; - } -#endif - - /* Inside \Q...\E everything is literal except \E */ - - if (inescq) - { - if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E) /* If we are at \E */ - { - inescq = FALSE; /* Reset literal state */ - ptr++; /* Skip the 'E' */ - continue; /* Carry on with next */ - } - goto CHECK_RANGE; /* Could be range if \E follows */ - } - - /* Handle POSIX class names. Perl allows a negation extension of the - form [:^name:]. A square bracket that doesn't match the syntax is - treated as a literal. We also recognize the POSIX constructions - [.ch.] and [=ch=] ("collating elements") and fault them, as Perl - 5.6 and 5.8 do. */ - - if (c == CHAR_LEFT_SQUARE_BRACKET && - (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT || - ptr[1] == CHAR_EQUALS_SIGN) && check_posix_syntax(ptr, &tempptr)) - { - BOOL local_negate = FALSE; - int posix_class, taboffset, tabopt; - const pcre_uint8 *cbits = cd->cbits; - pcre_uint8 pbits[32]; - - if (ptr[1] != CHAR_COLON) - { - *errorcodeptr = ERR31; - goto FAILED; - } - - ptr += 2; - if (*ptr == CHAR_CIRCUMFLEX_ACCENT) - { - local_negate = TRUE; - should_flip_negation = TRUE; /* Note negative special */ - ptr++; - } - - posix_class = check_posix_name(ptr, (int)(tempptr - ptr)); - if (posix_class < 0) - { - *errorcodeptr = ERR30; - goto FAILED; - } - - /* If matching is caseless, upper and lower are converted to - alpha. This relies on the fact that the class table starts with - alpha, lower, upper as the first 3 entries. */ - - if ((options & PCRE_CASELESS) != 0 && posix_class <= 2) - posix_class = 0; - - /* When PCRE_UCP is set, some of the POSIX classes are converted to - different escape sequences that use Unicode properties. */ - -#ifdef SUPPORT_UCP - if ((options & PCRE_UCP) != 0) - { - int pc = posix_class + ((local_negate)? POSIX_SUBSIZE/2 : 0); - if (posix_substitutes[pc] != NULL) - { - nestptr = tempptr + 1; - ptr = posix_substitutes[pc] - 1; - continue; - } - } -#endif - /* In the non-UCP case, we build the bit map for the POSIX class in a - chunk of local store because we may be adding and subtracting from it, - and we don't want to subtract bits that may be in the main map already. - At the end we or the result into the bit map that is being built. */ - - posix_class *= 3; - - /* Copy in the first table (always present) */ - - memcpy(pbits, cbits + posix_class_maps[posix_class], - 32 * sizeof(pcre_uint8)); - - /* If there is a second table, add or remove it as required. */ - - taboffset = posix_class_maps[posix_class + 1]; - tabopt = posix_class_maps[posix_class + 2]; - - if (taboffset >= 0) - { - if (tabopt >= 0) - for (c = 0; c < 32; c++) pbits[c] |= cbits[c + taboffset]; - else - for (c = 0; c < 32; c++) pbits[c] &= ~cbits[c + taboffset]; - } - - /* Not see if we need to remove any special characters. An option - value of 1 removes vertical space and 2 removes underscore. */ - - if (tabopt < 0) tabopt = -tabopt; - if (tabopt == 1) pbits[1] &= ~0x3c; - else if (tabopt == 2) pbits[11] &= 0x7f; - - /* Add the POSIX table or its complement into the main table that is - being built and we are done. */ - - if (local_negate) - for (c = 0; c < 32; c++) classbits[c] |= ~pbits[c]; - else - for (c = 0; c < 32; c++) classbits[c] |= pbits[c]; - - ptr = tempptr + 1; - /* Every class contains at least one < 256 characters. */ - class_has_8bitchar = 1; - /* Every class contains at least two characters. */ - class_single_char = 2; - continue; /* End of POSIX syntax handling */ - } - - /* Backslash may introduce a single character, or it may introduce one - of the specials, which just set a flag. The sequence \b is a special - case. Inside a class (and only there) it is treated as backspace. We - assume that other escapes have more than one character in them, so - speculatively set both class_has_8bitchar and class_single_char bigger - than one. Unrecognized escapes fall through and are either treated - as literal characters (by default), or are faulted if - PCRE_EXTRA is set. */ - - if (c == CHAR_BACKSLASH) - { - c = check_escape(&ptr, errorcodeptr, cd->bracount, options, TRUE); - if (*errorcodeptr != 0) goto FAILED; - - if (-c == ESC_b) c = CHAR_BS; /* \b is backspace in a class */ - else if (-c == ESC_N) /* \N is not supported in a class */ - { - *errorcodeptr = ERR71; - goto FAILED; - } - else if (-c == ESC_Q) /* Handle start of quoted string */ - { - if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E) - { - ptr += 2; /* avoid empty string */ - } - else inescq = TRUE; - continue; - } - else if (-c == ESC_E) continue; /* Ignore orphan \E */ - - if (c < 0) - { - const pcre_uint8 *cbits = cd->cbits; - /* Every class contains at least two < 256 characters. */ - class_has_8bitchar++; - /* Every class contains at least two characters. */ - class_single_char += 2; - - switch (-c) - { -#ifdef SUPPORT_UCP - case ESC_du: /* These are the values given for \d etc */ - case ESC_DU: /* when PCRE_UCP is set. We replace the */ - case ESC_wu: /* escape sequence with an appropriate \p */ - case ESC_WU: /* or \P to test Unicode properties instead */ - case ESC_su: /* of the default ASCII testing. */ - case ESC_SU: - nestptr = ptr; - ptr = substitutes[-c - ESC_DU] - 1; /* Just before substitute */ - class_has_8bitchar--; /* Undo! */ - continue; -#endif - case ESC_d: - for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_digit]; - continue; - - case ESC_D: - should_flip_negation = TRUE; - for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_digit]; - continue; - - case ESC_w: - for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_word]; - continue; - - case ESC_W: - should_flip_negation = TRUE; - for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_word]; - continue; - - /* Perl 5.004 onwards omits VT from \s, but we must preserve it - if it was previously set by something earlier in the character - class. */ - - case ESC_s: - classbits[0] |= cbits[cbit_space]; - classbits[1] |= cbits[cbit_space+1] & ~0x08; - for (c = 2; c < 32; c++) classbits[c] |= cbits[c+cbit_space]; - continue; - - case ESC_S: - should_flip_negation = TRUE; - for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_space]; - classbits[1] |= 0x08; /* Perl 5.004 onwards omits VT from \s */ - continue; - - case ESC_h: - SETBIT(classbits, 0x09); /* VT */ - SETBIT(classbits, 0x20); /* SPACE */ - SETBIT(classbits, 0xa0); /* NSBP */ -#ifndef COMPILE_PCRE8 - xclass = TRUE; - *class_uchardata++ = XCL_SINGLE; - *class_uchardata++ = 0x1680; - *class_uchardata++ = XCL_SINGLE; - *class_uchardata++ = 0x180e; - *class_uchardata++ = XCL_RANGE; - *class_uchardata++ = 0x2000; - *class_uchardata++ = 0x200a; - *class_uchardata++ = XCL_SINGLE; - *class_uchardata++ = 0x202f; - *class_uchardata++ = XCL_SINGLE; - *class_uchardata++ = 0x205f; - *class_uchardata++ = XCL_SINGLE; - *class_uchardata++ = 0x3000; -#elif defined SUPPORT_UTF - if (utf) - { - xclass = TRUE; - *class_uchardata++ = XCL_SINGLE; - class_uchardata += PRIV(ord2utf)(0x1680, class_uchardata); - *class_uchardata++ = XCL_SINGLE; - class_uchardata += PRIV(ord2utf)(0x180e, class_uchardata); - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(0x2000, class_uchardata); - class_uchardata += PRIV(ord2utf)(0x200a, class_uchardata); - *class_uchardata++ = XCL_SINGLE; - class_uchardata += PRIV(ord2utf)(0x202f, class_uchardata); - *class_uchardata++ = XCL_SINGLE; - class_uchardata += PRIV(ord2utf)(0x205f, class_uchardata); - *class_uchardata++ = XCL_SINGLE; - class_uchardata += PRIV(ord2utf)(0x3000, class_uchardata); - } -#endif - continue; - - case ESC_H: - for (c = 0; c < 32; c++) - { - int x = 0xff; - switch (c) - { - case 0x09/8: x ^= 1 << (0x09%8); break; - case 0x20/8: x ^= 1 << (0x20%8); break; - case 0xa0/8: x ^= 1 << (0xa0%8); break; - default: break; - } - classbits[c] |= x; - } -#ifndef COMPILE_PCRE8 - xclass = TRUE; - *class_uchardata++ = XCL_RANGE; - *class_uchardata++ = 0x0100; - *class_uchardata++ = 0x167f; - *class_uchardata++ = XCL_RANGE; - *class_uchardata++ = 0x1681; - *class_uchardata++ = 0x180d; - *class_uchardata++ = XCL_RANGE; - *class_uchardata++ = 0x180f; - *class_uchardata++ = 0x1fff; - *class_uchardata++ = XCL_RANGE; - *class_uchardata++ = 0x200b; - *class_uchardata++ = 0x202e; - *class_uchardata++ = XCL_RANGE; - *class_uchardata++ = 0x2030; - *class_uchardata++ = 0x205e; - *class_uchardata++ = XCL_RANGE; - *class_uchardata++ = 0x2060; - *class_uchardata++ = 0x2fff; - *class_uchardata++ = XCL_RANGE; - *class_uchardata++ = 0x3001; -#ifdef SUPPORT_UTF - if (utf) - class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); - else -#endif - *class_uchardata++ = 0xffff; -#elif defined SUPPORT_UTF - if (utf) - { - xclass = TRUE; - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(0x0100, class_uchardata); - class_uchardata += PRIV(ord2utf)(0x167f, class_uchardata); - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(0x1681, class_uchardata); - class_uchardata += PRIV(ord2utf)(0x180d, class_uchardata); - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(0x180f, class_uchardata); - class_uchardata += PRIV(ord2utf)(0x1fff, class_uchardata); - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(0x200b, class_uchardata); - class_uchardata += PRIV(ord2utf)(0x202e, class_uchardata); - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(0x2030, class_uchardata); - class_uchardata += PRIV(ord2utf)(0x205e, class_uchardata); - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(0x2060, class_uchardata); - class_uchardata += PRIV(ord2utf)(0x2fff, class_uchardata); - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(0x3001, class_uchardata); - class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); - } -#endif - continue; - - case ESC_v: - SETBIT(classbits, 0x0a); /* LF */ - SETBIT(classbits, 0x0b); /* VT */ - SETBIT(classbits, 0x0c); /* FF */ - SETBIT(classbits, 0x0d); /* CR */ - SETBIT(classbits, 0x85); /* NEL */ -#ifndef COMPILE_PCRE8 - xclass = TRUE; - *class_uchardata++ = XCL_RANGE; - *class_uchardata++ = 0x2028; - *class_uchardata++ = 0x2029; -#elif defined SUPPORT_UTF - if (utf) - { - xclass = TRUE; - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(0x2028, class_uchardata); - class_uchardata += PRIV(ord2utf)(0x2029, class_uchardata); - } -#endif - continue; - - case ESC_V: - for (c = 0; c < 32; c++) - { - int x = 0xff; - switch (c) - { - case 0x0a/8: x ^= 1 << (0x0a%8); - x ^= 1 << (0x0b%8); - x ^= 1 << (0x0c%8); - x ^= 1 << (0x0d%8); - break; - case 0x85/8: x ^= 1 << (0x85%8); break; - default: break; - } - classbits[c] |= x; - } - -#ifndef COMPILE_PCRE8 - xclass = TRUE; - *class_uchardata++ = XCL_RANGE; - *class_uchardata++ = 0x0100; - *class_uchardata++ = 0x2027; - *class_uchardata++ = XCL_RANGE; - *class_uchardata++ = 0x202a; -#ifdef SUPPORT_UTF - if (utf) - class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); - else -#endif - *class_uchardata++ = 0xffff; -#elif defined SUPPORT_UTF - if (utf) - { - xclass = TRUE; - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(0x0100, class_uchardata); - class_uchardata += PRIV(ord2utf)(0x2027, class_uchardata); - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(0x202a, class_uchardata); - class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); - } -#endif - continue; - -#ifdef SUPPORT_UCP - case ESC_p: - case ESC_P: - { - BOOL negated; - int pdata; - int ptype = get_ucp(&ptr, &negated, &pdata, errorcodeptr); - if (ptype < 0) goto FAILED; - xclass = TRUE; - *class_uchardata++ = ((-c == ESC_p) != negated)? - XCL_PROP : XCL_NOTPROP; - *class_uchardata++ = ptype; - *class_uchardata++ = pdata; - class_has_8bitchar--; /* Undo! */ - continue; - } -#endif - /* Unrecognized escapes are faulted if PCRE is running in its - strict mode. By default, for compatibility with Perl, they are - treated as literals. */ - - default: - if ((options & PCRE_EXTRA) != 0) - { - *errorcodeptr = ERR7; - goto FAILED; - } - class_has_8bitchar--; /* Undo the speculative increase. */ - class_single_char -= 2; /* Undo the speculative increase. */ - c = *ptr; /* Get the final character and fall through */ - break; - } - } - - /* Fall through if we have a single character (c >= 0). This may be - greater than 256. */ - - } /* End of backslash handling */ - - /* A single character may be followed by '-' to form a range. However, - Perl does not permit ']' to be the end of the range. A '-' character - at the end is treated as a literal. Perl ignores orphaned \E sequences - entirely. The code for handling \Q and \E is messy. */ - - CHECK_RANGE: - while (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E) - { - inescq = FALSE; - ptr += 2; - } - - oldptr = ptr; - - /* Remember \r or \n */ - - if (c == CHAR_CR || c == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF; - - /* Check for range */ - - if (!inescq && ptr[1] == CHAR_MINUS) - { - int d; - ptr += 2; - while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E) ptr += 2; - - /* If we hit \Q (not followed by \E) at this point, go into escaped - mode. */ - - while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_Q) - { - ptr += 2; - if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E) - { ptr += 2; continue; } - inescq = TRUE; - break; - } - - if (*ptr == 0 || (!inescq && *ptr == CHAR_RIGHT_SQUARE_BRACKET)) - { - ptr = oldptr; - goto LONE_SINGLE_CHARACTER; - } - -#ifdef SUPPORT_UTF - if (utf) - { /* Braces are required because the */ - GETCHARLEN(d, ptr, ptr); /* macro generates multiple statements */ - } - else -#endif - d = *ptr; /* Not UTF-8 mode */ - - /* The second part of a range can be a single-character escape, but - not any of the other escapes. Perl 5.6 treats a hyphen as a literal - in such circumstances. */ - - if (!inescq && d == CHAR_BACKSLASH) - { - d = check_escape(&ptr, errorcodeptr, cd->bracount, options, TRUE); - if (*errorcodeptr != 0) goto FAILED; - - /* \b is backspace; any other special means the '-' was literal */ - - if (d < 0) - { - if (d == -ESC_b) d = CHAR_BS; else - { - ptr = oldptr; - goto LONE_SINGLE_CHARACTER; /* A few lines below */ - } - } - } - - /* Check that the two values are in the correct order. Optimize - one-character ranges */ - - if (d < c) - { - *errorcodeptr = ERR8; - goto FAILED; - } - - if (d == c) goto LONE_SINGLE_CHARACTER; /* A few lines below */ - - /* Remember \r or \n */ - - if (d == CHAR_CR || d == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF; - - /* Since we found a character range, single character optimizations - cannot be done anymore. */ - class_single_char = 2; - - /* In UTF-8 mode, if the upper limit is > 255, or > 127 for caseless - matching, we have to use an XCLASS with extra data items. Caseless - matching for characters > 127 is available only if UCP support is - available. */ - -#if defined SUPPORT_UTF && !(defined COMPILE_PCRE8) - if ((d > 255) || (utf && ((options & PCRE_CASELESS) != 0 && d > 127))) -#elif defined SUPPORT_UTF - if (utf && (d > 255 || ((options & PCRE_CASELESS) != 0 && d > 127))) -#elif !(defined COMPILE_PCRE8) - if (d > 255) -#endif -#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) - { - xclass = TRUE; - - /* With UCP support, we can find the other case equivalents of - the relevant characters. There may be several ranges. Optimize how - they fit with the basic range. */ - -#ifdef SUPPORT_UCP -#ifndef COMPILE_PCRE8 - if (utf && (options & PCRE_CASELESS) != 0) -#else - if ((options & PCRE_CASELESS) != 0) -#endif - { - unsigned int occ, ocd; - unsigned int cc = c; - unsigned int origd = d; - while (get_othercase_range(&cc, origd, &occ, &ocd)) - { - if (occ >= (unsigned int)c && - ocd <= (unsigned int)d) - continue; /* Skip embedded ranges */ - - if (occ < (unsigned int)c && - ocd >= (unsigned int)c - 1) /* Extend the basic range */ - { /* if there is overlap, */ - c = occ; /* noting that if occ < c */ - continue; /* we can't have ocd > d */ - } /* because a subrange is */ - if (ocd > (unsigned int)d && - occ <= (unsigned int)d + 1) /* always shorter than */ - { /* the basic range. */ - d = ocd; - continue; - } - - if (occ == ocd) - { - *class_uchardata++ = XCL_SINGLE; - } - else - { - *class_uchardata++ = XCL_RANGE; - class_uchardata += PRIV(ord2utf)(occ, class_uchardata); - } - class_uchardata += PRIV(ord2utf)(ocd, class_uchardata); - } - } -#endif /* SUPPORT_UCP */ - - /* Now record the original range, possibly modified for UCP caseless - overlapping ranges. */ - - *class_uchardata++ = XCL_RANGE; -#ifdef SUPPORT_UTF -#ifndef COMPILE_PCRE8 - if (utf) - { - class_uchardata += PRIV(ord2utf)(c, class_uchardata); - class_uchardata += PRIV(ord2utf)(d, class_uchardata); - } - else - { - *class_uchardata++ = c; - *class_uchardata++ = d; - } -#else - class_uchardata += PRIV(ord2utf)(c, class_uchardata); - class_uchardata += PRIV(ord2utf)(d, class_uchardata); -#endif -#else /* SUPPORT_UTF */ - *class_uchardata++ = c; - *class_uchardata++ = d; -#endif /* SUPPORT_UTF */ - - /* With UCP support, we are done. Without UCP support, there is no - caseless matching for UTF characters > 127; we can use the bit map - for the smaller ones. As for 16 bit characters without UTF, we - can still use */ - -#ifdef SUPPORT_UCP -#ifndef COMPILE_PCRE8 - if (utf) -#endif - continue; /* With next character in the class */ -#endif /* SUPPORT_UCP */ - -#if defined SUPPORT_UTF && !defined(SUPPORT_UCP) && !(defined COMPILE_PCRE8) - if (utf) - { - if ((options & PCRE_CASELESS) == 0 || c > 127) continue; - /* Adjust upper limit and fall through to set up the map */ - d = 127; - } - else - { - if (c > 255) continue; - /* Adjust upper limit and fall through to set up the map */ - d = 255; - } -#elif defined SUPPORT_UTF && !defined(SUPPORT_UCP) - if ((options & PCRE_CASELESS) == 0 || c > 127) continue; - /* Adjust upper limit and fall through to set up the map */ - d = 127; -#else - if (c > 255) continue; - /* Adjust upper limit and fall through to set up the map */ - d = 255; -#endif /* SUPPORT_UTF && !SUPPORT_UCP && !COMPILE_PCRE8 */ - } -#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */ - - /* We use the bit map for 8 bit mode, or when the characters fall - partially or entirely to [0-255] ([0-127] for UCP) ranges. */ - - class_has_8bitchar = 1; - - /* We can save a bit of time by skipping this in the pre-compile. */ - - if (lengthptr == NULL) for (; c <= d; c++) - { - classbits[c/8] |= (1 << (c&7)); - if ((options & PCRE_CASELESS) != 0) - { - int uc = cd->fcc[c]; /* flip case */ - classbits[uc/8] |= (1 << (uc&7)); - } - } - - continue; /* Go get the next char in the class */ - } - - /* Handle a lone single character - we can get here for a normal - non-escape char, or after \ that introduces a single character or for an - apparent range that isn't. */ - - LONE_SINGLE_CHARACTER: - - /* Only the value of 1 matters for class_single_char. */ - - if (class_single_char < 2) class_single_char++; - - /* If class_charcount is 1, we saw precisely one character. As long as - there was no use of \p or \P, in other words, no use of any XCLASS - features, we can optimize. - - The optimization throws away the bit map. We turn the item into a - 1-character OP_CHAR[I] if it's positive, or OP_NOT[I] if it's negative. - In the positive case, it can cause firstchar to be set. Otherwise, there - can be no first char if this item is first, whatever repeat count may - follow. In the case of reqchar, save the previous value for reinstating. */ - - if (class_single_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) - { - ptr++; - zeroreqchar = reqchar; - - if (negate_class) - { - if (firstchar == REQ_UNSET) firstchar = REQ_NONE; - zerofirstchar = firstchar; - *code++ = ((options & PCRE_CASELESS) != 0)? OP_NOTI: OP_NOT; -#ifdef SUPPORT_UTF - if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR) - code += PRIV(ord2utf)(c, code); - else -#endif - *code++ = c; - goto NOT_CHAR; - } - - /* For a single, positive character, get the value into mcbuffer, and - then we can handle this with the normal one-character code. */ - -#ifdef SUPPORT_UTF - if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR) - mclength = PRIV(ord2utf)(c, mcbuffer); - else -#endif - { - mcbuffer[0] = c; - mclength = 1; - } - goto ONE_CHAR; - } /* End of 1-char optimization */ - - /* Handle a character that cannot go in the bit map. */ - -#if defined SUPPORT_UTF && !(defined COMPILE_PCRE8) - if ((c > 255) || (utf && ((options & PCRE_CASELESS) != 0 && c > 127))) -#elif defined SUPPORT_UTF - if (utf && (c > 255 || ((options & PCRE_CASELESS) != 0 && c > 127))) -#elif !(defined COMPILE_PCRE8) - if (c > 255) -#endif - -#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) - { - xclass = TRUE; - *class_uchardata++ = XCL_SINGLE; -#ifdef SUPPORT_UTF -#ifndef COMPILE_PCRE8 - /* In non 8 bit mode, we can get here even if we are not in UTF mode. */ - if (!utf) - *class_uchardata++ = c; - else -#endif - class_uchardata += PRIV(ord2utf)(c, class_uchardata); -#else /* SUPPORT_UTF */ - *class_uchardata++ = c; -#endif /* SUPPORT_UTF */ - -#ifdef SUPPORT_UCP -#ifdef COMPILE_PCRE8 - if ((options & PCRE_CASELESS) != 0) -#else - /* In non 8 bit mode, we can get here even if we are not in UTF mode. */ - if (utf && (options & PCRE_CASELESS) != 0) -#endif - { - unsigned int othercase; - if ((int)(othercase = UCD_OTHERCASE(c)) != c) - { - *class_uchardata++ = XCL_SINGLE; - class_uchardata += PRIV(ord2utf)(othercase, class_uchardata); - } - } -#endif /* SUPPORT_UCP */ - - } - else -#endif /* SUPPORT_UTF || COMPILE_PCRE16 */ - - /* Handle a single-byte character */ - { - class_has_8bitchar = 1; - classbits[c/8] |= (1 << (c&7)); - if ((options & PCRE_CASELESS) != 0) - { - c = cd->fcc[c]; /* flip case */ - classbits[c/8] |= (1 << (c&7)); - } - } - } - - /* Loop until ']' reached. This "while" is the end of the "do" far above. - If we are at the end of an internal nested string, revert to the outer - string. */ - - while (((c = *(++ptr)) != 0 || - (nestptr != NULL && - (ptr = nestptr, nestptr = NULL, c = *(++ptr)) != 0)) && - (c != CHAR_RIGHT_SQUARE_BRACKET || inescq)); - - /* Check for missing terminating ']' */ - - if (c == 0) - { - *errorcodeptr = ERR6; - goto FAILED; - } - - /* If this is the first thing in the branch, there can be no first char - setting, whatever the repeat count. Any reqchar setting must remain - unchanged after any kind of repeat. */ - - if (firstchar == REQ_UNSET) firstchar = REQ_NONE; - zerofirstchar = firstchar; - zeroreqchar = reqchar; - - /* If there are characters with values > 255, we have to compile an - extended class, with its own opcode, unless there was a negated special - such as \S in the class, and PCRE_UCP is not set, because in that case all - characters > 255 are in the class, so any that were explicitly given as - well can be ignored. If (when there are explicit characters > 255 that must - be listed) there are no characters < 256, we can omit the bitmap in the - actual compiled code. */ - -#ifdef SUPPORT_UTF - if (xclass && (!should_flip_negation || (options & PCRE_UCP) != 0)) -#elif !defined COMPILE_PCRE8 - if (xclass && !should_flip_negation) -#endif -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - { - *class_uchardata++ = XCL_END; /* Marks the end of extra data */ - *code++ = OP_XCLASS; - code += LINK_SIZE; - *code = negate_class? XCL_NOT:0; - - /* If the map is required, move up the extra data to make room for it; - otherwise just move the code pointer to the end of the extra data. */ - - if (class_has_8bitchar > 0) - { - *code++ |= XCL_MAP; - memmove(code + (32 / sizeof(pcre_uchar)), code, - IN_UCHARS(class_uchardata - code)); - memcpy(code, classbits, 32); - code = class_uchardata + (32 / sizeof(pcre_uchar)); - } - else code = class_uchardata; - - /* Now fill in the complete length of the item */ - - PUT(previous, 1, (int)(code - previous)); - break; /* End of class handling */ - } -#endif - - /* If there are no characters > 255, or they are all to be included or - excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the - whole class was negated and whether there were negative specials such as \S - (non-UCP) in the class. Then copy the 32-byte map into the code vector, - negating it if necessary. */ - - *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS; - if (lengthptr == NULL) /* Save time in the pre-compile phase */ - { - if (negate_class) - for (c = 0; c < 32; c++) classbits[c] = ~classbits[c]; - memcpy(code, classbits, 32); - } - code += 32 / sizeof(pcre_uchar); - NOT_CHAR: - break; - - - /* ===================================================================*/ - /* Various kinds of repeat; '{' is not necessarily a quantifier, but this - has been tested above. */ - - case CHAR_LEFT_CURLY_BRACKET: - if (!is_quantifier) goto NORMAL_CHAR; - ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorcodeptr); - if (*errorcodeptr != 0) goto FAILED; - goto REPEAT; - - case CHAR_ASTERISK: - repeat_min = 0; - repeat_max = -1; - goto REPEAT; - - case CHAR_PLUS: - repeat_min = 1; - repeat_max = -1; - goto REPEAT; - - case CHAR_QUESTION_MARK: - repeat_min = 0; - repeat_max = 1; - - REPEAT: - if (previous == NULL) - { - *errorcodeptr = ERR9; - goto FAILED; - } - - if (repeat_min == 0) - { - firstchar = zerofirstchar; /* Adjust for zero repeat */ - reqchar = zeroreqchar; /* Ditto */ - } - - /* Remember whether this is a variable length repeat */ - - reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY; - - op_type = 0; /* Default single-char op codes */ - possessive_quantifier = FALSE; /* Default not possessive quantifier */ - - /* Save start of previous item, in case we have to move it up in order to - insert something before it. */ - - tempcode = previous; - - /* If the next character is '+', we have a possessive quantifier. This - implies greediness, whatever the setting of the PCRE_UNGREEDY option. - If the next character is '?' this is a minimizing repeat, by default, - but if PCRE_UNGREEDY is set, it works the other way round. We change the - repeat type to the non-default. */ - - if (ptr[1] == CHAR_PLUS) - { - repeat_type = 0; /* Force greedy */ - possessive_quantifier = TRUE; - ptr++; - } - else if (ptr[1] == CHAR_QUESTION_MARK) - { - repeat_type = greedy_non_default; - ptr++; - } - else repeat_type = greedy_default; - - /* If previous was a recursion call, wrap it in atomic brackets so that - previous becomes the atomic group. All recursions were so wrapped in the - past, but it no longer happens for non-repeated recursions. In fact, the - repeated ones could be re-implemented independently so as not to need this, - but for the moment we rely on the code for repeating groups. */ - - if (*previous == OP_RECURSE) - { - memmove(previous + 1 + LINK_SIZE, previous, IN_UCHARS(1 + LINK_SIZE)); - *previous = OP_ONCE; - PUT(previous, 1, 2 + 2*LINK_SIZE); - previous[2 + 2*LINK_SIZE] = OP_KET; - PUT(previous, 3 + 2*LINK_SIZE, 2 + 2*LINK_SIZE); - code += 2 + 2 * LINK_SIZE; - length_prevgroup = 3 + 3*LINK_SIZE; - - /* When actually compiling, we need to check whether this was a forward - reference, and if so, adjust the offset. */ - - if (lengthptr == NULL && cd->hwm >= cd->start_workspace + LINK_SIZE) - { - int offset = GET(cd->hwm, -LINK_SIZE); - if (offset == previous + 1 - cd->start_code) - PUT(cd->hwm, -LINK_SIZE, offset + 1 + LINK_SIZE); - } - } - - /* Now handle repetition for the different types of item. */ - - /* If previous was a character or negated character match, abolish the item - and generate a repeat item instead. If a char item has a minimum of more - than one, ensure that it is set in reqchar - it might not be if a sequence - such as x{3} is the first thing in a branch because the x will have gone - into firstchar instead. */ - - if (*previous == OP_CHAR || *previous == OP_CHARI - || *previous == OP_NOT || *previous == OP_NOTI) - { - switch (*previous) - { - 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; - } - - /* Deal with UTF characters that take up more than one character. It's - easier to write this out separately than try to macrify it. Use c to - hold the length of the character in bytes, plus UTF_LENGTH to flag that - it's a length rather than a small character. */ - -#ifdef SUPPORT_UTF - if (utf && NOT_FIRSTCHAR(code[-1])) - { - pcre_uchar *lastchar = code - 1; - BACKCHAR(lastchar); - c = (int)(code - lastchar); /* Length of UTF-8 character */ - memcpy(utf_chars, lastchar, IN_UCHARS(c)); /* Save the char */ - c |= UTF_LENGTH; /* Flag c as a length */ - } - else -#endif /* SUPPORT_UTF */ - - /* Handle the case of a single character - either with no UTF support, or - with UTF disabled, or for a single character UTF character. */ - { - c = code[-1]; - if (*previous <= OP_CHARI && repeat_min > 1) - reqchar = c | req_caseopt | cd->req_varyopt; - } - - /* If the repetition is unlimited, it pays to see if the next thing on - the line is something that cannot possibly match this character. If so, - automatically possessifying this item gains some performance in the case - where the match fails. */ - - if (!possessive_quantifier && - repeat_max < 0 && - check_auto_possessive(previous, utf, ptr + 1, options, cd)) - { - repeat_type = 0; /* Force greedy */ - possessive_quantifier = TRUE; - } - - goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */ - } - - /* If previous was a character type match (\d or similar), abolish it and - create a suitable repeat item. The code is shared with single-character - repeats by setting op_type to add a suitable offset into repeat_type. Note - the the Unicode property types will be present only when SUPPORT_UCP is - defined, but we don't wrap the little bits of code here because it just - makes it horribly messy. */ - - else if (*previous < OP_EODN) - { - pcre_uchar *oldcode; - int prop_type, prop_value; - op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */ - c = *previous; - - if (!possessive_quantifier && - repeat_max < 0 && - check_auto_possessive(previous, utf, ptr + 1, options, cd)) - { - repeat_type = 0; /* Force greedy */ - possessive_quantifier = TRUE; - } - - OUTPUT_SINGLE_REPEAT: - if (*previous == OP_PROP || *previous == OP_NOTPROP) - { - prop_type = previous[1]; - prop_value = previous[2]; - } - else prop_type = prop_value = -1; - - oldcode = code; - code = previous; /* Usually overwrite previous item */ - - /* If the maximum is zero then the minimum must also be zero; Perl allows - this case, so we do too - by simply omitting the item altogether. */ - - if (repeat_max == 0) goto END_REPEAT; - - /*--------------------------------------------------------------------*/ - /* This code is obsolete from release 8.00; the restriction was finally - removed: */ - - /* All real repeats make it impossible to handle partial matching (maybe - one day we will be able to remove this restriction). */ - - /* if (repeat_max != 1) cd->external_flags |= PCRE_NOPARTIAL; */ - /*--------------------------------------------------------------------*/ - - /* Combine the op_type with the repeat_type */ - - repeat_type += op_type; - - /* A minimum of zero is handled either as the special case * or ?, or as - an UPTO, with the maximum given. */ - - if (repeat_min == 0) - { - if (repeat_max == -1) *code++ = OP_STAR + repeat_type; - else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type; - else - { - *code++ = OP_UPTO + repeat_type; - PUT2INC(code, 0, repeat_max); - } - } - - /* A repeat minimum of 1 is optimized into some special cases. If the - maximum is unlimited, we use OP_PLUS. Otherwise, the original item is - left in place and, if the maximum is greater than 1, we use OP_UPTO with - one less than the maximum. */ - - else if (repeat_min == 1) - { - if (repeat_max == -1) - *code++ = OP_PLUS + repeat_type; - else - { - code = oldcode; /* leave previous item in place */ - if (repeat_max == 1) goto END_REPEAT; - *code++ = OP_UPTO + repeat_type; - PUT2INC(code, 0, repeat_max - 1); - } - } - - /* The case {n,n} is just an EXACT, while the general case {n,m} is - handled as an EXACT followed by an UPTO. */ - - else - { - *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */ - PUT2INC(code, 0, repeat_min); - - /* If the maximum is unlimited, insert an OP_STAR. Before doing so, - we have to insert the character for the previous code. For a repeated - Unicode property match, there are two extra bytes that define the - required property. In UTF-8 mode, long characters have their length in - c, with the UTF_LENGTH bit as a flag. */ - - if (repeat_max < 0) - { -#ifdef SUPPORT_UTF - if (utf && (c & UTF_LENGTH) != 0) - { - memcpy(code, utf_chars, IN_UCHARS(c & 7)); - code += c & 7; - } - else -#endif - { - *code++ = c; - if (prop_type >= 0) - { - *code++ = prop_type; - *code++ = prop_value; - } - } - *code++ = OP_STAR + repeat_type; - } - - /* Else insert an UPTO if the max is greater than the min, again - preceded by the character, for the previously inserted code. If the - UPTO is just for 1 instance, we can use QUERY instead. */ - - else if (repeat_max != repeat_min) - { -#ifdef SUPPORT_UTF - if (utf && (c & UTF_LENGTH) != 0) - { - memcpy(code, utf_chars, IN_UCHARS(c & 7)); - code += c & 7; - } - else -#endif - *code++ = c; - if (prop_type >= 0) - { - *code++ = prop_type; - *code++ = prop_value; - } - repeat_max -= repeat_min; - - if (repeat_max == 1) - { - *code++ = OP_QUERY + repeat_type; - } - else - { - *code++ = OP_UPTO + repeat_type; - PUT2INC(code, 0, repeat_max); - } - } - } - - /* The character or character type itself comes last in all cases. */ - -#ifdef SUPPORT_UTF - if (utf && (c & UTF_LENGTH) != 0) - { - memcpy(code, utf_chars, IN_UCHARS(c & 7)); - code += c & 7; - } - else -#endif - *code++ = c; - - /* For a repeated Unicode property match, there are two extra bytes that - define the required property. */ - -#ifdef SUPPORT_UCP - if (prop_type >= 0) - { - *code++ = prop_type; - *code++ = prop_value; - } -#endif - } - - /* If previous was a character class or a back reference, we put the repeat - stuff after it, but just skip the item if the repeat was {0,0}. */ - - else if (*previous == OP_CLASS || - *previous == OP_NCLASS || -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - *previous == OP_XCLASS || -#endif - *previous == OP_REF || - *previous == OP_REFI) - { - if (repeat_max == 0) - { - code = previous; - goto END_REPEAT; - } - - /*--------------------------------------------------------------------*/ - /* This code is obsolete from release 8.00; the restriction was finally - removed: */ - - /* All real repeats make it impossible to handle partial matching (maybe - one day we will be able to remove this restriction). */ - - /* if (repeat_max != 1) cd->external_flags |= PCRE_NOPARTIAL; */ - /*--------------------------------------------------------------------*/ - - if (repeat_min == 0 && repeat_max == -1) - *code++ = OP_CRSTAR + repeat_type; - else if (repeat_min == 1 && repeat_max == -1) - *code++ = OP_CRPLUS + repeat_type; - else if (repeat_min == 0 && repeat_max == 1) - *code++ = OP_CRQUERY + repeat_type; - else - { - *code++ = OP_CRRANGE + repeat_type; - PUT2INC(code, 0, repeat_min); - if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */ - PUT2INC(code, 0, repeat_max); - } - } - - /* If previous was a bracket group, we may have to replicate it in certain - cases. Note that at this point we can encounter only the "basic" bracket - opcodes such as BRA and CBRA, as this is the place where they get converted - into the more special varieties such as BRAPOS and SBRA. A test for >= - OP_ASSERT and <= OP_COND includes ASSERT, ASSERT_NOT, ASSERTBACK, - ASSERTBACK_NOT, ONCE, BRA, CBRA, and COND. Originally, PCRE did not allow - repetition of assertions, but now it does, for Perl compatibility. */ - - else if (*previous >= OP_ASSERT && *previous <= OP_COND) - { - int i; - int len = (int)(code - previous); - pcre_uchar *bralink = NULL; - pcre_uchar *brazeroptr = NULL; - - /* Repeating a DEFINE group is pointless, but Perl allows the syntax, so - we just ignore the repeat. */ - - if (*previous == OP_COND && previous[LINK_SIZE+1] == OP_DEF) - goto END_REPEAT; - - /* There is no sense in actually repeating assertions. The only potential - use of repetition is in cases when the assertion is optional. Therefore, - if the minimum is greater than zero, just ignore the repeat. If the - maximum is not not zero or one, set it to 1. */ - - if (*previous < OP_ONCE) /* Assertion */ - { - if (repeat_min > 0) goto END_REPEAT; - if (repeat_max < 0 || repeat_max > 1) repeat_max = 1; - } - - /* The case of a zero minimum is special because of the need to stick - OP_BRAZERO in front of it, and because the group appears once in the - data, whereas in other cases it appears the minimum number of times. For - this reason, it is simplest to treat this case separately, as otherwise - the code gets far too messy. There are several special subcases when the - minimum is zero. */ - - if (repeat_min == 0) - { - /* If the maximum is also zero, we used to just omit the group from the - output altogether, like this: - - ** if (repeat_max == 0) - ** { - ** code = previous; - ** goto END_REPEAT; - ** } - - However, that fails when a group or a subgroup within it is referenced - as a subroutine from elsewhere in the pattern, so now we stick in - OP_SKIPZERO in front of it so that it is skipped on execution. As we - don't have a list of which groups are referenced, we cannot do this - selectively. - - If the maximum is 1 or unlimited, we just have to stick in the BRAZERO - and do no more at this point. However, we do need to adjust any - OP_RECURSE calls inside the group that refer to the group itself or any - internal or forward referenced group, because the offset is from the - start of the whole regex. Temporarily terminate the pattern while doing - this. */ - - if (repeat_max <= 1) /* Covers 0, 1, and unlimited */ - { - *code = OP_END; - adjust_recurse(previous, 1, utf, cd, save_hwm); - memmove(previous + 1, previous, IN_UCHARS(len)); - code++; - if (repeat_max == 0) - { - *previous++ = OP_SKIPZERO; - goto END_REPEAT; - } - brazeroptr = previous; /* Save for possessive optimizing */ - *previous++ = OP_BRAZERO + repeat_type; - } - - /* If the maximum is greater than 1 and limited, we have to replicate - in a nested fashion, sticking OP_BRAZERO before each set of brackets. - The first one has to be handled carefully because it's the original - copy, which has to be moved up. The remainder can be handled by code - that is common with the non-zero minimum case below. We have to - adjust the value or repeat_max, since one less copy is required. Once - again, we may have to adjust any OP_RECURSE calls inside the group. */ - - else - { - int offset; - *code = OP_END; - adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm); - memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len)); - code += 2 + LINK_SIZE; - *previous++ = OP_BRAZERO + repeat_type; - *previous++ = OP_BRA; - - /* We chain together the bracket offset fields that have to be - filled in later when the ends of the brackets are reached. */ - - offset = (bralink == NULL)? 0 : (int)(previous - bralink); - bralink = previous; - PUTINC(previous, 0, offset); - } - - repeat_max--; - } - - /* If the minimum is greater than zero, replicate the group as many - times as necessary, and adjust the maximum to the number of subsequent - copies that we need. If we set a first char from the group, and didn't - set a required char, copy the latter from the former. If there are any - forward reference subroutine calls in the group, there will be entries on - the workspace list; replicate these with an appropriate increment. */ - - else - { - if (repeat_min > 1) - { - /* In the pre-compile phase, we don't actually do the replication. We - just adjust the length as if we had. Do some paranoid checks for - potential integer overflow. The INT64_OR_DOUBLE type is a 64-bit - integer type when available, otherwise double. */ - - if (lengthptr != NULL) - { - int delta = (repeat_min - 1)*length_prevgroup; - if ((INT64_OR_DOUBLE)(repeat_min - 1)* - (INT64_OR_DOUBLE)length_prevgroup > - (INT64_OR_DOUBLE)INT_MAX || - OFLOW_MAX - *lengthptr < delta) - { - *errorcodeptr = ERR20; - goto FAILED; - } - *lengthptr += delta; - } - - /* This is compiling for real. If there is a set first byte for - the group, and we have not yet set a "required byte", set it. Make - sure there is enough workspace for copying forward references before - doing the copy. */ - - else - { - if (groupsetfirstchar && reqchar < 0) reqchar = firstchar; - - for (i = 1; i < repeat_min; i++) - { - pcre_uchar *hc; - pcre_uchar *this_hwm = cd->hwm; - memcpy(code, previous, IN_UCHARS(len)); - - while (cd->hwm > cd->start_workspace + cd->workspace_size - - WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm)) - { - int save_offset = save_hwm - cd->start_workspace; - int this_offset = this_hwm - cd->start_workspace; - *errorcodeptr = expand_workspace(cd); - if (*errorcodeptr != 0) goto FAILED; - save_hwm = (pcre_uchar *)cd->start_workspace + save_offset; - this_hwm = (pcre_uchar *)cd->start_workspace + this_offset; - } - - for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE) - { - PUT(cd->hwm, 0, GET(hc, 0) + len); - cd->hwm += LINK_SIZE; - } - save_hwm = this_hwm; - code += len; - } - } - } - - if (repeat_max > 0) repeat_max -= repeat_min; - } - - /* This code is common to both the zero and non-zero minimum cases. If - the maximum is limited, it replicates the group in a nested fashion, - remembering the bracket starts on a stack. In the case of a zero minimum, - the first one was set up above. In all cases the repeat_max now specifies - the number of additional copies needed. Again, we must remember to - replicate entries on the forward reference list. */ - - if (repeat_max >= 0) - { - /* In the pre-compile phase, we don't actually do the replication. We - just adjust the length as if we had. For each repetition we must add 1 - to the length for BRAZERO and for all but the last repetition we must - add 2 + 2*LINKSIZE to allow for the nesting that occurs. Do some - paranoid checks to avoid integer overflow. The INT64_OR_DOUBLE type is - a 64-bit integer type when available, otherwise double. */ - - if (lengthptr != NULL && repeat_max > 0) - { - int delta = repeat_max * (length_prevgroup + 1 + 2 + 2*LINK_SIZE) - - 2 - 2*LINK_SIZE; /* Last one doesn't nest */ - if ((INT64_OR_DOUBLE)repeat_max * - (INT64_OR_DOUBLE)(length_prevgroup + 1 + 2 + 2*LINK_SIZE) - > (INT64_OR_DOUBLE)INT_MAX || - OFLOW_MAX - *lengthptr < delta) - { - *errorcodeptr = ERR20; - goto FAILED; - } - *lengthptr += delta; - } - - /* This is compiling for real */ - - else for (i = repeat_max - 1; i >= 0; i--) - { - pcre_uchar *hc; - pcre_uchar *this_hwm = cd->hwm; - - *code++ = OP_BRAZERO + repeat_type; - - /* All but the final copy start a new nesting, maintaining the - chain of brackets outstanding. */ - - if (i != 0) - { - int offset; - *code++ = OP_BRA; - offset = (bralink == NULL)? 0 : (int)(code - bralink); - bralink = code; - PUTINC(code, 0, offset); - } - - memcpy(code, previous, IN_UCHARS(len)); - - /* Ensure there is enough workspace for forward references before - copying them. */ - - while (cd->hwm > cd->start_workspace + cd->workspace_size - - WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm)) - { - int save_offset = save_hwm - cd->start_workspace; - int this_offset = this_hwm - cd->start_workspace; - *errorcodeptr = expand_workspace(cd); - if (*errorcodeptr != 0) goto FAILED; - save_hwm = (pcre_uchar *)cd->start_workspace + save_offset; - this_hwm = (pcre_uchar *)cd->start_workspace + this_offset; - } - - for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE) - { - PUT(cd->hwm, 0, GET(hc, 0) + len + ((i != 0)? 2+LINK_SIZE : 1)); - cd->hwm += LINK_SIZE; - } - save_hwm = this_hwm; - code += len; - } - - /* Now chain through the pending brackets, and fill in their length - fields (which are holding the chain links pro tem). */ - - while (bralink != NULL) - { - int oldlinkoffset; - int offset = (int)(code - bralink + 1); - pcre_uchar *bra = code - offset; - oldlinkoffset = GET(bra, 1); - bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset; - *code++ = OP_KET; - PUTINC(code, 0, offset); - PUT(bra, 1, offset); - } - } - - /* If the maximum is unlimited, set a repeater in the final copy. For - ONCE brackets, that's all we need to do. However, possessively repeated - ONCE brackets can be converted into non-capturing brackets, as the - behaviour of (?:xx)++ is the same as (?>xx)++ and this saves having to - deal with possessive ONCEs specially. - - Otherwise, when we are doing the actual compile phase, check to see - whether this group is one that could match an empty string. If so, - convert the initial operator to the S form (e.g. OP_BRA -> OP_SBRA) so - that runtime checking can be done. [This check is also applied to ONCE - groups at runtime, but in a different way.] - - Then, if the quantifier was possessive and the bracket is not a - conditional, we convert the BRA code to the POS form, and the KET code to - KETRPOS. (It turns out to be convenient at runtime to detect this kind of - subpattern at both the start and at the end.) The use of special opcodes - makes it possible to reduce greatly the stack usage in pcre_exec(). If - the group is preceded by OP_BRAZERO, convert this to OP_BRAPOSZERO. - - Then, if the minimum number of matches is 1 or 0, cancel the possessive - flag so that the default action below, of wrapping everything inside - atomic brackets, does not happen. When the minimum is greater than 1, - there will be earlier copies of the group, and so we still have to wrap - the whole thing. */ - - else - { - pcre_uchar *ketcode = code - 1 - LINK_SIZE; - pcre_uchar *bracode = ketcode - GET(ketcode, 1); - - /* Convert possessive ONCE brackets to non-capturing */ - - if ((*bracode == OP_ONCE || *bracode == OP_ONCE_NC) && - possessive_quantifier) *bracode = OP_BRA; - - /* For non-possessive ONCE brackets, all we need to do is to - set the KET. */ - - if (*bracode == OP_ONCE || *bracode == OP_ONCE_NC) - *ketcode = OP_KETRMAX + repeat_type; - - /* Handle non-ONCE brackets and possessive ONCEs (which have been - converted to non-capturing above). */ - - else - { - /* In the compile phase, check for empty string matching. */ - - if (lengthptr == NULL) - { - pcre_uchar *scode = bracode; - do - { - if (could_be_empty_branch(scode, ketcode, utf, cd)) - { - *bracode += OP_SBRA - OP_BRA; - break; - } - scode += GET(scode, 1); - } - while (*scode == OP_ALT); - } - - /* Handle possessive quantifiers. */ - - if (possessive_quantifier) - { - /* For COND brackets, we wrap the whole thing in a possessively - repeated non-capturing bracket, because we have not invented POS - versions of the COND opcodes. Because we are moving code along, we - must ensure that any pending recursive references are updated. */ - - if (*bracode == OP_COND || *bracode == OP_SCOND) - { - int nlen = (int)(code - bracode); - *code = OP_END; - adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm); - memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen)); - code += 1 + LINK_SIZE; - nlen += 1 + LINK_SIZE; - *bracode = OP_BRAPOS; - *code++ = OP_KETRPOS; - PUTINC(code, 0, nlen); - PUT(bracode, 1, nlen); - } - - /* For non-COND brackets, we modify the BRA code and use KETRPOS. */ - - else - { - *bracode += 1; /* Switch to xxxPOS opcodes */ - *ketcode = OP_KETRPOS; - } - - /* If the minimum is zero, mark it as possessive, then unset the - possessive flag when the minimum is 0 or 1. */ - - if (brazeroptr != NULL) *brazeroptr = OP_BRAPOSZERO; - if (repeat_min < 2) possessive_quantifier = FALSE; - } - - /* Non-possessive quantifier */ - - else *ketcode = OP_KETRMAX + repeat_type; - } - } - } - - /* If previous is OP_FAIL, it was generated by an empty class [] in - JavaScript mode. The other ways in which OP_FAIL can be generated, that is - by (*FAIL) or (?!) set previous to NULL, which gives a "nothing to repeat" - error above. We can just ignore the repeat in JS case. */ - - else if (*previous == OP_FAIL) goto END_REPEAT; - - /* Else there's some kind of shambles */ - - else - { - *errorcodeptr = ERR11; - goto FAILED; - } - - /* If the character following a repeat is '+', or if certain optimization - tests above succeeded, possessive_quantifier is TRUE. For some opcodes, - there are special alternative opcodes for this case. For anything else, we - wrap the entire repeated item inside OP_ONCE brackets. Logically, the '+' - notation is just syntactic sugar, taken from Sun's Java package, but the - special opcodes can optimize it. - - Some (but not all) possessively repeated subpatterns have already been - completely handled in the code just above. For them, possessive_quantifier - is always FALSE at this stage. - - Note that the repeated item starts at tempcode, not at previous, which - might be the first part of a string whose (former) last char we repeated. - - Possessifying an 'exact' quantifier has no effect, so we can ignore it. But - an 'upto' may follow. We skip over an 'exact' item, and then test the - length of what remains before proceeding. */ - - if (possessive_quantifier) - { - int len; - - if (*tempcode == OP_TYPEEXACT) - tempcode += PRIV(OP_lengths)[*tempcode] + - ((tempcode[1 + IMM2_SIZE] == OP_PROP - || tempcode[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0); - - else if (*tempcode == OP_EXACT || *tempcode == OP_NOTEXACT) - { - tempcode += PRIV(OP_lengths)[*tempcode]; -#ifdef SUPPORT_UTF - if (utf && HAS_EXTRALEN(tempcode[-1])) - tempcode += GET_EXTRALEN(tempcode[-1]); -#endif - } - - len = (int)(code - tempcode); - if (len > 0) switch (*tempcode) - { - case OP_STAR: *tempcode = OP_POSSTAR; break; - case OP_PLUS: *tempcode = OP_POSPLUS; break; - case OP_QUERY: *tempcode = OP_POSQUERY; break; - case OP_UPTO: *tempcode = OP_POSUPTO; break; - - case OP_STARI: *tempcode = OP_POSSTARI; break; - case OP_PLUSI: *tempcode = OP_POSPLUSI; break; - case OP_QUERYI: *tempcode = OP_POSQUERYI; break; - case OP_UPTOI: *tempcode = OP_POSUPTOI; break; - - case OP_NOTSTAR: *tempcode = OP_NOTPOSSTAR; break; - case OP_NOTPLUS: *tempcode = OP_NOTPOSPLUS; break; - case OP_NOTQUERY: *tempcode = OP_NOTPOSQUERY; break; - case OP_NOTUPTO: *tempcode = OP_NOTPOSUPTO; break; - - case OP_NOTSTARI: *tempcode = OP_NOTPOSSTARI; break; - case OP_NOTPLUSI: *tempcode = OP_NOTPOSPLUSI; break; - case OP_NOTQUERYI: *tempcode = OP_NOTPOSQUERYI; break; - case OP_NOTUPTOI: *tempcode = OP_NOTPOSUPTOI; break; - - case OP_TYPESTAR: *tempcode = OP_TYPEPOSSTAR; break; - case OP_TYPEPLUS: *tempcode = OP_TYPEPOSPLUS; break; - case OP_TYPEQUERY: *tempcode = OP_TYPEPOSQUERY; break; - case OP_TYPEUPTO: *tempcode = OP_TYPEPOSUPTO; break; - - /* Because we are moving code along, we must ensure that any - pending recursive references are updated. */ - - default: - *code = OP_END; - adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm); - memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); - code += 1 + LINK_SIZE; - len += 1 + LINK_SIZE; - tempcode[0] = OP_ONCE; - *code++ = OP_KET; - PUTINC(code, 0, len); - PUT(tempcode, 1, len); - break; - } - } - - /* In all case we no longer have a previous item. We also set the - "follows varying string" flag for subsequently encountered reqchars if - it isn't already set and we have just passed a varying length item. */ - - END_REPEAT: - previous = NULL; - cd->req_varyopt |= reqvary; - break; - - - /* ===================================================================*/ - /* Start of nested parenthesized sub-expression, or comment or lookahead or - lookbehind or option setting or condition or all the other extended - parenthesis forms. */ - - case CHAR_LEFT_PARENTHESIS: - newoptions = options; - skipbytes = 0; - bravalue = OP_CBRA; - save_hwm = cd->hwm; - reset_bracount = FALSE; - - /* First deal with various "verbs" that can be introduced by '*'. */ - - ptr++; - if (ptr[0] == CHAR_ASTERISK && (ptr[1] == ':' - || (MAX_255(ptr[1]) && ((cd->ctypes[ptr[1]] & ctype_letter) != 0)))) - { - int i, namelen; - int arglen = 0; - const char *vn = verbnames; - const pcre_uchar *name = ptr + 1; - const pcre_uchar *arg = NULL; - previous = NULL; - ptr++; - while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_letter) != 0) ptr++; - namelen = (int)(ptr - name); - - /* It appears that Perl allows any characters whatsoever, other than - a closing parenthesis, to appear in arguments, so we no longer insist on - letters, digits, and underscores. */ - - if (*ptr == CHAR_COLON) - { - arg = ++ptr; - while (*ptr != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; - arglen = (int)(ptr - arg); - if (arglen > (int)MAX_MARK) - { - *errorcodeptr = ERR75; - goto FAILED; - } - } - - if (*ptr != CHAR_RIGHT_PARENTHESIS) - { - *errorcodeptr = ERR60; - goto FAILED; - } - - /* Scan the table of verb names */ - - for (i = 0; i < verbcount; i++) - { - if (namelen == verbs[i].len && - STRNCMP_UC_C8(name, vn, namelen) == 0) - { - /* Check for open captures before ACCEPT and convert it to - ASSERT_ACCEPT if in an assertion. */ - - if (verbs[i].op == OP_ACCEPT) - { - open_capitem *oc; - if (arglen != 0) - { - *errorcodeptr = ERR59; - goto FAILED; - } - cd->had_accept = TRUE; - for (oc = cd->open_caps; oc != NULL; oc = oc->next) - { - *code++ = OP_CLOSE; - PUT2INC(code, 0, oc->number); - } - *code++ = (cd->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT; - - /* Do not set firstchar after *ACCEPT */ - if (firstchar == REQ_UNSET) firstchar = REQ_NONE; - } - - /* Handle other cases with/without an argument */ - - else if (arglen == 0) - { - if (verbs[i].op < 0) /* Argument is mandatory */ - { - *errorcodeptr = ERR66; - goto FAILED; - } - *code = verbs[i].op; - if (*code++ == OP_THEN) cd->external_flags |= PCRE_HASTHEN; - } - - else - { - if (verbs[i].op_arg < 0) /* Argument is forbidden */ - { - *errorcodeptr = ERR59; - goto FAILED; - } - *code = verbs[i].op_arg; - if (*code++ == OP_THEN_ARG) cd->external_flags |= PCRE_HASTHEN; - *code++ = arglen; - memcpy(code, arg, IN_UCHARS(arglen)); - code += arglen; - *code++ = 0; - } - - break; /* Found verb, exit loop */ - } - - vn += verbs[i].len + 1; - } - - if (i < verbcount) continue; /* Successfully handled a verb */ - *errorcodeptr = ERR60; /* Verb not recognized */ - goto FAILED; - } - - /* Deal with the extended parentheses; all are introduced by '?', and the - appearance of any of them means that this is not a capturing group. */ - - else if (*ptr == CHAR_QUESTION_MARK) - { - int i, set, unset, namelen; - int *optset; - const pcre_uchar *name; - pcre_uchar *slot; - - switch (*(++ptr)) - { - case CHAR_NUMBER_SIGN: /* Comment; skip to ket */ - ptr++; - while (*ptr != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; - if (*ptr == 0) - { - *errorcodeptr = ERR18; - goto FAILED; - } - continue; - - - /* ------------------------------------------------------------ */ - case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */ - reset_bracount = TRUE; - /* Fall through */ - - /* ------------------------------------------------------------ */ - case CHAR_COLON: /* Non-capturing bracket */ - bravalue = OP_BRA; - ptr++; - break; - - - /* ------------------------------------------------------------ */ - case CHAR_LEFT_PARENTHESIS: - bravalue = OP_COND; /* Conditional group */ - - /* A condition can be an assertion, a number (referring to a numbered - group), a name (referring to a named group), or 'R', referring to - recursion. R<digits> and R&name are also permitted for recursion tests. - - There are several syntaxes for testing a named group: (?(name)) is used - by Python; Perl 5.10 onwards uses (?(<name>) or (?('name')). - - There are two unfortunate ambiguities, caused by history. (a) 'R' can - be the recursive thing or the name 'R' (and similarly for 'R' followed - by digits), and (b) a number could be a name that consists of digits. - In both cases, we look for a name first; if not found, we try the other - cases. */ - - /* For conditions that are assertions, check the syntax, and then exit - the switch. This will take control down to where bracketed groups, - including assertions, are processed. */ - - if (ptr[1] == CHAR_QUESTION_MARK && (ptr[2] == CHAR_EQUALS_SIGN || - ptr[2] == CHAR_EXCLAMATION_MARK || ptr[2] == CHAR_LESS_THAN_SIGN)) - break; - - /* Most other conditions use OP_CREF (a couple change to OP_RREF - below), and all need to skip 1+IMM2_SIZE bytes at the start of the group. */ - - code[1+LINK_SIZE] = OP_CREF; - skipbytes = 1+IMM2_SIZE; - refsign = -1; - - /* Check for a test for recursion in a named group. */ - - if (ptr[1] == CHAR_R && ptr[2] == CHAR_AMPERSAND) - { - terminator = -1; - ptr += 2; - code[1+LINK_SIZE] = OP_RREF; /* Change the type of test */ - } - - /* Check for a test for a named group's having been set, using the Perl - syntax (?(<name>) or (?('name') */ - - else if (ptr[1] == CHAR_LESS_THAN_SIGN) - { - terminator = CHAR_GREATER_THAN_SIGN; - ptr++; - } - else if (ptr[1] == CHAR_APOSTROPHE) - { - terminator = CHAR_APOSTROPHE; - ptr++; - } - else - { - terminator = 0; - if (ptr[1] == CHAR_MINUS || ptr[1] == CHAR_PLUS) refsign = *(++ptr); - } - - /* We now expect to read a name; any thing else is an error */ - - if (!MAX_255(ptr[1]) || (cd->ctypes[ptr[1]] & ctype_word) == 0) - { - ptr += 1; /* To get the right offset */ - *errorcodeptr = ERR28; - goto FAILED; - } - - /* Read the name, but also get it as a number if it's all digits */ - - recno = 0; - name = ++ptr; - while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) - { - if (recno >= 0) - recno = (IS_DIGIT(*ptr))? recno * 10 + *ptr - CHAR_0 : -1; - ptr++; - } - namelen = (int)(ptr - name); - - if ((terminator > 0 && *ptr++ != terminator) || - *ptr++ != CHAR_RIGHT_PARENTHESIS) - { - ptr--; /* Error offset */ - *errorcodeptr = ERR26; - goto FAILED; - } - - /* Do no further checking in the pre-compile phase. */ - - if (lengthptr != NULL) break; - - /* In the real compile we do the work of looking for the actual - reference. If the string started with "+" or "-" we require the rest to - be digits, in which case recno will be set. */ - - if (refsign > 0) - { - if (recno <= 0) - { - *errorcodeptr = ERR58; - goto FAILED; - } - recno = (refsign == CHAR_MINUS)? - cd->bracount - recno + 1 : recno +cd->bracount; - if (recno <= 0 || recno > cd->final_bracount) - { - *errorcodeptr = ERR15; - goto FAILED; - } - PUT2(code, 2+LINK_SIZE, recno); - break; - } - - /* Otherwise (did not start with "+" or "-"), start by looking for the - name. If we find a name, add one to the opcode to change OP_CREF or - OP_RREF into OP_NCREF or OP_NRREF. These behave exactly the same, - except they record that the reference was originally to a name. The - information is used to check duplicate names. */ - - slot = cd->name_table; - for (i = 0; i < cd->names_found; i++) - { - if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0) break; - slot += cd->name_entry_size; - } - - /* Found a previous named subpattern */ - - if (i < cd->names_found) - { - recno = GET2(slot, 0); - PUT2(code, 2+LINK_SIZE, recno); - code[1+LINK_SIZE]++; - } - - /* Search the pattern for a forward reference */ - - else if ((i = find_parens(cd, name, namelen, - (options & PCRE_EXTENDED) != 0, utf)) > 0) - { - PUT2(code, 2+LINK_SIZE, i); - code[1+LINK_SIZE]++; - } - - /* If terminator == 0 it means that the name followed directly after - the opening parenthesis [e.g. (?(abc)...] and in this case there are - some further alternatives to try. For the cases where terminator != 0 - [things like (?(<name>... or (?('name')... or (?(R&name)... ] we have - now checked all the possibilities, so give an error. */ - - else if (terminator != 0) - { - *errorcodeptr = ERR15; - goto FAILED; - } - - /* Check for (?(R) for recursion. Allow digits after R to specify a - specific group number. */ - - else if (*name == CHAR_R) - { - recno = 0; - for (i = 1; i < namelen; i++) - { - if (!IS_DIGIT(name[i])) - { - *errorcodeptr = ERR15; - goto FAILED; - } - recno = recno * 10 + name[i] - CHAR_0; - } - if (recno == 0) recno = RREF_ANY; - code[1+LINK_SIZE] = OP_RREF; /* Change test type */ - PUT2(code, 2+LINK_SIZE, recno); - } - - /* Similarly, check for the (?(DEFINE) "condition", which is always - false. */ - - else if (namelen == 6 && STRNCMP_UC_C8(name, STRING_DEFINE, 6) == 0) - { - code[1+LINK_SIZE] = OP_DEF; - skipbytes = 1; - } - - /* Check for the "name" actually being a subpattern number. We are - in the second pass here, so final_bracount is set. */ - - else if (recno > 0 && recno <= cd->final_bracount) - { - PUT2(code, 2+LINK_SIZE, recno); - } - - /* Either an unidentified subpattern, or a reference to (?(0) */ - - else - { - *errorcodeptr = (recno == 0)? ERR35: ERR15; - goto FAILED; - } - break; - - - /* ------------------------------------------------------------ */ - case CHAR_EQUALS_SIGN: /* Positive lookahead */ - bravalue = OP_ASSERT; - cd->assert_depth += 1; - ptr++; - break; - - - /* ------------------------------------------------------------ */ - case CHAR_EXCLAMATION_MARK: /* Negative lookahead */ - ptr++; - if (*ptr == CHAR_RIGHT_PARENTHESIS) /* Optimize (?!) */ - { - *code++ = OP_FAIL; - previous = NULL; - continue; - } - bravalue = OP_ASSERT_NOT; - cd->assert_depth += 1; - break; - - - /* ------------------------------------------------------------ */ - case CHAR_LESS_THAN_SIGN: /* Lookbehind or named define */ - switch (ptr[1]) - { - case CHAR_EQUALS_SIGN: /* Positive lookbehind */ - bravalue = OP_ASSERTBACK; - cd->assert_depth += 1; - ptr += 2; - break; - - case CHAR_EXCLAMATION_MARK: /* Negative lookbehind */ - bravalue = OP_ASSERTBACK_NOT; - cd->assert_depth += 1; - ptr += 2; - break; - - default: /* Could be name define, else bad */ - if (MAX_255(ptr[1]) && (cd->ctypes[ptr[1]] & ctype_word) != 0) - goto DEFINE_NAME; - ptr++; /* Correct offset for error */ - *errorcodeptr = ERR24; - goto FAILED; - } - break; - - - /* ------------------------------------------------------------ */ - case CHAR_GREATER_THAN_SIGN: /* One-time brackets */ - bravalue = OP_ONCE; - ptr++; - break; - - - /* ------------------------------------------------------------ */ - case CHAR_C: /* Callout - may be followed by digits; */ - previous_callout = code; /* Save for later completion */ - after_manual_callout = 1; /* Skip one item before completing */ - *code++ = OP_CALLOUT; - { - int n = 0; - ptr++; - while(IS_DIGIT(*ptr)) - n = n * 10 + *ptr++ - CHAR_0; - if (*ptr != CHAR_RIGHT_PARENTHESIS) - { - *errorcodeptr = ERR39; - goto FAILED; - } - if (n > 255) - { - *errorcodeptr = ERR38; - goto FAILED; - } - *code++ = n; - PUT(code, 0, (int)(ptr - cd->start_pattern + 1)); /* Pattern offset */ - PUT(code, LINK_SIZE, 0); /* Default length */ - code += 2 * LINK_SIZE; - } - previous = NULL; - continue; - - - /* ------------------------------------------------------------ */ - case CHAR_P: /* Python-style named subpattern handling */ - if (*(++ptr) == CHAR_EQUALS_SIGN || - *ptr == CHAR_GREATER_THAN_SIGN) /* Reference or recursion */ - { - is_recurse = *ptr == CHAR_GREATER_THAN_SIGN; - terminator = CHAR_RIGHT_PARENTHESIS; - goto NAMED_REF_OR_RECURSE; - } - else if (*ptr != CHAR_LESS_THAN_SIGN) /* Test for Python-style defn */ - { - *errorcodeptr = ERR41; - goto FAILED; - } - /* Fall through to handle (?P< as (?< is handled */ - - - /* ------------------------------------------------------------ */ - DEFINE_NAME: /* Come here from (?< handling */ - case CHAR_APOSTROPHE: - { - terminator = (*ptr == CHAR_LESS_THAN_SIGN)? - CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE; - name = ++ptr; - - while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++; - namelen = (int)(ptr - name); - - /* In the pre-compile phase, just do a syntax check. */ - - if (lengthptr != NULL) - { - if (*ptr != terminator) - { - *errorcodeptr = ERR42; - goto FAILED; - } - if (cd->names_found >= MAX_NAME_COUNT) - { - *errorcodeptr = ERR49; - goto FAILED; - } - if (namelen + IMM2_SIZE + 1 > cd->name_entry_size) - { - cd->name_entry_size = namelen + IMM2_SIZE + 1; - if (namelen > MAX_NAME_SIZE) - { - *errorcodeptr = ERR48; - goto FAILED; - } - } - } - - /* In the real compile, create the entry in the table, maintaining - alphabetical order. Duplicate names for different numbers are - permitted only if PCRE_DUPNAMES is set. Duplicate names for the same - number are always OK. (An existing number can be re-used if (?| - appears in the pattern.) In either event, a duplicate name results in - a duplicate entry in the table, even if the number is the same. This - is because the number of names, and hence the table size, is computed - in the pre-compile, and it affects various numbers and pointers which - would all have to be modified, and the compiled code moved down, if - duplicates with the same number were omitted from the table. This - doesn't seem worth the hassle. However, *different* names for the - same number are not permitted. */ - - else - { - BOOL dupname = FALSE; - slot = cd->name_table; - - for (i = 0; i < cd->names_found; i++) - { - int crc = memcmp(name, slot+IMM2_SIZE, IN_UCHARS(namelen)); - if (crc == 0) - { - if (slot[IMM2_SIZE+namelen] == 0) - { - if (GET2(slot, 0) != cd->bracount + 1 && - (options & PCRE_DUPNAMES) == 0) - { - *errorcodeptr = ERR43; - goto FAILED; - } - else dupname = TRUE; - } - else crc = -1; /* Current name is a substring */ - } - - /* Make space in the table and break the loop for an earlier - name. For a duplicate or later name, carry on. We do this for - duplicates so that in the simple case (when ?(| is not used) they - are in order of their numbers. */ - - if (crc < 0) - { - memmove(slot + cd->name_entry_size, slot, - IN_UCHARS((cd->names_found - i) * cd->name_entry_size)); - break; - } - - /* Continue the loop for a later or duplicate name */ - - slot += cd->name_entry_size; - } - - /* For non-duplicate names, check for a duplicate number before - adding the new name. */ - - if (!dupname) - { - pcre_uchar *cslot = cd->name_table; - for (i = 0; i < cd->names_found; i++) - { - if (cslot != slot) - { - if (GET2(cslot, 0) == cd->bracount + 1) - { - *errorcodeptr = ERR65; - goto FAILED; - } - } - else i--; - cslot += cd->name_entry_size; - } - } - - PUT2(slot, 0, cd->bracount + 1); - memcpy(slot + IMM2_SIZE, name, IN_UCHARS(namelen)); - slot[IMM2_SIZE + namelen] = 0; - } - } - - /* In both pre-compile and compile, count the number of names we've - encountered. */ - - cd->names_found++; - ptr++; /* Move past > or ' */ - goto NUMBERED_GROUP; - - - /* ------------------------------------------------------------ */ - case CHAR_AMPERSAND: /* Perl recursion/subroutine syntax */ - terminator = CHAR_RIGHT_PARENTHESIS; - is_recurse = TRUE; - /* Fall through */ - - /* We come here from the Python syntax above that handles both - references (?P=name) and recursion (?P>name), as well as falling - through from the Perl recursion syntax (?&name). We also come here from - the Perl \k<name> or \k'name' back reference syntax and the \k{name} - .NET syntax, and the Oniguruma \g<...> and \g'...' subroutine syntax. */ - - NAMED_REF_OR_RECURSE: - name = ++ptr; - while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++; - namelen = (int)(ptr - name); - - /* In the pre-compile phase, do a syntax check. We used to just set - a dummy reference number, because it was not used in the first pass. - However, with the change of recursive back references to be atomic, - we have to look for the number so that this state can be identified, as - otherwise the incorrect length is computed. If it's not a backwards - reference, the dummy number will do. */ - - if (lengthptr != NULL) - { - const pcre_uchar *temp; - - if (namelen == 0) - { - *errorcodeptr = ERR62; - goto FAILED; - } - if (*ptr != terminator) - { - *errorcodeptr = ERR42; - goto FAILED; - } - if (namelen > MAX_NAME_SIZE) - { - *errorcodeptr = ERR48; - goto FAILED; - } - - /* The name table does not exist in the first pass, so we cannot - do a simple search as in the code below. Instead, we have to scan the - pattern to find the number. It is important that we scan it only as - far as we have got because the syntax of named subpatterns has not - been checked for the rest of the pattern, and find_parens() assumes - correct syntax. In any case, it's a waste of resources to scan - further. We stop the scan at the current point by temporarily - adjusting the value of cd->endpattern. */ - - temp = cd->end_pattern; - cd->end_pattern = ptr; - recno = find_parens(cd, name, namelen, - (options & PCRE_EXTENDED) != 0, utf); - cd->end_pattern = temp; - if (recno < 0) recno = 0; /* Forward ref; set dummy number */ - } - - /* In the real compile, seek the name in the table. We check the name - first, and then check that we have reached the end of the name in the - table. That way, if the name that is longer than any in the table, - the comparison will fail without reading beyond the table entry. */ - - else - { - slot = cd->name_table; - for (i = 0; i < cd->names_found; i++) - { - if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0 && - slot[IMM2_SIZE+namelen] == 0) - break; - slot += cd->name_entry_size; - } - - if (i < cd->names_found) /* Back reference */ - { - recno = GET2(slot, 0); - } - else if ((recno = /* Forward back reference */ - find_parens(cd, name, namelen, - (options & PCRE_EXTENDED) != 0, utf)) <= 0) - { - *errorcodeptr = ERR15; - goto FAILED; - } - } - - /* In both phases, we can now go to the code than handles numerical - recursion or backreferences. */ - - if (is_recurse) goto HANDLE_RECURSION; - else goto HANDLE_REFERENCE; - - - /* ------------------------------------------------------------ */ - case CHAR_R: /* Recursion */ - ptr++; /* Same as (?0) */ - /* Fall through */ - - - /* ------------------------------------------------------------ */ - case CHAR_MINUS: case CHAR_PLUS: /* Recursion or subroutine */ - case CHAR_0: case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: - case CHAR_5: case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9: - { - const pcre_uchar *called; - terminator = CHAR_RIGHT_PARENTHESIS; - - /* Come here from the \g<...> and \g'...' code (Oniguruma - compatibility). However, the syntax has been checked to ensure that - the ... are a (signed) number, so that neither ERR63 nor ERR29 will - be called on this path, nor with the jump to OTHER_CHAR_AFTER_QUERY - ever be taken. */ - - HANDLE_NUMERICAL_RECURSION: - - if ((refsign = *ptr) == CHAR_PLUS) - { - ptr++; - if (!IS_DIGIT(*ptr)) - { - *errorcodeptr = ERR63; - goto FAILED; - } - } - else if (refsign == CHAR_MINUS) - { - if (!IS_DIGIT(ptr[1])) - goto OTHER_CHAR_AFTER_QUERY; - ptr++; - } - - recno = 0; - while(IS_DIGIT(*ptr)) - recno = recno * 10 + *ptr++ - CHAR_0; - - if (*ptr != terminator) - { - *errorcodeptr = ERR29; - goto FAILED; - } - - if (refsign == CHAR_MINUS) - { - if (recno == 0) - { - *errorcodeptr = ERR58; - goto FAILED; - } - recno = cd->bracount - recno + 1; - if (recno <= 0) - { - *errorcodeptr = ERR15; - goto FAILED; - } - } - else if (refsign == CHAR_PLUS) - { - if (recno == 0) - { - *errorcodeptr = ERR58; - goto FAILED; - } - recno += cd->bracount; - } - - /* Come here from code above that handles a named recursion */ - - HANDLE_RECURSION: - - previous = code; - called = cd->start_code; - - /* When we are actually compiling, find the bracket that is being - referenced. Temporarily end the regex in case it doesn't exist before - this point. If we end up with a forward reference, first check that - the bracket does occur later so we can give the error (and position) - now. Then remember this forward reference in the workspace so it can - be filled in at the end. */ - - if (lengthptr == NULL) - { - *code = OP_END; - if (recno != 0) - called = PRIV(find_bracket)(cd->start_code, utf, recno); - - /* Forward reference */ - - if (called == NULL) - { - if (find_parens(cd, NULL, recno, - (options & PCRE_EXTENDED) != 0, utf) < 0) - { - *errorcodeptr = ERR15; - goto FAILED; - } - - /* Fudge the value of "called" so that when it is inserted as an - offset below, what it actually inserted is the reference number - of the group. Then remember the forward reference. */ - - called = cd->start_code + recno; - if (cd->hwm >= cd->start_workspace + cd->workspace_size - - WORK_SIZE_SAFETY_MARGIN) - { - *errorcodeptr = expand_workspace(cd); - if (*errorcodeptr != 0) goto FAILED; - } - PUTINC(cd->hwm, 0, (int)(code + 1 - cd->start_code)); - } - - /* If not a forward reference, and the subpattern is still open, - this is a recursive call. We check to see if this is a left - recursion that could loop for ever, and diagnose that case. We - must not, however, do this check if we are in a conditional - subpattern because the condition might be testing for recursion in - a pattern such as /(?(R)a+|(?R)b)/, which is perfectly valid. - Forever loops are also detected at runtime, so those that occur in - conditional subpatterns will be picked up then. */ - - else if (GET(called, 1) == 0 && cond_depth <= 0 && - could_be_empty(called, code, bcptr, utf, cd)) - { - *errorcodeptr = ERR40; - goto FAILED; - } - } - - /* Insert the recursion/subroutine item. It does not have a set first - character (relevant if it is repeated, because it will then be - wrapped with ONCE brackets). */ - - *code = OP_RECURSE; - PUT(code, 1, (int)(called - cd->start_code)); - code += 1 + LINK_SIZE; - groupsetfirstchar = FALSE; - } - - /* Can't determine a first byte now */ - - if (firstchar == REQ_UNSET) firstchar = REQ_NONE; - continue; - - - /* ------------------------------------------------------------ */ - default: /* Other characters: check option setting */ - OTHER_CHAR_AFTER_QUERY: - set = unset = 0; - optset = &set; - - while (*ptr != CHAR_RIGHT_PARENTHESIS && *ptr != CHAR_COLON) - { - switch (*ptr++) - { - case CHAR_MINUS: optset = &unset; break; - - case CHAR_J: /* Record that it changed in the external options */ - *optset |= PCRE_DUPNAMES; - cd->external_flags |= PCRE_JCHANGED; - break; - - case CHAR_i: *optset |= PCRE_CASELESS; break; - case CHAR_m: *optset |= PCRE_MULTILINE; break; - case CHAR_s: *optset |= PCRE_DOTALL; break; - case CHAR_x: *optset |= PCRE_EXTENDED; break; - case CHAR_U: *optset |= PCRE_UNGREEDY; break; - case CHAR_X: *optset |= PCRE_EXTRA; break; - - default: *errorcodeptr = ERR12; - ptr--; /* Correct the offset */ - goto FAILED; - } - } - - /* Set up the changed option bits, but don't change anything yet. */ - - newoptions = (options | set) & (~unset); - - /* If the options ended with ')' this is not the start of a nested - group with option changes, so the options change at this level. If this - item is right at the start of the pattern, the options can be - abstracted and made external in the pre-compile phase, and ignored in - the compile phase. This can be helpful when matching -- for instance in - caseless checking of required bytes. - - If the code pointer is not (cd->start_code + 1 + LINK_SIZE), we are - definitely *not* at the start of the pattern because something has been - compiled. In the pre-compile phase, however, the code pointer can have - that value after the start, because it gets reset as code is discarded - during the pre-compile. However, this can happen only at top level - if - we are within parentheses, the starting BRA will still be present. At - any parenthesis level, the length value can be used to test if anything - has been compiled at that level. Thus, a test for both these conditions - is necessary to ensure we correctly detect the start of the pattern in - both phases. - - If we are not at the pattern start, reset the greedy defaults and the - case value for firstchar and reqchar. */ - - if (*ptr == CHAR_RIGHT_PARENTHESIS) - { - if (code == cd->start_code + 1 + LINK_SIZE && - (lengthptr == NULL || *lengthptr == 2 + 2*LINK_SIZE)) - { - cd->external_options = newoptions; - } - else - { - greedy_default = ((newoptions & PCRE_UNGREEDY) != 0); - greedy_non_default = greedy_default ^ 1; - req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS:0; - } - - /* Change options at this level, and pass them back for use - in subsequent branches. */ - - *optionsptr = options = newoptions; - previous = NULL; /* This item can't be repeated */ - continue; /* It is complete */ - } - - /* If the options ended with ':' we are heading into a nested group - with possible change of options. Such groups are non-capturing and are - not assertions of any kind. All we need to do is skip over the ':'; - the newoptions value is handled below. */ - - bravalue = OP_BRA; - ptr++; - } /* End of switch for character following (? */ - } /* End of (? handling */ - - /* Opening parenthesis not followed by '*' or '?'. If PCRE_NO_AUTO_CAPTURE - is set, all unadorned brackets become non-capturing and behave like (?:...) - brackets. */ - - else if ((options & PCRE_NO_AUTO_CAPTURE) != 0) - { - bravalue = OP_BRA; - } - - /* Else we have a capturing group. */ - - else - { - NUMBERED_GROUP: - cd->bracount += 1; - PUT2(code, 1+LINK_SIZE, cd->bracount); - skipbytes = IMM2_SIZE; - } - - /* Process nested bracketed regex. Assertions used not to be repeatable, - but this was changed for Perl compatibility, so all kinds can now be - repeated. We copy code into a non-register variable (tempcode) in order to - be able to pass its address because some compilers complain otherwise. */ - - previous = code; /* For handling repetition */ - *code = bravalue; - tempcode = code; - tempreqvary = cd->req_varyopt; /* Save value before bracket */ - tempbracount = cd->bracount; /* Save value before bracket */ - length_prevgroup = 0; /* Initialize for pre-compile phase */ - - if (!compile_regex( - newoptions, /* The complete new option state */ - &tempcode, /* Where to put code (updated) */ - &ptr, /* Input pointer (updated) */ - errorcodeptr, /* Where to put an error message */ - (bravalue == OP_ASSERTBACK || - bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */ - reset_bracount, /* True if (?| group */ - skipbytes, /* Skip over bracket number */ - cond_depth + - ((bravalue == OP_COND)?1:0), /* Depth of condition subpatterns */ - &subfirstchar, /* For possible first char */ - &subreqchar, /* For possible last char */ - bcptr, /* Current branch chain */ - cd, /* Tables block */ - (lengthptr == NULL)? NULL : /* Actual compile phase */ - &length_prevgroup /* Pre-compile phase */ - )) - goto FAILED; - - /* If this was an atomic group and there are no capturing groups within it, - generate OP_ONCE_NC instead of OP_ONCE. */ - - if (bravalue == OP_ONCE && cd->bracount <= tempbracount) - *code = OP_ONCE_NC; - - if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT) - cd->assert_depth -= 1; - - /* At the end of compiling, code is still pointing to the start of the - group, while tempcode has been updated to point past the end of the group. - The pattern pointer (ptr) is on the bracket. - - If this is a conditional bracket, check that there are no more than - two branches in the group, or just one if it's a DEFINE group. We do this - in the real compile phase, not in the pre-pass, where the whole group may - not be available. */ - - if (bravalue == OP_COND && lengthptr == NULL) - { - pcre_uchar *tc = code; - int condcount = 0; - - do { - condcount++; - tc += GET(tc,1); - } - while (*tc != OP_KET); - - /* A DEFINE group is never obeyed inline (the "condition" is always - false). It must have only one branch. */ - - if (code[LINK_SIZE+1] == OP_DEF) - { - if (condcount > 1) - { - *errorcodeptr = ERR54; - goto FAILED; - } - bravalue = OP_DEF; /* Just a flag to suppress char handling below */ - } - - /* A "normal" conditional group. If there is just one branch, we must not - make use of its firstchar or reqchar, because this is equivalent to an - empty second branch. */ - - else - { - if (condcount > 2) - { - *errorcodeptr = ERR27; - goto FAILED; - } - if (condcount == 1) subfirstchar = subreqchar = REQ_NONE; - } - } - - /* Error if hit end of pattern */ - - if (*ptr != CHAR_RIGHT_PARENTHESIS) - { - *errorcodeptr = ERR14; - goto FAILED; - } - - /* In the pre-compile phase, update the length by the length of the group, - less the brackets at either end. Then reduce the compiled code to just a - set of non-capturing brackets so that it doesn't use much memory if it is - duplicated by a quantifier.*/ - - if (lengthptr != NULL) - { - if (OFLOW_MAX - *lengthptr < length_prevgroup - 2 - 2*LINK_SIZE) - { - *errorcodeptr = ERR20; - goto FAILED; - } - *lengthptr += length_prevgroup - 2 - 2*LINK_SIZE; - code++; /* This already contains bravalue */ - PUTINC(code, 0, 1 + LINK_SIZE); - *code++ = OP_KET; - PUTINC(code, 0, 1 + LINK_SIZE); - break; /* No need to waste time with special character handling */ - } - - /* Otherwise update the main code pointer to the end of the group. */ - - code = tempcode; - - /* For a DEFINE group, required and first character settings are not - relevant. */ - - if (bravalue == OP_DEF) break; - - /* Handle updating of the required and first characters for other types of - group. Update for normal brackets of all kinds, and conditions with two - branches (see code above). If the bracket is followed by a quantifier with - zero repeat, we have to back off. Hence the definition of zeroreqchar and - zerofirstchar outside the main loop so that they can be accessed for the - back off. */ - - zeroreqchar = reqchar; - zerofirstchar = firstchar; - groupsetfirstchar = FALSE; - - if (bravalue >= OP_ONCE) - { - /* If we have not yet set a firstchar in this branch, take it from the - subpattern, remembering that it was set here so that a repeat of more - than one can replicate it as reqchar if necessary. If the subpattern has - no firstchar, set "none" for the whole branch. In both cases, a zero - repeat forces firstchar to "none". */ - - if (firstchar == REQ_UNSET) - { - if (subfirstchar >= 0) - { - firstchar = subfirstchar; - groupsetfirstchar = TRUE; - } - else firstchar = REQ_NONE; - zerofirstchar = REQ_NONE; - } - - /* If firstchar was previously set, convert the subpattern's firstchar - into reqchar if there wasn't one, using the vary flag that was in - existence beforehand. */ - - else if (subfirstchar >= 0 && subreqchar < 0) - subreqchar = subfirstchar | tempreqvary; - - /* If the subpattern set a required byte (or set a first byte that isn't - really the first byte - see above), set it. */ - - if (subreqchar >= 0) reqchar = subreqchar; - } - - /* For a forward assertion, we take the reqchar, if set. This can be - helpful if the pattern that follows the assertion doesn't set a different - char. For example, it's useful for /(?=abcde).+/. We can't set firstchar - for an assertion, however because it leads to incorrect effect for patterns - such as /(?=a)a.+/ when the "real" "a" would then become a reqchar instead - of a firstchar. This is overcome by a scan at the end if there's no - firstchar, looking for an asserted first char. */ - - else if (bravalue == OP_ASSERT && subreqchar >= 0) reqchar = subreqchar; - break; /* End of processing '(' */ - - - /* ===================================================================*/ - /* Handle metasequences introduced by \. For ones like \d, the ESC_ values - are arranged to be the negation of the corresponding OP_values in the - default case when PCRE_UCP is not set. For the back references, the values - are ESC_REF plus the reference number. Only back references and those types - that consume a character may be repeated. We can test for values between - ESC_b and ESC_Z for the latter; this may have to change if any new ones are - ever created. */ - - case CHAR_BACKSLASH: - tempptr = ptr; - c = check_escape(&ptr, errorcodeptr, cd->bracount, options, FALSE); - if (*errorcodeptr != 0) goto FAILED; - - if (c < 0) - { - if (-c == ESC_Q) /* Handle start of quoted string */ - { - if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E) - ptr += 2; /* avoid empty string */ - else inescq = TRUE; - continue; - } - - if (-c == ESC_E) continue; /* Perl ignores an orphan \E */ - - /* For metasequences that actually match a character, we disable the - setting of a first character if it hasn't already been set. */ - - if (firstchar == REQ_UNSET && -c > ESC_b && -c < ESC_Z) - firstchar = REQ_NONE; - - /* Set values to reset to if this is followed by a zero repeat. */ - - zerofirstchar = firstchar; - zeroreqchar = reqchar; - - /* \g<name> or \g'name' is a subroutine call by name and \g<n> or \g'n' - is a subroutine call by number (Oniguruma syntax). In fact, the value - -ESC_g is returned only for these cases. So we don't need to check for < - or ' if the value is -ESC_g. For the Perl syntax \g{n} the value is - -ESC_REF+n, and for the Perl syntax \g{name} the result is -ESC_k (as - that is a synonym for a named back reference). */ - - if (-c == ESC_g) - { - const pcre_uchar *p; - save_hwm = cd->hwm; /* Normally this is set when '(' is read */ - terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? - CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE; - - /* These two statements stop the compiler for warning about possibly - unset variables caused by the jump to HANDLE_NUMERICAL_RECURSION. In - fact, because we actually check for a number below, the paths that - would actually be in error are never taken. */ - - skipbytes = 0; - reset_bracount = FALSE; - - /* Test for a name */ - - if (ptr[1] != CHAR_PLUS && ptr[1] != CHAR_MINUS) - { - BOOL is_a_number = TRUE; - for (p = ptr + 1; *p != 0 && *p != terminator; p++) - { - if (!MAX_255(*p)) { is_a_number = FALSE; break; } - if ((cd->ctypes[*p] & ctype_digit) == 0) is_a_number = FALSE; - if ((cd->ctypes[*p] & ctype_word) == 0) break; - } - if (*p != terminator) - { - *errorcodeptr = ERR57; - break; - } - if (is_a_number) - { - ptr++; - goto HANDLE_NUMERICAL_RECURSION; - } - is_recurse = TRUE; - goto NAMED_REF_OR_RECURSE; - } - - /* Test a signed number in angle brackets or quotes. */ - - p = ptr + 2; - while (IS_DIGIT(*p)) p++; - if (*p != terminator) - { - *errorcodeptr = ERR57; - break; - } - ptr++; - goto HANDLE_NUMERICAL_RECURSION; - } - - /* \k<name> or \k'name' is a back reference by name (Perl syntax). - We also support \k{name} (.NET syntax). */ - - if (-c == ESC_k) - { - if ((ptr[1] != CHAR_LESS_THAN_SIGN && - ptr[1] != CHAR_APOSTROPHE && ptr[1] != CHAR_LEFT_CURLY_BRACKET)) - { - *errorcodeptr = ERR69; - break; - } - is_recurse = FALSE; - terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? - CHAR_GREATER_THAN_SIGN : (*ptr == CHAR_APOSTROPHE)? - CHAR_APOSTROPHE : CHAR_RIGHT_CURLY_BRACKET; - goto NAMED_REF_OR_RECURSE; - } - - /* Back references are handled specially; must disable firstchar if - not set to cope with cases like (?=(\w+))\1: which would otherwise set - ':' later. */ - - if (-c >= ESC_REF) - { - open_capitem *oc; - recno = -c - ESC_REF; - - HANDLE_REFERENCE: /* Come here from named backref handling */ - if (firstchar == REQ_UNSET) firstchar = REQ_NONE; - previous = code; - *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF; - PUT2INC(code, 0, recno); - cd->backref_map |= (recno < 32)? (1 << recno) : 1; - if (recno > cd->top_backref) cd->top_backref = recno; - - /* Check to see if this back reference is recursive, that it, it - is inside the group that it references. A flag is set so that the - group can be made atomic. */ - - for (oc = cd->open_caps; oc != NULL; oc = oc->next) - { - if (oc->number == recno) - { - oc->flag = TRUE; - break; - } - } - } - - /* So are Unicode property matches, if supported. */ - -#ifdef SUPPORT_UCP - else if (-c == ESC_P || -c == ESC_p) - { - BOOL negated; - int pdata; - int ptype = get_ucp(&ptr, &negated, &pdata, errorcodeptr); - if (ptype < 0) goto FAILED; - previous = code; - *code++ = ((-c == ESC_p) != negated)? OP_PROP : OP_NOTPROP; - *code++ = ptype; - *code++ = pdata; - } -#else - - /* If Unicode properties are not supported, \X, \P, and \p are not - allowed. */ - - else if (-c == ESC_X || -c == ESC_P || -c == ESC_p) - { - *errorcodeptr = ERR45; - goto FAILED; - } -#endif - - /* For the rest (including \X when Unicode properties are supported), we - can obtain the OP value by negating the escape value in the default - situation when PCRE_UCP is not set. When it *is* set, we substitute - Unicode property tests. Note that \b and \B do a one-character - lookbehind. */ - - else - { - if ((-c == ESC_b || -c == ESC_B) && cd->max_lookbehind == 0) - cd->max_lookbehind = 1; -#ifdef SUPPORT_UCP - if (-c >= ESC_DU && -c <= ESC_wu) - { - nestptr = ptr + 1; /* Where to resume */ - ptr = substitutes[-c - ESC_DU] - 1; /* Just before substitute */ - } - else -#endif - /* In non-UTF-8 mode, we turn \C into OP_ALLANY instead of OP_ANYBYTE - so that it works in DFA mode and in lookbehinds. */ - - { - previous = (-c > ESC_b && -c < ESC_Z)? code : NULL; - *code++ = (!utf && c == -ESC_C)? OP_ALLANY : -c; - } - } - continue; - } - - /* We have a data character whose value is in c. In UTF-8 mode it may have - a value > 127. We set its representation in the length/buffer, and then - handle it as a data character. */ - -#ifdef SUPPORT_UTF - if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR) - mclength = PRIV(ord2utf)(c, mcbuffer); - else -#endif - - { - mcbuffer[0] = c; - mclength = 1; - } - goto ONE_CHAR; - - - /* ===================================================================*/ - /* Handle a literal character. It is guaranteed not to be whitespace or # - when the extended flag is set. If we are in UTF-8 mode, it may be a - multi-byte literal character. */ - - default: - NORMAL_CHAR: - mclength = 1; - mcbuffer[0] = c; - -#ifdef SUPPORT_UTF - if (utf && HAS_EXTRALEN(c)) - ACROSSCHAR(TRUE, ptr[1], mcbuffer[mclength++] = *(++ptr)); -#endif - - /* At this point we have the character's bytes in mcbuffer, and the length - in mclength. When not in UTF-8 mode, the length is always 1. */ - - ONE_CHAR: - previous = code; - *code++ = ((options & PCRE_CASELESS) != 0)? OP_CHARI : OP_CHAR; - for (c = 0; c < mclength; c++) *code++ = mcbuffer[c]; - - /* Remember if \r or \n were seen */ - - if (mcbuffer[0] == CHAR_CR || mcbuffer[0] == CHAR_NL) - cd->external_flags |= PCRE_HASCRORLF; - - /* Set the first and required bytes appropriately. If no previous first - byte, set it from this character, but revert to none on a zero repeat. - Otherwise, leave the firstchar value alone, and don't change it on a zero - repeat. */ - - if (firstchar == REQ_UNSET) - { - zerofirstchar = REQ_NONE; - zeroreqchar = reqchar; - - /* If the character is more than one byte long, we can set firstchar - only if it is not to be matched caselessly. */ - - if (mclength == 1 || req_caseopt == 0) - { - firstchar = mcbuffer[0] | req_caseopt; - if (mclength != 1) reqchar = code[-1] | cd->req_varyopt; - } - else firstchar = reqchar = REQ_NONE; - } - - /* firstchar was previously set; we can set reqchar only if the length is - 1 or the matching is caseful. */ - - else - { - zerofirstchar = firstchar; - zeroreqchar = reqchar; - if (mclength == 1 || req_caseopt == 0) - reqchar = code[-1] | req_caseopt | cd->req_varyopt; - } - - break; /* End of literal character handling */ - } - } /* end of big loop */ - - -/* Control never reaches here by falling through, only by a goto for all the -error states. Pass back the position in the pattern so that it can be displayed -to the user for diagnosing the error. */ - -FAILED: -*ptrptr = ptr; -return FALSE; -} - - - - -/************************************************* -* Compile sequence of alternatives * -*************************************************/ - -/* On entry, ptr is pointing past the bracket character, but on return it -points to the closing bracket, or vertical bar, or end of string. The code -variable is pointing at the byte into which the BRA operator has been stored. -This function is used during the pre-compile phase when we are trying to find -out the amount of memory needed, as well as during the real compile phase. The -value of lengthptr distinguishes the two phases. - -Arguments: - options option bits, including any changes for this subpattern - codeptr -> the address of the current code pointer - ptrptr -> the address of the current pattern pointer - errorcodeptr -> pointer to error code variable - lookbehind TRUE if this is a lookbehind assertion - reset_bracount TRUE to reset the count for each branch - skipbytes skip this many bytes at start (for brackets and OP_COND) - cond_depth depth of nesting for conditional subpatterns - firstcharptr place to put the first required character, or a negative number - reqcharptr place to put the last required character, or a negative number - bcptr pointer to the chain of currently open branches - cd points to the data block with tables pointers etc. - lengthptr NULL during the real compile phase - points to length accumulator during pre-compile phase - -Returns: TRUE on success -*/ - -static BOOL -compile_regex(int options, pcre_uchar **codeptr, const pcre_uchar **ptrptr, - int *errorcodeptr, BOOL lookbehind, BOOL reset_bracount, int skipbytes, - int cond_depth, pcre_int32 *firstcharptr, pcre_int32 *reqcharptr, - branch_chain *bcptr, compile_data *cd, int *lengthptr) -{ -const pcre_uchar *ptr = *ptrptr; -pcre_uchar *code = *codeptr; -pcre_uchar *last_branch = code; -pcre_uchar *start_bracket = code; -pcre_uchar *reverse_count = NULL; -open_capitem capitem; -int capnumber = 0; -pcre_int32 firstchar, reqchar; -pcre_int32 branchfirstchar, branchreqchar; -int length; -int orig_bracount; -int max_bracount; -branch_chain bc; - -bc.outer = bcptr; -bc.current_branch = code; - -firstchar = reqchar = REQ_UNSET; - -/* Accumulate the length for use in the pre-compile phase. Start with the -length of the BRA and KET and any extra bytes that are required at the -beginning. We accumulate in a local variable to save frequent testing of -lenthptr for NULL. We cannot do this by looking at the value of code at the -start and end of each alternative, because compiled items are discarded during -the pre-compile phase so that the work space is not exceeded. */ - -length = 2 + 2*LINK_SIZE + skipbytes; - -/* WARNING: If the above line is changed for any reason, you must also change -the code that abstracts option settings at the start of the pattern and makes -them global. It tests the value of length for (2 + 2*LINK_SIZE) in the -pre-compile phase to find out whether anything has yet been compiled or not. */ - -/* If this is a capturing subpattern, add to the chain of open capturing items -so that we can detect them if (*ACCEPT) is encountered. This is also used to -detect groups that contain recursive back references to themselves. Note that -only OP_CBRA need be tested here; changing this opcode to one of its variants, -e.g. OP_SCBRAPOS, happens later, after the group has been compiled. */ - -if (*code == OP_CBRA) - { - capnumber = GET2(code, 1 + LINK_SIZE); - capitem.number = capnumber; - capitem.next = cd->open_caps; - capitem.flag = FALSE; - cd->open_caps = &capitem; - } - -/* Offset is set zero to mark that this bracket is still open */ - -PUT(code, 1, 0); -code += 1 + LINK_SIZE + skipbytes; - -/* Loop for each alternative branch */ - -orig_bracount = max_bracount = cd->bracount; -for (;;) - { - /* For a (?| group, reset the capturing bracket count so that each branch - uses the same numbers. */ - - if (reset_bracount) cd->bracount = orig_bracount; - - /* Set up dummy OP_REVERSE if lookbehind assertion */ - - if (lookbehind) - { - *code++ = OP_REVERSE; - reverse_count = code; - PUTINC(code, 0, 0); - length += 1 + LINK_SIZE; - } - - /* Now compile the branch; in the pre-compile phase its length gets added - into the length. */ - - if (!compile_branch(&options, &code, &ptr, errorcodeptr, &branchfirstchar, - &branchreqchar, &bc, cond_depth, cd, - (lengthptr == NULL)? NULL : &length)) - { - *ptrptr = ptr; - return FALSE; - } - - /* Keep the highest bracket count in case (?| was used and some branch - has fewer than the rest. */ - - if (cd->bracount > max_bracount) max_bracount = cd->bracount; - - /* In the real compile phase, there is some post-processing to be done. */ - - if (lengthptr == NULL) - { - /* If this is the first branch, the firstchar and reqchar values for the - branch become the values for the regex. */ - - if (*last_branch != OP_ALT) - { - firstchar = branchfirstchar; - reqchar = branchreqchar; - } - - /* If this is not the first branch, the first char and reqchar have to - match the values from all the previous branches, except that if the - previous value for reqchar didn't have REQ_VARY set, it can still match, - and we set REQ_VARY for the regex. */ - - else - { - /* If we previously had a firstchar, but it doesn't match the new branch, - we have to abandon the firstchar for the regex, but if there was - previously no reqchar, it takes on the value of the old firstchar. */ - - if (firstchar >= 0 && firstchar != branchfirstchar) - { - if (reqchar < 0) reqchar = firstchar; - firstchar = REQ_NONE; - } - - /* If we (now or from before) have no firstchar, a firstchar from the - branch becomes a reqchar if there isn't a branch reqchar. */ - - if (firstchar < 0 && branchfirstchar >= 0 && branchreqchar < 0) - branchreqchar = branchfirstchar; - - /* Now ensure that the reqchars match */ - - if ((reqchar & ~REQ_VARY) != (branchreqchar & ~REQ_VARY)) - reqchar = REQ_NONE; - else reqchar |= branchreqchar; /* To "or" REQ_VARY */ - } - - /* If lookbehind, check that this branch matches a fixed-length string, and - put the length into the OP_REVERSE item. Temporarily mark the end of the - branch with OP_END. If the branch contains OP_RECURSE, the result is -3 - because there may be forward references that we can't check here. Set a - flag to cause another lookbehind check at the end. Why not do it all at the - end? Because common, erroneous checks are picked up here and the offset of - the problem can be shown. */ - - if (lookbehind) - { - int fixed_length; - *code = OP_END; - fixed_length = find_fixedlength(last_branch, (options & PCRE_UTF8) != 0, - FALSE, cd); - DPRINTF(("fixed length = %d\n", fixed_length)); - if (fixed_length == -3) - { - cd->check_lookbehind = TRUE; - } - else if (fixed_length < 0) - { - *errorcodeptr = (fixed_length == -2)? ERR36 : - (fixed_length == -4)? ERR70: ERR25; - *ptrptr = ptr; - return FALSE; - } - else - { - if (fixed_length > cd->max_lookbehind) - cd->max_lookbehind = fixed_length; - PUT(reverse_count, 0, fixed_length); - } - } - } - - /* Reached end of expression, either ')' or end of pattern. In the real - compile phase, go back through the alternative branches and reverse the chain - of offsets, with the field in the BRA item now becoming an offset to the - first alternative. If there are no alternatives, it points to the end of the - group. The length in the terminating ket is always the length of the whole - bracketed item. Return leaving the pointer at the terminating char. */ - - if (*ptr != CHAR_VERTICAL_LINE) - { - if (lengthptr == NULL) - { - int branch_length = (int)(code - last_branch); - do - { - int prev_length = GET(last_branch, 1); - PUT(last_branch, 1, branch_length); - branch_length = prev_length; - last_branch -= branch_length; - } - while (branch_length > 0); - } - - /* Fill in the ket */ - - *code = OP_KET; - PUT(code, 1, (int)(code - start_bracket)); - code += 1 + LINK_SIZE; - - /* If it was a capturing subpattern, check to see if it contained any - recursive back references. If so, we must wrap it in atomic brackets. - In any event, remove the block from the chain. */ - - if (capnumber > 0) - { - if (cd->open_caps->flag) - { - memmove(start_bracket + 1 + LINK_SIZE, start_bracket, - IN_UCHARS(code - start_bracket)); - *start_bracket = OP_ONCE; - code += 1 + LINK_SIZE; - PUT(start_bracket, 1, (int)(code - start_bracket)); - *code = OP_KET; - PUT(code, 1, (int)(code - start_bracket)); - code += 1 + LINK_SIZE; - length += 2 + 2*LINK_SIZE; - } - cd->open_caps = cd->open_caps->next; - } - - /* Retain the highest bracket number, in case resetting was used. */ - - cd->bracount = max_bracount; - - /* Set values to pass back */ - - *codeptr = code; - *ptrptr = ptr; - *firstcharptr = firstchar; - *reqcharptr = reqchar; - if (lengthptr != NULL) - { - if (OFLOW_MAX - *lengthptr < length) - { - *errorcodeptr = ERR20; - return FALSE; - } - *lengthptr += length; - } - return TRUE; - } - - /* Another branch follows. In the pre-compile phase, we can move the code - pointer back to where it was for the start of the first branch. (That is, - pretend that each branch is the only one.) - - In the real compile phase, insert an ALT node. Its length field points back - to the previous branch while the bracket remains open. At the end the chain - is reversed. It's done like this so that the start of the bracket has a - zero offset until it is closed, making it possible to detect recursion. */ - - if (lengthptr != NULL) - { - code = *codeptr + 1 + LINK_SIZE + skipbytes; - length += 1 + LINK_SIZE; - } - else - { - *code = OP_ALT; - PUT(code, 1, (int)(code - last_branch)); - bc.current_branch = last_branch = code; - code += 1 + LINK_SIZE; - } - - ptr++; - } -/* Control never reaches here */ -} - - - - -/************************************************* -* Check for anchored expression * -*************************************************/ - -/* Try to find out if this is an anchored regular expression. Consider each -alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket -all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then -it's anchored. However, if this is a multiline pattern, then only OP_SOD will -be found, because ^ generates OP_CIRCM in that mode. - -We can also consider a regex to be anchored if OP_SOM starts all its branches. -This is the code for \G, which means "match at start of match position, taking -into account the match offset". - -A branch is also implicitly anchored if it starts with .* and DOTALL is set, -because that will try the rest of the pattern at all possible matching points, -so there is no point trying again.... er .... - -.... except when the .* appears inside capturing parentheses, and there is a -subsequent back reference to those parentheses. We haven't enough information -to catch that case precisely. - -At first, the best we could do was to detect when .* was in capturing brackets -and the highest back reference was greater than or equal to that level. -However, by keeping a bitmap of the first 31 back references, we can catch some -of the more common cases more precisely. - -Arguments: - code points to start of expression (the bracket) - bracket_map a bitmap of which brackets we are inside while testing; this - handles up to substring 31; after that we just have to take - the less precise approach - backref_map the back reference bitmap - -Returns: TRUE or FALSE -*/ - -static BOOL -is_anchored(const pcre_uchar *code, unsigned int bracket_map, - unsigned int backref_map) -{ -do { - const pcre_uchar *scode = first_significant_code( - code + PRIV(OP_lengths)[*code], FALSE); - int op = *scode; - - /* Non-capturing brackets */ - - if (op == OP_BRA || op == OP_BRAPOS || - op == OP_SBRA || op == OP_SBRAPOS) - { - if (!is_anchored(scode, bracket_map, backref_map)) return FALSE; - } - - /* Capturing brackets */ - - else if (op == OP_CBRA || op == OP_CBRAPOS || - op == OP_SCBRA || op == OP_SCBRAPOS) - { - int n = GET2(scode, 1+LINK_SIZE); - int new_map = bracket_map | ((n < 32)? (1 << n) : 1); - if (!is_anchored(scode, new_map, backref_map)) return FALSE; - } - - /* Other brackets */ - - else if (op == OP_ASSERT || op == OP_ONCE || op == OP_ONCE_NC || - op == OP_COND) - { - if (!is_anchored(scode, bracket_map, backref_map)) return FALSE; - } - - /* .* is not anchored unless DOTALL is set (which generates OP_ALLANY) and - it isn't in brackets that are or may be referenced. */ - - else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR || - op == OP_TYPEPOSSTAR)) - { - if (scode[1] != OP_ALLANY || (bracket_map & backref_map) != 0) - return FALSE; - } - - /* Check for explicit anchoring */ - - else if (op != OP_SOD && op != OP_SOM && op != OP_CIRC) return FALSE; - code += GET(code, 1); - } -while (*code == OP_ALT); /* Loop for each alternative */ -return TRUE; -} - - - -/************************************************* -* Check for starting with ^ or .* * -*************************************************/ - -/* This is called to find out if every branch starts with ^ or .* so that -"first char" processing can be done to speed things up in multiline -matching and for non-DOTALL patterns that start with .* (which must start at -the beginning or after \n). As in the case of is_anchored() (see above), we -have to take account of back references to capturing brackets that contain .* -because in that case we can't make the assumption. - -Arguments: - code points to start of expression (the bracket) - bracket_map a bitmap of which brackets we are inside while testing; this - handles up to substring 31; after that we just have to take - the less precise approach - backref_map the back reference bitmap - -Returns: TRUE or FALSE -*/ - -static BOOL -is_startline(const pcre_uchar *code, unsigned int bracket_map, - unsigned int backref_map) -{ -do { - const pcre_uchar *scode = first_significant_code( - code + PRIV(OP_lengths)[*code], FALSE); - int op = *scode; - - /* If we are at the start of a conditional assertion group, *both* the - conditional assertion *and* what follows the condition must satisfy the test - for start of line. Other kinds of condition fail. Note that there may be an - auto-callout at the start of a condition. */ - - if (op == OP_COND) - { - scode += 1 + LINK_SIZE; - if (*scode == OP_CALLOUT) scode += PRIV(OP_lengths)[OP_CALLOUT]; - switch (*scode) - { - case OP_CREF: - case OP_NCREF: - case OP_RREF: - case OP_NRREF: - case OP_DEF: - return FALSE; - - default: /* Assertion */ - if (!is_startline(scode, bracket_map, backref_map)) return FALSE; - do scode += GET(scode, 1); while (*scode == OP_ALT); - scode += 1 + LINK_SIZE; - break; - } - scode = first_significant_code(scode, FALSE); - op = *scode; - } - - /* Non-capturing brackets */ - - if (op == OP_BRA || op == OP_BRAPOS || - op == OP_SBRA || op == OP_SBRAPOS) - { - if (!is_startline(scode, bracket_map, backref_map)) return FALSE; - } - - /* Capturing brackets */ - - else if (op == OP_CBRA || op == OP_CBRAPOS || - op == OP_SCBRA || op == OP_SCBRAPOS) - { - int n = GET2(scode, 1+LINK_SIZE); - int new_map = bracket_map | ((n < 32)? (1 << n) : 1); - if (!is_startline(scode, new_map, backref_map)) return FALSE; - } - - /* Other brackets */ - - else if (op == OP_ASSERT || op == OP_ONCE || op == OP_ONCE_NC) - { - if (!is_startline(scode, bracket_map, backref_map)) return FALSE; - } - - /* .* means "start at start or after \n" if it isn't in brackets that - may be referenced. */ - - else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR) - { - if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE; - } - - /* Check for explicit circumflex */ - - else if (op != OP_CIRC && op != OP_CIRCM) return FALSE; - - /* Move on to the next alternative */ - - code += GET(code, 1); - } -while (*code == OP_ALT); /* Loop for each alternative */ -return TRUE; -} - - - -/************************************************* -* Check for asserted fixed first char * -*************************************************/ - -/* During compilation, the "first char" settings from forward assertions are -discarded, because they can cause conflicts with actual literals that follow. -However, if we end up without a first char setting for an unanchored pattern, -it is worth scanning the regex to see if there is an initial asserted first -char. If all branches start with the same asserted char, or with a bracket all -of whose alternatives start with the same asserted char (recurse ad lib), then -we return that char, otherwise -1. - -Arguments: - code points to start of expression (the bracket) - inassert TRUE if in an assertion - -Returns: -1 or the fixed first char -*/ - -static int -find_firstassertedchar(const pcre_uchar *code, BOOL inassert) -{ -int c = -1; -do { - int d; - int xl = (*code == OP_CBRA || *code == OP_SCBRA || - *code == OP_CBRAPOS || *code == OP_SCBRAPOS)? IMM2_SIZE:0; - const pcre_uchar *scode = first_significant_code(code + 1+LINK_SIZE + xl, - TRUE); - int op = *scode; - - switch(op) - { - default: - return -1; - - case OP_BRA: - case OP_BRAPOS: - case OP_CBRA: - case OP_SCBRA: - case OP_CBRAPOS: - case OP_SCBRAPOS: - case OP_ASSERT: - case OP_ONCE: - case OP_ONCE_NC: - case OP_COND: - if ((d = find_firstassertedchar(scode, op == OP_ASSERT)) < 0) - return -1; - if (c < 0) c = d; else if (c != d) return -1; - break; - - case OP_EXACT: - scode += IMM2_SIZE; - /* Fall through */ - - case OP_CHAR: - case OP_PLUS: - case OP_MINPLUS: - case OP_POSPLUS: - if (!inassert) return -1; - if (c < 0) c = scode[1]; - else if (c != scode[1]) return -1; - break; - - case OP_EXACTI: - scode += IMM2_SIZE; - /* Fall through */ - - case OP_CHARI: - case OP_PLUSI: - case OP_MINPLUSI: - case OP_POSPLUSI: - if (!inassert) return -1; - if (c < 0) c = scode[1] | REQ_CASELESS; - else if (c != scode[1]) return -1; - break; - } - - code += GET(code, 1); - } -while (*code == OP_ALT); -return c; -} - - - -/************************************************* -* Compile a Regular Expression * -*************************************************/ - -/* This function takes a string and returns a pointer to a block of store -holding a compiled version of the expression. The original API for this -function had no error code return variable; it is retained for backwards -compatibility. The new function is given a new name. - -Arguments: - pattern the regular expression - options various option bits - errorcodeptr pointer to error code variable (pcre_compile2() only) - can be NULL if you don't want a code value - errorptr pointer to pointer to error text - erroroffset ptr offset in pattern where error was detected - tables pointer to character tables or NULL - -Returns: pointer to compiled data block, or NULL on error, - with errorptr and erroroffset set -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION -pcre_compile(const char *pattern, int options, const char **errorptr, - int *erroroffset, const unsigned char *tables) -#else -PCRE_EXP_DEFN pcre16 * PCRE_CALL_CONVENTION -pcre16_compile(PCRE_SPTR16 pattern, int options, const char **errorptr, - int *erroroffset, const unsigned char *tables) -#endif -{ -#ifdef COMPILE_PCRE8 -return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables); -#else -return pcre16_compile2(pattern, options, NULL, errorptr, erroroffset, tables); -#endif -} - - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION -pcre_compile2(const char *pattern, int options, int *errorcodeptr, - const char **errorptr, int *erroroffset, const unsigned char *tables) -#else -PCRE_EXP_DEFN pcre16 * PCRE_CALL_CONVENTION -pcre16_compile2(PCRE_SPTR16 pattern, int options, int *errorcodeptr, - const char **errorptr, int *erroroffset, const unsigned char *tables) -#endif -{ -REAL_PCRE *re; -int length = 1; /* For final END opcode */ -pcre_int32 firstchar, reqchar; -int newline; -int errorcode = 0; -int skipatstart = 0; -BOOL utf; -size_t size; -pcre_uchar *code; -const pcre_uchar *codestart; -const pcre_uchar *ptr; -compile_data compile_block; -compile_data *cd = &compile_block; - -/* This space is used for "compiling" into during the first phase, when we are -computing the amount of memory that is needed. Compiled items are thrown away -as soon as possible, so that a fairly large buffer should be sufficient for -this purpose. The same space is used in the second phase for remembering where -to fill in forward references to subpatterns. That may overflow, in which case -new memory is obtained from malloc(). */ - -pcre_uchar cworkspace[COMPILE_WORK_SIZE]; - -/* Set this early so that early errors get offset 0. */ - -ptr = (const pcre_uchar *)pattern; - -/* We can't pass back an error message if errorptr is NULL; I guess the best we -can do is just return NULL, but we can set a code value if there is a code -pointer. */ - -if (errorptr == NULL) - { - if (errorcodeptr != NULL) *errorcodeptr = 99; - return NULL; - } - -*errorptr = NULL; -if (errorcodeptr != NULL) *errorcodeptr = ERR0; - -/* However, we can give a message for this error */ - -if (erroroffset == NULL) - { - errorcode = ERR16; - goto PCRE_EARLY_ERROR_RETURN2; - } - -*erroroffset = 0; - -/* Set up pointers to the individual character tables */ - -if (tables == NULL) tables = PRIV(default_tables); -cd->lcc = tables + lcc_offset; -cd->fcc = tables + fcc_offset; -cd->cbits = tables + cbits_offset; -cd->ctypes = tables + ctypes_offset; - -/* Check that all undefined public option bits are zero */ - -if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0) - { - errorcode = ERR17; - goto PCRE_EARLY_ERROR_RETURN; - } - -/* Check for global one-time settings at the start of the pattern, and remember -the offset for later. */ - -while (ptr[skipatstart] == CHAR_LEFT_PARENTHESIS && - ptr[skipatstart+1] == CHAR_ASTERISK) - { - int newnl = 0; - int newbsr = 0; - -#ifdef COMPILE_PCRE8 - if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF_RIGHTPAR, 5) == 0) - { skipatstart += 7; options |= PCRE_UTF8; continue; } -#endif -#ifdef COMPILE_PCRE16 - if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF_RIGHTPAR, 6) == 0) - { skipatstart += 8; options |= PCRE_UTF16; continue; } -#endif - else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UCP_RIGHTPAR, 4) == 0) - { skipatstart += 6; options |= PCRE_UCP; continue; } - else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_NO_START_OPT_RIGHTPAR, 13) == 0) - { skipatstart += 15; options |= PCRE_NO_START_OPTIMIZE; continue; } - - if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_CR_RIGHTPAR, 3) == 0) - { skipatstart += 5; newnl = PCRE_NEWLINE_CR; } - else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_LF_RIGHTPAR, 3) == 0) - { skipatstart += 5; newnl = PCRE_NEWLINE_LF; } - else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_CRLF_RIGHTPAR, 5) == 0) - { skipatstart += 7; newnl = PCRE_NEWLINE_CR + PCRE_NEWLINE_LF; } - else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_ANY_RIGHTPAR, 4) == 0) - { skipatstart += 6; newnl = PCRE_NEWLINE_ANY; } - else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_ANYCRLF_RIGHTPAR, 8) == 0) - { skipatstart += 10; newnl = PCRE_NEWLINE_ANYCRLF; } - - else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_BSR_ANYCRLF_RIGHTPAR, 12) == 0) - { skipatstart += 14; newbsr = PCRE_BSR_ANYCRLF; } - else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_BSR_UNICODE_RIGHTPAR, 12) == 0) - { skipatstart += 14; newbsr = PCRE_BSR_UNICODE; } - - if (newnl != 0) - options = (options & ~PCRE_NEWLINE_BITS) | newnl; - else if (newbsr != 0) - options = (options & ~(PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) | newbsr; - else break; - } - -/* PCRE_UTF16 has the same value as PCRE_UTF8. */ -utf = (options & PCRE_UTF8) != 0; - -/* Can't support UTF unless PCRE has been compiled to include the code. The -return of an error code from PRIV(valid_utf)() is a new feature, introduced in -release 8.13. It is passed back from pcre_[dfa_]exec(), but at the moment is -not used here. */ - -#ifdef SUPPORT_UTF -if (utf && (options & PCRE_NO_UTF8_CHECK) == 0 && - (errorcode = PRIV(valid_utf)((PCRE_PUCHAR)pattern, -1, erroroffset)) != 0) - { -#ifdef COMPILE_PCRE8 - errorcode = ERR44; -#else - errorcode = ERR74; -#endif - goto PCRE_EARLY_ERROR_RETURN2; - } -#else -if (utf) - { - errorcode = ERR32; - goto PCRE_EARLY_ERROR_RETURN; - } -#endif - -/* Can't support UCP unless PCRE has been compiled to include the code. */ - -#ifndef SUPPORT_UCP -if ((options & PCRE_UCP) != 0) - { - errorcode = ERR67; - goto PCRE_EARLY_ERROR_RETURN; - } -#endif - -/* Check validity of \R options. */ - -if ((options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == - (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) - { - errorcode = ERR56; - goto PCRE_EARLY_ERROR_RETURN; - } - -/* Handle different types of newline. The three bits give seven cases. The -current code allows for fixed one- or two-byte sequences, plus "any" and -"anycrlf". */ - -switch (options & PCRE_NEWLINE_BITS) - { - case 0: newline = NEWLINE; break; /* Build-time default */ - case PCRE_NEWLINE_CR: newline = CHAR_CR; break; - case PCRE_NEWLINE_LF: newline = CHAR_NL; break; - case PCRE_NEWLINE_CR+ - PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break; - case PCRE_NEWLINE_ANY: newline = -1; break; - case PCRE_NEWLINE_ANYCRLF: newline = -2; break; - default: errorcode = ERR56; goto PCRE_EARLY_ERROR_RETURN; - } - -if (newline == -2) - { - cd->nltype = NLTYPE_ANYCRLF; - } -else if (newline < 0) - { - cd->nltype = NLTYPE_ANY; - } -else - { - cd->nltype = NLTYPE_FIXED; - if (newline > 255) - { - cd->nllen = 2; - cd->nl[0] = (newline >> 8) & 255; - cd->nl[1] = newline & 255; - } - else - { - cd->nllen = 1; - cd->nl[0] = newline; - } - } - -/* Maximum back reference and backref bitmap. The bitmap records up to 31 back -references to help in deciding whether (.*) can be treated as anchored or not. -*/ - -cd->top_backref = 0; -cd->backref_map = 0; - -/* Reflect pattern for debugging output */ - -DPRINTF(("------------------------------------------------------------------\n")); -#ifdef PCRE_DEBUG -print_puchar(stdout, (PCRE_PUCHAR)pattern); -#endif -DPRINTF(("\n")); - -/* Pretend to compile the pattern while actually just accumulating the length -of memory required. This behaviour is triggered by passing a non-NULL final -argument to compile_regex(). We pass a block of workspace (cworkspace) for it -to compile parts of the pattern into; the compiled code is discarded when it is -no longer needed, so hopefully this workspace will never overflow, though there -is a test for its doing so. */ - -cd->bracount = cd->final_bracount = 0; -cd->names_found = 0; -cd->name_entry_size = 0; -cd->name_table = NULL; -cd->start_code = cworkspace; -cd->hwm = cworkspace; -cd->start_workspace = cworkspace; -cd->workspace_size = COMPILE_WORK_SIZE; -cd->start_pattern = (const pcre_uchar *)pattern; -cd->end_pattern = (const pcre_uchar *)(pattern + STRLEN_UC((const pcre_uchar *)pattern)); -cd->req_varyopt = 0; -cd->assert_depth = 0; -cd->max_lookbehind = 0; -cd->external_options = options; -cd->external_flags = 0; -cd->open_caps = NULL; - -/* Now do the pre-compile. On error, errorcode will be set non-zero, so we -don't need to look at the result of the function here. The initial options have -been put into the cd block so that they can be changed if an option setting is -found within the regex right at the beginning. Bringing initial option settings -outside can help speed up starting point checks. */ - -ptr += skipatstart; -code = cworkspace; -*code = OP_BRA; -(void)compile_regex(cd->external_options, &code, &ptr, &errorcode, FALSE, - FALSE, 0, 0, &firstchar, &reqchar, NULL, cd, &length); -if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN; - -DPRINTF(("end pre-compile: length=%d workspace=%d\n", length, - (int)(cd->hwm - cworkspace))); - -if (length > MAX_PATTERN_SIZE) - { - errorcode = ERR20; - goto PCRE_EARLY_ERROR_RETURN; - } - -/* Compute the size of data block needed and get it, either from malloc or -externally provided function. Integer overflow should no longer be possible -because nowadays we limit the maximum value of cd->names_found and -cd->name_entry_size. */ - -size = sizeof(REAL_PCRE) + (length + cd->names_found * cd->name_entry_size) * sizeof(pcre_uchar); -re = (REAL_PCRE *)(PUBL(malloc))(size); - -if (re == NULL) - { - errorcode = ERR21; - goto PCRE_EARLY_ERROR_RETURN; - } - -/* Put in the magic number, and save the sizes, initial options, internal -flags, and character table pointer. NULL is used for the default character -tables. The nullpad field is at the end; it's there to help in the case when a -regex compiled on a system with 4-byte pointers is run on another with 8-byte -pointers. */ - -re->magic_number = MAGIC_NUMBER; -re->size = (int)size; -re->options = cd->external_options; -re->flags = cd->external_flags; -re->first_char = 0; -re->req_char = 0; -re->name_table_offset = sizeof(REAL_PCRE) / sizeof(pcre_uchar); -re->name_entry_size = cd->name_entry_size; -re->name_count = cd->names_found; -re->ref_count = 0; -re->tables = (tables == PRIV(default_tables))? NULL : tables; -re->nullpad = NULL; - -/* The starting points of the name/number translation table and of the code are -passed around in the compile data block. The start/end pattern and initial -options are already set from the pre-compile phase, as is the name_entry_size -field. Reset the bracket count and the names_found field. Also reset the hwm -field; this time it's used for remembering forward references to subpatterns. -*/ - -cd->final_bracount = cd->bracount; /* Save for checking forward references */ -cd->assert_depth = 0; -cd->bracount = 0; -cd->max_lookbehind = 0; -cd->names_found = 0; -cd->name_table = (pcre_uchar *)re + re->name_table_offset; -codestart = cd->name_table + re->name_entry_size * re->name_count; -cd->start_code = codestart; -cd->hwm = (pcre_uchar *)(cd->start_workspace); -cd->req_varyopt = 0; -cd->had_accept = FALSE; -cd->check_lookbehind = FALSE; -cd->open_caps = NULL; - -/* Set up a starting, non-extracting bracket, then compile the expression. On -error, errorcode will be set non-zero, so we don't need to look at the result -of the function here. */ - -ptr = (const pcre_uchar *)pattern + skipatstart; -code = (pcre_uchar *)codestart; -*code = OP_BRA; -(void)compile_regex(re->options, &code, &ptr, &errorcode, FALSE, FALSE, 0, 0, - &firstchar, &reqchar, NULL, cd, NULL); -re->top_bracket = cd->bracount; -re->top_backref = cd->top_backref; -re->max_lookbehind = cd->max_lookbehind; -re->flags = cd->external_flags | PCRE_MODE; - -if (cd->had_accept) reqchar = REQ_NONE; /* Must disable after (*ACCEPT) */ - -/* If not reached end of pattern on success, there's an excess bracket. */ - -if (errorcode == 0 && *ptr != 0) errorcode = ERR22; - -/* Fill in the terminating state and check for disastrous overflow, but -if debugging, leave the test till after things are printed out. */ - -*code++ = OP_END; - -#ifndef PCRE_DEBUG -if (code - codestart > length) errorcode = ERR23; -#endif - -/* Fill in any forward references that are required. There may be repeated -references; optimize for them, as searching a large regex takes time. */ - -if (cd->hwm > cd->start_workspace) - { - int prev_recno = -1; - const pcre_uchar *groupptr = NULL; - while (errorcode == 0 && cd->hwm > cd->start_workspace) - { - int offset, recno; - cd->hwm -= LINK_SIZE; - offset = GET(cd->hwm, 0); - recno = GET(codestart, offset); - if (recno != prev_recno) - { - groupptr = PRIV(find_bracket)(codestart, utf, recno); - prev_recno = recno; - } - if (groupptr == NULL) errorcode = ERR53; - else PUT(((pcre_uchar *)codestart), offset, (int)(groupptr - codestart)); - } - } - -/* If the workspace had to be expanded, free the new memory. */ - -if (cd->workspace_size > COMPILE_WORK_SIZE) - (PUBL(free))((void *)cd->start_workspace); - -/* Give an error if there's back reference to a non-existent capturing -subpattern. */ - -if (errorcode == 0 && re->top_backref > re->top_bracket) errorcode = ERR15; - -/* If there were any lookbehind assertions that contained OP_RECURSE -(recursions or subroutine calls), a flag is set for them to be checked here, -because they may contain forward references. Actual recursions can't be fixed -length, but subroutine calls can. It is done like this so that those without -OP_RECURSE that are not fixed length get a diagnosic with a useful offset. The -exceptional ones forgo this. We scan the pattern to check that they are fixed -length, and set their lengths. */ - -if (cd->check_lookbehind) - { - pcre_uchar *cc = (pcre_uchar *)codestart; - - /* Loop, searching for OP_REVERSE items, and process those that do not have - their length set. (Actually, it will also re-process any that have a length - of zero, but that is a pathological case, and it does no harm.) When we find - one, we temporarily terminate the branch it is in while we scan it. */ - - for (cc = (pcre_uchar *)PRIV(find_bracket)(codestart, utf, -1); - cc != NULL; - cc = (pcre_uchar *)PRIV(find_bracket)(cc, utf, -1)) - { - if (GET(cc, 1) == 0) - { - int fixed_length; - pcre_uchar *be = cc - 1 - LINK_SIZE + GET(cc, -LINK_SIZE); - int end_op = *be; - *be = OP_END; - fixed_length = find_fixedlength(cc, (re->options & PCRE_UTF8) != 0, TRUE, - cd); - *be = end_op; - DPRINTF(("fixed length = %d\n", fixed_length)); - if (fixed_length < 0) - { - errorcode = (fixed_length == -2)? ERR36 : - (fixed_length == -4)? ERR70 : ERR25; - break; - } - if (fixed_length > cd->max_lookbehind) cd->max_lookbehind = fixed_length; - PUT(cc, 1, fixed_length); - } - cc += 1 + LINK_SIZE; - } - } - -/* Failed to compile, or error while post-processing */ - -if (errorcode != 0) - { - (PUBL(free))(re); - PCRE_EARLY_ERROR_RETURN: - *erroroffset = (int)(ptr - (const pcre_uchar *)pattern); - PCRE_EARLY_ERROR_RETURN2: - *errorptr = find_error_text(errorcode); - if (errorcodeptr != NULL) *errorcodeptr = errorcode; - return NULL; - } - -/* If the anchored option was not passed, set the flag if we can determine that -the pattern is anchored by virtue of ^ characters or \A or anything else (such -as starting with .* when DOTALL is set). - -Otherwise, if we know what the first byte has to be, save it, because that -speeds up unanchored matches no end. If not, see if we can set the -PCRE_STARTLINE flag. This is helpful for multiline matches when all branches -start with ^. and also when all branches start with .* for non-DOTALL matches. -*/ - -if ((re->options & PCRE_ANCHORED) == 0) - { - if (is_anchored(codestart, 0, cd->backref_map)) - re->options |= PCRE_ANCHORED; - else - { - if (firstchar < 0) - firstchar = find_firstassertedchar(codestart, FALSE); - if (firstchar >= 0) /* Remove caseless flag for non-caseable chars */ - { -#ifdef COMPILE_PCRE8 - re->first_char = firstchar & 0xff; -#else -#ifdef COMPILE_PCRE16 - re->first_char = firstchar & 0xffff; -#endif -#endif - if ((firstchar & REQ_CASELESS) != 0) - { -#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) - /* We ignore non-ASCII first chars in 8 bit mode. */ - if (utf) - { - if (re->first_char < 128) - { - if (cd->fcc[re->first_char] != re->first_char) - re->flags |= PCRE_FCH_CASELESS; - } - else if (UCD_OTHERCASE(re->first_char) != re->first_char) - re->flags |= PCRE_FCH_CASELESS; - } - else -#endif - if (MAX_255(re->first_char) - && cd->fcc[re->first_char] != re->first_char) - re->flags |= PCRE_FCH_CASELESS; - } - - re->flags |= PCRE_FIRSTSET; - } - else if (is_startline(codestart, 0, cd->backref_map)) - re->flags |= PCRE_STARTLINE; - } - } - -/* For an anchored pattern, we use the "required byte" only if it follows a -variable length item in the regex. Remove the caseless flag for non-caseable -bytes. */ - -if (reqchar >= 0 && - ((re->options & PCRE_ANCHORED) == 0 || (reqchar & REQ_VARY) != 0)) - { -#ifdef COMPILE_PCRE8 - re->req_char = reqchar & 0xff; -#else -#ifdef COMPILE_PCRE16 - re->req_char = reqchar & 0xffff; -#endif -#endif - if ((reqchar & REQ_CASELESS) != 0) - { -#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) - /* We ignore non-ASCII first chars in 8 bit mode. */ - if (utf) - { - if (re->req_char < 128) - { - if (cd->fcc[re->req_char] != re->req_char) - re->flags |= PCRE_RCH_CASELESS; - } - else if (UCD_OTHERCASE(re->req_char) != re->req_char) - re->flags |= PCRE_RCH_CASELESS; - } - else -#endif - if (MAX_255(re->req_char) && cd->fcc[re->req_char] != re->req_char) - re->flags |= PCRE_RCH_CASELESS; - } - - re->flags |= PCRE_REQCHSET; - } - -/* Print out the compiled data if debugging is enabled. This is never the -case when building a production library. */ - -#ifdef PCRE_DEBUG -printf("Length = %d top_bracket = %d top_backref = %d\n", - length, re->top_bracket, re->top_backref); - -printf("Options=%08x\n", re->options); - -if ((re->flags & PCRE_FIRSTSET) != 0) - { - pcre_uchar ch = re->first_char; - const char *caseless = - ((re->flags & PCRE_FCH_CASELESS) == 0)? "" : " (caseless)"; - if (PRINTABLE(ch)) printf("First char = %c%s\n", ch, caseless); - else printf("First char = \\x%02x%s\n", ch, caseless); - } - -if ((re->flags & PCRE_REQCHSET) != 0) - { - pcre_uchar ch = re->req_char; - const char *caseless = - ((re->flags & PCRE_RCH_CASELESS) == 0)? "" : " (caseless)"; - if (PRINTABLE(ch)) printf("Req char = %c%s\n", ch, caseless); - else printf("Req char = \\x%02x%s\n", ch, caseless); - } - -#ifdef COMPILE_PCRE8 -pcre_printint((pcre *)re, stdout, TRUE); -#else -pcre16_printint((pcre *)re, stdout, TRUE); -#endif - -/* This check is done here in the debugging case so that the code that -was compiled can be seen. */ - -if (code - codestart > length) - { - (PUBL(free))(re); - *errorptr = find_error_text(ERR23); - *erroroffset = ptr - (pcre_uchar *)pattern; - if (errorcodeptr != NULL) *errorcodeptr = ERR23; - return NULL; - } -#endif /* PCRE_DEBUG */ - -#ifdef COMPILE_PCRE8 -return (pcre *)re; -#else -return (pcre16 *)re; -#endif -} - -/* End of pcre_compile.c */ diff --git a/glib/pcre/pcre_config.c b/glib/pcre/pcre_config.c deleted file mode 100644 index 34719591f..000000000 --- a/glib/pcre/pcre_config.c +++ /dev/null @@ -1,168 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains the external function pcre_config(). */ - - -#include "config.h" - -/* Keep the original link size. */ -static int real_link_size = LINK_SIZE; - -#include "pcre_internal.h" - - -/************************************************* -* Return info about what features are configured * -*************************************************/ - -/* This function has an extensible interface so that additional items can be -added compatibly. - -Arguments: - what what information is required - where where to put the information - -Returns: 0 if data returned, negative on error -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre_config(int what, void *where) -#else -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre16_config(int what, void *where) -#endif -{ -switch (what) - { - case PCRE_CONFIG_UTF8: -#if defined COMPILE_PCRE16 - *((int *)where) = 0; - return PCRE_ERROR_BADOPTION; -#else -#if defined SUPPORT_UTF - *((int *)where) = 1; -#else - *((int *)where) = 0; -#endif - break; -#endif - - case PCRE_CONFIG_UTF16: -#if defined COMPILE_PCRE8 - *((int *)where) = 0; - return PCRE_ERROR_BADOPTION; -#else -#if defined SUPPORT_UTF - *((int *)where) = 1; -#else - *((int *)where) = 0; -#endif - break; -#endif - - case PCRE_CONFIG_UNICODE_PROPERTIES: -#ifdef SUPPORT_UCP - *((int *)where) = 1; -#else - *((int *)where) = 0; -#endif - break; - - case PCRE_CONFIG_JIT: -#ifdef SUPPORT_JIT - *((int *)where) = 1; -#else - *((int *)where) = 0; -#endif - break; - - case PCRE_CONFIG_JITTARGET: -#ifdef SUPPORT_JIT - *((const char **)where) = PRIV(jit_get_target)(); -#else - *((const char **)where) = NULL; -#endif - break; - - case PCRE_CONFIG_NEWLINE: - *((int *)where) = NEWLINE; - break; - - case PCRE_CONFIG_BSR: -#ifdef BSR_ANYCRLF - *((int *)where) = 1; -#else - *((int *)where) = 0; -#endif - break; - - case PCRE_CONFIG_LINK_SIZE: - *((int *)where) = real_link_size; - break; - - case PCRE_CONFIG_POSIX_MALLOC_THRESHOLD: - *((int *)where) = POSIX_MALLOC_THRESHOLD; - break; - - case PCRE_CONFIG_MATCH_LIMIT: - *((unsigned long int *)where) = MATCH_LIMIT; - break; - - case PCRE_CONFIG_MATCH_LIMIT_RECURSION: - *((unsigned long int *)where) = MATCH_LIMIT_RECURSION; - break; - - case PCRE_CONFIG_STACKRECURSE: -#ifdef NO_RECURSE - *((int *)where) = 0; -#else - *((int *)where) = 1; -#endif - break; - - default: return PCRE_ERROR_BADOPTION; - } - -return 0; -} - -/* End of pcre_config.c */ diff --git a/glib/pcre/pcre_dfa_exec.c b/glib/pcre/pcre_dfa_exec.c deleted file mode 100644 index 9cc82323d..000000000 --- a/glib/pcre/pcre_dfa_exec.c +++ /dev/null @@ -1,3611 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language (but see -below for why this module is different). - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - -/* This module contains the external function pcre_dfa_exec(), which is an -alternative matching function that uses a sort of DFA algorithm (not a true -FSM). This is NOT Perl-compatible, but it has advantages in certain -applications. */ - - -/* NOTE ABOUT PERFORMANCE: A user of this function sent some code that improved -the performance of his patterns greatly. I could not use it as it stood, as it -was not thread safe, and made assumptions about pattern sizes. Also, it caused -test 7 to loop, and test 9 to crash with a segfault. - -The issue is the check for duplicate states, which is done by a simple linear -search up the state list. (Grep for "duplicate" below to find the code.) For -many patterns, there will never be many states active at one time, so a simple -linear search is fine. In patterns that have many active states, it might be a -bottleneck. The suggested code used an indexing scheme to remember which states -had previously been used for each character, and avoided the linear search when -it knew there was no chance of a duplicate. This was implemented when adding -states to the state lists. - -I wrote some thread-safe, not-limited code to try something similar at the time -of checking for duplicates (instead of when adding states), using index vectors -on the stack. It did give a 13% improvement with one specially constructed -pattern for certain subject strings, but on other strings and on many of the -simpler patterns in the test suite it did worse. The major problem, I think, -was the extra time to initialize the index. This had to be done for each call -of internal_dfa_exec(). (The supplied patch used a static vector, initialized -only once - I suspect this was the cause of the problems with the tests.) - -Overall, I concluded that the gains in some cases did not outweigh the losses -in others, so I abandoned this code. */ - - - -#include "config.h" - -#define NLBLOCK md /* Block containing newline information */ -#define PSSTART start_subject /* Field containing processed string start */ -#define PSEND end_subject /* Field containing processed string end */ - -#include "pcre_internal.h" - - -/* For use to indent debugging output */ - -#define SP " " - - -/************************************************* -* Code parameters and static tables * -*************************************************/ - -/* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes -into others, under special conditions. A gap of 20 between the blocks should be -enough. The resulting opcodes don't have to be less than 256 because they are -never stored, so we push them well clear of the normal opcodes. */ - -#define OP_PROP_EXTRA 300 -#define OP_EXTUNI_EXTRA 320 -#define OP_ANYNL_EXTRA 340 -#define OP_HSPACE_EXTRA 360 -#define OP_VSPACE_EXTRA 380 - - -/* This table identifies those opcodes that are followed immediately by a -character that is to be tested in some way. This makes it possible to -centralize the loading of these characters. In the case of Type * etc, the -"character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a -small value. Non-zero values in the table are the offsets from the opcode where -the character is to be found. ***NOTE*** If the start of this table is -modified, the three tables that follow must also be modified. */ - -static const pcre_uint8 coptable[] = { - 0, /* End */ - 0, 0, 0, 0, 0, /* \A, \G, \K, \B, \b */ - 0, 0, 0, 0, 0, 0, /* \D, \d, \S, \s, \W, \w */ - 0, 0, 0, /* Any, AllAny, Anybyte */ - 0, 0, /* \P, \p */ - 0, 0, 0, 0, 0, /* \R, \H, \h, \V, \v */ - 0, /* \X */ - 0, 0, 0, 0, 0, 0, /* \Z, \z, ^, ^M, $, $M */ - 1, /* Char */ - 1, /* Chari */ - 1, /* not */ - 1, /* noti */ - /* Positive single-char repeats */ - 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ - 1+IMM2_SIZE, 1+IMM2_SIZE, /* upto, minupto */ - 1+IMM2_SIZE, /* exact */ - 1, 1, 1, 1+IMM2_SIZE, /* *+, ++, ?+, upto+ */ - 1, 1, 1, 1, 1, 1, /* *I, *?I, +I, +?I, ?I, ??I */ - 1+IMM2_SIZE, 1+IMM2_SIZE, /* upto I, minupto I */ - 1+IMM2_SIZE, /* exact I */ - 1, 1, 1, 1+IMM2_SIZE, /* *+I, ++I, ?+I, upto+I */ - /* Negative single-char repeats - only for chars < 256 */ - 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */ - 1+IMM2_SIZE, 1+IMM2_SIZE, /* NOT upto, minupto */ - 1+IMM2_SIZE, /* NOT exact */ - 1, 1, 1, 1+IMM2_SIZE, /* NOT *+, ++, ?+, upto+ */ - 1, 1, 1, 1, 1, 1, /* NOT *I, *?I, +I, +?I, ?I, ??I */ - 1+IMM2_SIZE, 1+IMM2_SIZE, /* NOT upto I, minupto I */ - 1+IMM2_SIZE, /* NOT exact I */ - 1, 1, 1, 1+IMM2_SIZE, /* NOT *+I, ++I, ?+I, upto+I */ - /* Positive type repeats */ - 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */ - 1+IMM2_SIZE, 1+IMM2_SIZE, /* Type upto, minupto */ - 1+IMM2_SIZE, /* Type exact */ - 1, 1, 1, 1+IMM2_SIZE, /* Type *+, ++, ?+, upto+ */ - /* Character class & ref repeats */ - 0, 0, 0, 0, 0, 0, /* *, *?, +, +?, ?, ?? */ - 0, 0, /* CRRANGE, CRMINRANGE */ - 0, /* CLASS */ - 0, /* NCLASS */ - 0, /* XCLASS - variable length */ - 0, /* REF */ - 0, /* REFI */ - 0, /* RECURSE */ - 0, /* CALLOUT */ - 0, /* Alt */ - 0, /* Ket */ - 0, /* KetRmax */ - 0, /* KetRmin */ - 0, /* KetRpos */ - 0, /* Reverse */ - 0, /* Assert */ - 0, /* Assert not */ - 0, /* Assert behind */ - 0, /* Assert behind not */ - 0, 0, /* ONCE, ONCE_NC */ - 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */ - 0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */ - 0, 0, /* CREF, NCREF */ - 0, 0, /* RREF, NRREF */ - 0, /* DEF */ - 0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */ - 0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */ - 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */ - 0, 0, 0, 0, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */ - 0, 0 /* CLOSE, SKIPZERO */ -}; - -/* This table identifies those opcodes that inspect a character. It is used to -remember the fact that a character could have been inspected when the end of -the subject is reached. ***NOTE*** If the start of this table is modified, the -two tables that follow must also be modified. */ - -static const pcre_uint8 poptable[] = { - 0, /* End */ - 0, 0, 0, 1, 1, /* \A, \G, \K, \B, \b */ - 1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */ - 1, 1, 1, /* Any, AllAny, Anybyte */ - 1, 1, /* \P, \p */ - 1, 1, 1, 1, 1, /* \R, \H, \h, \V, \v */ - 1, /* \X */ - 0, 0, 0, 0, 0, 0, /* \Z, \z, ^, ^M, $, $M */ - 1, /* Char */ - 1, /* Chari */ - 1, /* not */ - 1, /* noti */ - /* Positive single-char repeats */ - 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ - 1, 1, 1, /* upto, minupto, exact */ - 1, 1, 1, 1, /* *+, ++, ?+, upto+ */ - 1, 1, 1, 1, 1, 1, /* *I, *?I, +I, +?I, ?I, ??I */ - 1, 1, 1, /* upto I, minupto I, exact I */ - 1, 1, 1, 1, /* *+I, ++I, ?+I, upto+I */ - /* Negative single-char repeats - only for chars < 256 */ - 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */ - 1, 1, 1, /* NOT upto, minupto, exact */ - 1, 1, 1, 1, /* NOT *+, ++, ?+, upto+ */ - 1, 1, 1, 1, 1, 1, /* NOT *I, *?I, +I, +?I, ?I, ??I */ - 1, 1, 1, /* NOT upto I, minupto I, exact I */ - 1, 1, 1, 1, /* NOT *+I, ++I, ?+I, upto+I */ - /* Positive type repeats */ - 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */ - 1, 1, 1, /* Type upto, minupto, exact */ - 1, 1, 1, 1, /* Type *+, ++, ?+, upto+ */ - /* Character class & ref repeats */ - 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ - 1, 1, /* CRRANGE, CRMINRANGE */ - 1, /* CLASS */ - 1, /* NCLASS */ - 1, /* XCLASS - variable length */ - 0, /* REF */ - 0, /* REFI */ - 0, /* RECURSE */ - 0, /* CALLOUT */ - 0, /* Alt */ - 0, /* Ket */ - 0, /* KetRmax */ - 0, /* KetRmin */ - 0, /* KetRpos */ - 0, /* Reverse */ - 0, /* Assert */ - 0, /* Assert not */ - 0, /* Assert behind */ - 0, /* Assert behind not */ - 0, 0, /* ONCE, ONCE_NC */ - 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */ - 0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */ - 0, 0, /* CREF, NCREF */ - 0, 0, /* RREF, NRREF */ - 0, /* DEF */ - 0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */ - 0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */ - 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */ - 0, 0, 0, 0, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */ - 0, 0 /* CLOSE, SKIPZERO */ -}; - -/* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W, -and \w */ - -static const pcre_uint8 toptable1[] = { - 0, 0, 0, 0, 0, 0, - ctype_digit, ctype_digit, - ctype_space, ctype_space, - ctype_word, ctype_word, - 0, 0 /* OP_ANY, OP_ALLANY */ -}; - -static const pcre_uint8 toptable2[] = { - 0, 0, 0, 0, 0, 0, - ctype_digit, 0, - ctype_space, 0, - ctype_word, 0, - 1, 1 /* OP_ANY, OP_ALLANY */ -}; - - -/* Structure for holding data about a particular state, which is in effect the -current data for an active path through the match tree. It must consist -entirely of ints because the working vector we are passed, and which we put -these structures in, is a vector of ints. */ - -typedef struct stateblock { - int offset; /* Offset to opcode */ - int count; /* Count for repeats */ - int data; /* Some use extra data */ -} stateblock; - -#define INTS_PER_STATEBLOCK (int)(sizeof(stateblock)/sizeof(int)) - - -#ifdef PCRE_DEBUG -/************************************************* -* Print character string * -*************************************************/ - -/* Character string printing function for debugging. - -Arguments: - p points to string - length number of bytes - f where to print - -Returns: nothing -*/ - -static void -pchars(const pcre_uchar *p, int length, FILE *f) -{ -int c; -while (length-- > 0) - { - if (isprint(c = *(p++))) - fprintf(f, "%c", c); - else - fprintf(f, "\\x%02x", c); - } -} -#endif - - - -/************************************************* -* Execute a Regular Expression - DFA engine * -*************************************************/ - -/* This internal function applies a compiled pattern to a subject string, -starting at a given point, using a DFA engine. This function is called from the -external one, possibly multiple times if the pattern is not anchored. The -function calls itself recursively for some kinds of subpattern. - -Arguments: - md the match_data block with fixed information - this_start_code the opening bracket of this subexpression's code - current_subject where we currently are in the subject string - start_offset start offset in the subject string - offsets vector to contain the matching string offsets - offsetcount size of same - workspace vector of workspace - wscount size of same - rlevel function call recursion level - -Returns: > 0 => number of match offset pairs placed in offsets - = 0 => offsets overflowed; longest matches are present - -1 => failed to match - < -1 => some kind of unexpected problem - -The following macros are used for adding states to the two state vectors (one -for the current character, one for the following character). */ - -#define ADD_ACTIVE(x,y) \ - if (active_count++ < wscount) \ - { \ - next_active_state->offset = (x); \ - next_active_state->count = (y); \ - next_active_state++; \ - DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \ - } \ - else return PCRE_ERROR_DFA_WSSIZE - -#define ADD_ACTIVE_DATA(x,y,z) \ - if (active_count++ < wscount) \ - { \ - next_active_state->offset = (x); \ - next_active_state->count = (y); \ - next_active_state->data = (z); \ - next_active_state++; \ - DPRINTF(("%.*sADD_ACTIVE_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \ - } \ - else return PCRE_ERROR_DFA_WSSIZE - -#define ADD_NEW(x,y) \ - if (new_count++ < wscount) \ - { \ - next_new_state->offset = (x); \ - next_new_state->count = (y); \ - next_new_state++; \ - DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \ - } \ - else return PCRE_ERROR_DFA_WSSIZE - -#define ADD_NEW_DATA(x,y,z) \ - if (new_count++ < wscount) \ - { \ - next_new_state->offset = (x); \ - next_new_state->count = (y); \ - next_new_state->data = (z); \ - next_new_state++; \ - DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d) line %d\n", rlevel*2-2, SP, \ - (x), (y), (z), __LINE__)); \ - } \ - else return PCRE_ERROR_DFA_WSSIZE - -/* And now, here is the code */ - -static int -internal_dfa_exec( - dfa_match_data *md, - const pcre_uchar *this_start_code, - const pcre_uchar *current_subject, - int start_offset, - int *offsets, - int offsetcount, - int *workspace, - int wscount, - int rlevel) -{ -stateblock *active_states, *new_states, *temp_states; -stateblock *next_active_state, *next_new_state; - -const pcre_uint8 *ctypes, *lcc, *fcc; -const pcre_uchar *ptr; -const pcre_uchar *end_code, *first_op; - -dfa_recursion_info new_recursive; - -int active_count, new_count, match_count; - -/* Some fields in the md block are frequently referenced, so we load them into -independent variables in the hope that this will perform better. */ - -const pcre_uchar *start_subject = md->start_subject; -const pcre_uchar *end_subject = md->end_subject; -const pcre_uchar *start_code = md->start_code; - -#ifdef SUPPORT_UTF -BOOL utf = (md->poptions & PCRE_UTF8) != 0; -#else -BOOL utf = FALSE; -#endif - -BOOL reset_could_continue = FALSE; - -rlevel++; -offsetcount &= (-2); - -wscount -= 2; -wscount = (wscount - (wscount % (INTS_PER_STATEBLOCK * 2))) / - (2 * INTS_PER_STATEBLOCK); - -DPRINTF(("\n%.*s---------------------\n" - "%.*sCall to internal_dfa_exec f=%d\n", - rlevel*2-2, SP, rlevel*2-2, SP, rlevel)); - -ctypes = md->tables + ctypes_offset; -lcc = md->tables + lcc_offset; -fcc = md->tables + fcc_offset; - -match_count = PCRE_ERROR_NOMATCH; /* A negative number */ - -active_states = (stateblock *)(workspace + 2); -next_new_state = new_states = active_states + wscount; -new_count = 0; - -first_op = this_start_code + 1 + LINK_SIZE + - ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA || - *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS) - ? IMM2_SIZE:0); - -/* The first thing in any (sub) pattern is a bracket of some sort. Push all -the alternative states onto the list, and find out where the end is. This -makes is possible to use this function recursively, when we want to stop at a -matching internal ket rather than at the end. - -If the first opcode in the first alternative is OP_REVERSE, we are dealing with -a backward assertion. In that case, we have to find out the maximum amount to -move back, and set up each alternative appropriately. */ - -if (*first_op == OP_REVERSE) - { - int max_back = 0; - int gone_back; - - end_code = this_start_code; - do - { - int back = GET(end_code, 2+LINK_SIZE); - if (back > max_back) max_back = back; - end_code += GET(end_code, 1); - } - while (*end_code == OP_ALT); - - /* If we can't go back the amount required for the longest lookbehind - pattern, go back as far as we can; some alternatives may still be viable. */ - -#ifdef SUPPORT_UTF - /* In character mode we have to step back character by character */ - - if (utf) - { - for (gone_back = 0; gone_back < max_back; gone_back++) - { - if (current_subject <= start_subject) break; - current_subject--; - ACROSSCHAR(current_subject > start_subject, *current_subject, current_subject--); - } - } - else -#endif - - /* In byte-mode we can do this quickly. */ - - { - gone_back = (current_subject - max_back < start_subject)? - (int)(current_subject - start_subject) : max_back; - current_subject -= gone_back; - } - - /* Save the earliest consulted character */ - - if (current_subject < md->start_used_ptr) - md->start_used_ptr = current_subject; - - /* Now we can process the individual branches. */ - - end_code = this_start_code; - do - { - int back = GET(end_code, 2+LINK_SIZE); - if (back <= gone_back) - { - int bstate = (int)(end_code - start_code + 2 + 2*LINK_SIZE); - ADD_NEW_DATA(-bstate, 0, gone_back - back); - } - end_code += GET(end_code, 1); - } - while (*end_code == OP_ALT); - } - -/* This is the code for a "normal" subpattern (not a backward assertion). The -start of a whole pattern is always one of these. If we are at the top level, -we may be asked to restart matching from the same point that we reached for a -previous partial match. We still have to scan through the top-level branches to -find the end state. */ - -else - { - end_code = this_start_code; - - /* Restarting */ - - if (rlevel == 1 && (md->moptions & PCRE_DFA_RESTART) != 0) - { - do { end_code += GET(end_code, 1); } while (*end_code == OP_ALT); - new_count = workspace[1]; - if (!workspace[0]) - memcpy(new_states, active_states, new_count * sizeof(stateblock)); - } - - /* Not restarting */ - - else - { - int length = 1 + LINK_SIZE + - ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA || - *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS) - ? IMM2_SIZE:0); - do - { - ADD_NEW((int)(end_code - start_code + length), 0); - end_code += GET(end_code, 1); - length = 1 + LINK_SIZE; - } - while (*end_code == OP_ALT); - } - } - -workspace[0] = 0; /* Bit indicating which vector is current */ - -DPRINTF(("%.*sEnd state = %d\n", rlevel*2-2, SP, (int)(end_code - start_code))); - -/* Loop for scanning the subject */ - -ptr = current_subject; -for (;;) - { - int i, j; - int clen, dlen; - unsigned int c, d; - int forced_fail = 0; - BOOL partial_newline = FALSE; - BOOL could_continue = reset_could_continue; - reset_could_continue = FALSE; - - /* Make the new state list into the active state list and empty the - new state list. */ - - temp_states = active_states; - active_states = new_states; - new_states = temp_states; - active_count = new_count; - new_count = 0; - - workspace[0] ^= 1; /* Remember for the restarting feature */ - workspace[1] = active_count; - -#ifdef PCRE_DEBUG - printf("%.*sNext character: rest of subject = \"", rlevel*2-2, SP); - pchars(ptr, STRLEN_UC(ptr), stdout); - printf("\"\n"); - - printf("%.*sActive states: ", rlevel*2-2, SP); - for (i = 0; i < active_count; i++) - printf("%d/%d ", active_states[i].offset, active_states[i].count); - printf("\n"); -#endif - - /* Set the pointers for adding new states */ - - next_active_state = active_states + active_count; - next_new_state = new_states; - - /* Load the current character from the subject outside the loop, as many - different states may want to look at it, and we assume that at least one - will. */ - - if (ptr < end_subject) - { - clen = 1; /* Number of data items in the character */ -#ifdef SUPPORT_UTF - if (utf) { GETCHARLEN(c, ptr, clen); } else -#endif /* SUPPORT_UTF */ - c = *ptr; - } - else - { - clen = 0; /* This indicates the end of the subject */ - c = NOTACHAR; /* This value should never actually be used */ - } - - /* Scan up the active states and act on each one. The result of an action - may be to add more states to the currently active list (e.g. on hitting a - parenthesis) or it may be to put states on the new list, for considering - when we move the character pointer on. */ - - for (i = 0; i < active_count; i++) - { - stateblock *current_state = active_states + i; - BOOL caseless = FALSE; - const pcre_uchar *code; - int state_offset = current_state->offset; - int count, codevalue, rrc; - -#ifdef PCRE_DEBUG - printf ("%.*sProcessing state %d c=", rlevel*2-2, SP, state_offset); - if (clen == 0) printf("EOL\n"); - else if (c > 32 && c < 127) printf("'%c'\n", c); - else printf("0x%02x\n", c); -#endif - - /* A negative offset is a special case meaning "hold off going to this - (negated) state until the number of characters in the data field have - been skipped". If the could_continue flag was passed over from a previous - state, arrange for it to passed on. */ - - if (state_offset < 0) - { - if (current_state->data > 0) - { - DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP)); - ADD_NEW_DATA(state_offset, current_state->count, - current_state->data - 1); - if (could_continue) reset_could_continue = TRUE; - continue; - } - else - { - current_state->offset = state_offset = -state_offset; - } - } - - /* Check for a duplicate state with the same count, and skip if found. - See the note at the head of this module about the possibility of improving - performance here. */ - - for (j = 0; j < i; j++) - { - if (active_states[j].offset == state_offset && - active_states[j].count == current_state->count) - { - DPRINTF(("%.*sDuplicate state: skipped\n", rlevel*2-2, SP)); - goto NEXT_ACTIVE_STATE; - } - } - - /* The state offset is the offset to the opcode */ - - code = start_code + state_offset; - codevalue = *code; - - /* If this opcode inspects a character, but we are at the end of the - subject, remember the fact for use when testing for a partial match. */ - - if (clen == 0 && poptable[codevalue] != 0) - could_continue = TRUE; - - /* If this opcode is followed by an inline character, load it. It is - tempting to test for the presence of a subject character here, but that - is wrong, because sometimes zero repetitions of the subject are - permitted. - - We also use this mechanism for opcodes such as OP_TYPEPLUS that take an - argument that is not a data character - but is always one byte long because - the values are small. We have to take special action to deal with \P, \p, - \H, \h, \V, \v and \X in this case. To keep the other cases fast, convert - these ones to new opcodes. */ - - if (coptable[codevalue] > 0) - { - dlen = 1; -#ifdef SUPPORT_UTF - if (utf) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else -#endif /* SUPPORT_UTF */ - d = code[coptable[codevalue]]; - if (codevalue >= OP_TYPESTAR) - { - switch(d) - { - case OP_ANYBYTE: return PCRE_ERROR_DFA_UITEM; - case OP_NOTPROP: - case OP_PROP: codevalue += OP_PROP_EXTRA; break; - case OP_ANYNL: codevalue += OP_ANYNL_EXTRA; break; - case OP_EXTUNI: codevalue += OP_EXTUNI_EXTRA; break; - case OP_NOT_HSPACE: - case OP_HSPACE: codevalue += OP_HSPACE_EXTRA; break; - case OP_NOT_VSPACE: - case OP_VSPACE: codevalue += OP_VSPACE_EXTRA; break; - default: break; - } - } - } - else - { - dlen = 0; /* Not strictly necessary, but compilers moan */ - d = NOTACHAR; /* if these variables are not set. */ - } - - - /* Now process the individual opcodes */ - - switch (codevalue) - { -/* ========================================================================== */ - /* These cases are never obeyed. This is a fudge that causes a compile- - time error if the vectors coptable or poptable, which are indexed by - opcode, are not the correct length. It seems to be the only way to do - such a check at compile time, as the sizeof() operator does not work - in the C preprocessor. */ - - case OP_TABLE_LENGTH: - case OP_TABLE_LENGTH + - ((sizeof(coptable) == OP_TABLE_LENGTH) && - (sizeof(poptable) == OP_TABLE_LENGTH)): - break; - -/* ========================================================================== */ - /* Reached a closing bracket. If not at the end of the pattern, carry - on with the next opcode. For repeating opcodes, also add the repeat - state. Note that KETRPOS will always be encountered at the end of the - subpattern, because the possessive subpattern repeats are always handled - using recursive calls. Thus, it never adds any new states. - - At the end of the (sub)pattern, unless we have an empty string and - PCRE_NOTEMPTY is set, or PCRE_NOTEMPTY_ATSTART is set and we are at the - start of the subject, save the match data, shifting up all previous - matches so we always have the longest first. */ - - case OP_KET: - case OP_KETRMIN: - case OP_KETRMAX: - case OP_KETRPOS: - if (code != end_code) - { - ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0); - if (codevalue != OP_KET) - { - ADD_ACTIVE(state_offset - GET(code, 1), 0); - } - } - else - { - if (ptr > current_subject || - ((md->moptions & PCRE_NOTEMPTY) == 0 && - ((md->moptions & PCRE_NOTEMPTY_ATSTART) == 0 || - current_subject > start_subject + md->start_offset))) - { - if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0; - else if (match_count > 0 && ++match_count * 2 > offsetcount) - match_count = 0; - count = ((match_count == 0)? offsetcount : match_count * 2) - 2; - if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int)); - if (offsetcount >= 2) - { - offsets[0] = (int)(current_subject - start_subject); - offsets[1] = (int)(ptr - start_subject); - DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP, - offsets[1] - offsets[0], (char *)current_subject)); - } - if ((md->moptions & PCRE_DFA_SHORTEST) != 0) - { - DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n" - "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, - match_count, rlevel*2-2, SP)); - return match_count; - } - } - } - break; - -/* ========================================================================== */ - /* These opcodes add to the current list of states without looking - at the current character. */ - - /*-----------------------------------------------------------------*/ - case OP_ALT: - do { code += GET(code, 1); } while (*code == OP_ALT); - ADD_ACTIVE((int)(code - start_code), 0); - break; - - /*-----------------------------------------------------------------*/ - case OP_BRA: - case OP_SBRA: - do - { - ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0); - code += GET(code, 1); - } - while (*code == OP_ALT); - break; - - /*-----------------------------------------------------------------*/ - case OP_CBRA: - case OP_SCBRA: - ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE + IMM2_SIZE), 0); - code += GET(code, 1); - while (*code == OP_ALT) - { - ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0); - code += GET(code, 1); - } - break; - - /*-----------------------------------------------------------------*/ - case OP_BRAZERO: - case OP_BRAMINZERO: - ADD_ACTIVE(state_offset + 1, 0); - code += 1 + GET(code, 2); - while (*code == OP_ALT) code += GET(code, 1); - ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0); - break; - - /*-----------------------------------------------------------------*/ - case OP_SKIPZERO: - code += 1 + GET(code, 2); - while (*code == OP_ALT) code += GET(code, 1); - ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0); - break; - - /*-----------------------------------------------------------------*/ - case OP_CIRC: - if (ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) - { ADD_ACTIVE(state_offset + 1, 0); } - break; - - /*-----------------------------------------------------------------*/ - case OP_CIRCM: - if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) || - (ptr != end_subject && WAS_NEWLINE(ptr))) - { ADD_ACTIVE(state_offset + 1, 0); } - break; - - /*-----------------------------------------------------------------*/ - case OP_EOD: - if (ptr >= end_subject) - { - if ((md->moptions & PCRE_PARTIAL_HARD) != 0) - could_continue = TRUE; - else { ADD_ACTIVE(state_offset + 1, 0); } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_SOD: - if (ptr == start_subject) { ADD_ACTIVE(state_offset + 1, 0); } - break; - - /*-----------------------------------------------------------------*/ - case OP_SOM: - if (ptr == start_subject + start_offset) { ADD_ACTIVE(state_offset + 1, 0); } - break; - - -/* ========================================================================== */ - /* These opcodes inspect the next subject character, and sometimes - the previous one as well, but do not have an argument. The variable - clen contains the length of the current character and is zero if we are - at the end of the subject. */ - - /*-----------------------------------------------------------------*/ - case OP_ANY: - if (clen > 0 && !IS_NEWLINE(ptr)) - { - if (ptr + 1 >= md->end_subject && - (md->moptions & (PCRE_PARTIAL_HARD)) != 0 && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - c == NLBLOCK->nl[0]) - { - could_continue = partial_newline = TRUE; - } - else - { - ADD_NEW(state_offset + 1, 0); - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_ALLANY: - if (clen > 0) - { ADD_NEW(state_offset + 1, 0); } - break; - - /*-----------------------------------------------------------------*/ - case OP_EODN: - if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0) - could_continue = TRUE; - else if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - md->nllen)) - { ADD_ACTIVE(state_offset + 1, 0); } - break; - - /*-----------------------------------------------------------------*/ - case OP_DOLL: - if ((md->moptions & PCRE_NOTEOL) == 0) - { - if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0) - could_continue = TRUE; - else if (clen == 0 || - ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) && - (ptr == end_subject - md->nllen) - )) - { ADD_ACTIVE(state_offset + 1, 0); } - else if (ptr + 1 >= md->end_subject && - (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - c == NLBLOCK->nl[0]) - { - if ((md->moptions & PCRE_PARTIAL_HARD) != 0) - { - reset_could_continue = TRUE; - ADD_NEW_DATA(-(state_offset + 1), 0, 1); - } - else could_continue = partial_newline = TRUE; - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_DOLLM: - if ((md->moptions & PCRE_NOTEOL) == 0) - { - if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0) - could_continue = TRUE; - else if (clen == 0 || - ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr))) - { ADD_ACTIVE(state_offset + 1, 0); } - else if (ptr + 1 >= md->end_subject && - (md->moptions & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) != 0 && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - c == NLBLOCK->nl[0]) - { - if ((md->moptions & PCRE_PARTIAL_HARD) != 0) - { - reset_could_continue = TRUE; - ADD_NEW_DATA(-(state_offset + 1), 0, 1); - } - else could_continue = partial_newline = TRUE; - } - } - else if (IS_NEWLINE(ptr)) - { ADD_ACTIVE(state_offset + 1, 0); } - break; - - /*-----------------------------------------------------------------*/ - - case OP_DIGIT: - case OP_WHITESPACE: - case OP_WORDCHAR: - if (clen > 0 && c < 256 && - ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0) - { ADD_NEW(state_offset + 1, 0); } - break; - - /*-----------------------------------------------------------------*/ - case OP_NOT_DIGIT: - case OP_NOT_WHITESPACE: - case OP_NOT_WORDCHAR: - if (clen > 0 && (c >= 256 || - ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0)) - { ADD_NEW(state_offset + 1, 0); } - break; - - /*-----------------------------------------------------------------*/ - case OP_WORD_BOUNDARY: - case OP_NOT_WORD_BOUNDARY: - { - int left_word, right_word; - - if (ptr > start_subject) - { - const pcre_uchar *temp = ptr - 1; - if (temp < md->start_used_ptr) md->start_used_ptr = temp; -#ifdef SUPPORT_UTF - if (utf) { BACKCHAR(temp); } -#endif - GETCHARTEST(d, temp); -#ifdef SUPPORT_UCP - if ((md->poptions & PCRE_UCP) != 0) - { - if (d == '_') left_word = TRUE; else - { - int cat = UCD_CATEGORY(d); - left_word = (cat == ucp_L || cat == ucp_N); - } - } - else -#endif - left_word = d < 256 && (ctypes[d] & ctype_word) != 0; - } - else left_word = FALSE; - - if (clen > 0) - { -#ifdef SUPPORT_UCP - if ((md->poptions & PCRE_UCP) != 0) - { - if (c == '_') right_word = TRUE; else - { - int cat = UCD_CATEGORY(c); - right_word = (cat == ucp_L || cat == ucp_N); - } - } - else -#endif - right_word = c < 256 && (ctypes[c] & ctype_word) != 0; - } - else right_word = FALSE; - - if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY)) - { ADD_ACTIVE(state_offset + 1, 0); } - } - break; - - - /*-----------------------------------------------------------------*/ - /* Check the next character by Unicode property. We will get here only - if the support is in the binary; otherwise a compile-time error occurs. - */ - -#ifdef SUPPORT_UCP - case OP_PROP: - case OP_NOTPROP: - if (clen > 0) - { - BOOL OK; - const pcre_uint8 chartype = UCD_CHARTYPE(c); - switch(code[1]) - { - case PT_ANY: - OK = TRUE; - break; - - case PT_LAMP: - OK = chartype == ucp_Lu || chartype == ucp_Ll || - chartype == ucp_Lt; - break; - - case PT_GC: - OK = PRIV(ucp_gentype)[chartype] == code[2]; - break; - - case PT_PC: - OK = chartype == code[2]; - break; - - case PT_SC: - OK = UCD_SCRIPT(c) == code[2]; - break; - - /* These are specials for combination cases. */ - - case PT_ALNUM: - OK = PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N; - break; - - case PT_SPACE: /* Perl space */ - OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR; - break; - - case PT_PXSPACE: /* POSIX space */ - OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR; - break; - - case PT_WORD: - OK = PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N || - c == CHAR_UNDERSCORE; - break; - - /* Should never occur, but keep compilers from grumbling. */ - - default: - OK = codevalue != OP_PROP; - break; - } - - if (OK == (codevalue == OP_PROP)) { ADD_NEW(state_offset + 3, 0); } - } - break; -#endif - - - -/* ========================================================================== */ - /* These opcodes likewise inspect the subject character, but have an - argument that is not a data character. It is one of these opcodes: - OP_ANY, OP_ALLANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE, - OP_WORDCHAR, OP_NOT_WORDCHAR. The value is loaded into d. */ - - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEPOSPLUS: - count = current_state->count; /* Already matched */ - if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } - if (clen > 0) - { - if (d == OP_ANY && ptr + 1 >= md->end_subject && - (md->moptions & (PCRE_PARTIAL_HARD)) != 0 && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - c == NLBLOCK->nl[0]) - { - could_continue = partial_newline = TRUE; - } - else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || - (c < 256 && - (d != OP_ANY || !IS_NEWLINE(ptr)) && - ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) - { - if (count > 0 && codevalue == OP_TYPEPOSPLUS) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - count++; - ADD_NEW(state_offset, count); - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_TYPEQUERY: - case OP_TYPEMINQUERY: - case OP_TYPEPOSQUERY: - ADD_ACTIVE(state_offset + 2, 0); - if (clen > 0) - { - if (d == OP_ANY && ptr + 1 >= md->end_subject && - (md->moptions & (PCRE_PARTIAL_HARD)) != 0 && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - c == NLBLOCK->nl[0]) - { - could_continue = partial_newline = TRUE; - } - else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || - (c < 256 && - (d != OP_ANY || !IS_NEWLINE(ptr)) && - ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) - { - if (codevalue == OP_TYPEPOSQUERY) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - ADD_NEW(state_offset + 2, 0); - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEPOSSTAR: - ADD_ACTIVE(state_offset + 2, 0); - if (clen > 0) - { - if (d == OP_ANY && ptr + 1 >= md->end_subject && - (md->moptions & (PCRE_PARTIAL_HARD)) != 0 && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - c == NLBLOCK->nl[0]) - { - could_continue = partial_newline = TRUE; - } - else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || - (c < 256 && - (d != OP_ANY || !IS_NEWLINE(ptr)) && - ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) - { - if (codevalue == OP_TYPEPOSSTAR) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - ADD_NEW(state_offset, 0); - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_TYPEEXACT: - count = current_state->count; /* Number already matched */ - if (clen > 0) - { - if (d == OP_ANY && ptr + 1 >= md->end_subject && - (md->moptions & (PCRE_PARTIAL_HARD)) != 0 && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - c == NLBLOCK->nl[0]) - { - could_continue = partial_newline = TRUE; - } - else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || - (c < 256 && - (d != OP_ANY || !IS_NEWLINE(ptr)) && - ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) - { - if (++count >= GET2(code, 1)) - { ADD_NEW(state_offset + 1 + IMM2_SIZE + 1, 0); } - else - { ADD_NEW(state_offset, count); } - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_TYPEUPTO: - case OP_TYPEMINUPTO: - case OP_TYPEPOSUPTO: - ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); - count = current_state->count; /* Number already matched */ - if (clen > 0) - { - if (d == OP_ANY && ptr + 1 >= md->end_subject && - (md->moptions & (PCRE_PARTIAL_HARD)) != 0 && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - c == NLBLOCK->nl[0]) - { - could_continue = partial_newline = TRUE; - } - else if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || - (c < 256 && - (d != OP_ANY || !IS_NEWLINE(ptr)) && - ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) - { - if (codevalue == OP_TYPEPOSUPTO) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - if (++count >= GET2(code, 1)) - { ADD_NEW(state_offset + 2 + IMM2_SIZE, 0); } - else - { ADD_NEW(state_offset, count); } - } - } - break; - -/* ========================================================================== */ - /* These are virtual opcodes that are used when something like - OP_TYPEPLUS has OP_PROP, OP_NOTPROP, OP_ANYNL, or OP_EXTUNI as its - argument. It keeps the code above fast for the other cases. The argument - is in the d variable. */ - -#ifdef SUPPORT_UCP - case OP_PROP_EXTRA + OP_TYPEPLUS: - case OP_PROP_EXTRA + OP_TYPEMINPLUS: - case OP_PROP_EXTRA + OP_TYPEPOSPLUS: - count = current_state->count; /* Already matched */ - if (count > 0) { ADD_ACTIVE(state_offset + 4, 0); } - if (clen > 0) - { - BOOL OK; - const pcre_uint8 chartype = UCD_CHARTYPE(c); - switch(code[2]) - { - case PT_ANY: - OK = TRUE; - break; - - case PT_LAMP: - OK = chartype == ucp_Lu || chartype == ucp_Ll || - chartype == ucp_Lt; - break; - - case PT_GC: - OK = PRIV(ucp_gentype)[chartype] == code[3]; - break; - - case PT_PC: - OK = chartype == code[3]; - break; - - case PT_SC: - OK = UCD_SCRIPT(c) == code[3]; - break; - - /* These are specials for combination cases. */ - - case PT_ALNUM: - OK = PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N; - break; - - case PT_SPACE: /* Perl space */ - OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR; - break; - - case PT_PXSPACE: /* POSIX space */ - OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR; - break; - - case PT_WORD: - OK = PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N || - c == CHAR_UNDERSCORE; - break; - - /* Should never occur, but keep compilers from grumbling. */ - - default: - OK = codevalue != OP_PROP; - break; - } - - if (OK == (d == OP_PROP)) - { - if (count > 0 && codevalue == OP_PROP_EXTRA + OP_TYPEPOSPLUS) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - count++; - ADD_NEW(state_offset, count); - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_EXTUNI_EXTRA + OP_TYPEPLUS: - case OP_EXTUNI_EXTRA + OP_TYPEMINPLUS: - case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS: - count = current_state->count; /* Already matched */ - if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } - if (clen > 0 && UCD_CATEGORY(c) != ucp_M) - { - const pcre_uchar *nptr = ptr + clen; - int ncount = 0; - if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - while (nptr < end_subject) - { - int nd; - int ndlen = 1; - GETCHARLEN(nd, nptr, ndlen); - if (UCD_CATEGORY(nd) != ucp_M) break; - ncount++; - nptr += ndlen; - } - count++; - ADD_NEW_DATA(-state_offset, count, ncount); - } - break; -#endif - - /*-----------------------------------------------------------------*/ - case OP_ANYNL_EXTRA + OP_TYPEPLUS: - case OP_ANYNL_EXTRA + OP_TYPEMINPLUS: - case OP_ANYNL_EXTRA + OP_TYPEPOSPLUS: - count = current_state->count; /* Already matched */ - if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } - if (clen > 0) - { - int ncount = 0; - switch (c) - { - case 0x000b: - case 0x000c: - case 0x0085: - case 0x2028: - case 0x2029: - if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break; - goto ANYNL01; - - case 0x000d: - if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1; - /* Fall through */ - - ANYNL01: - case 0x000a: - if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - count++; - ADD_NEW_DATA(-state_offset, count, ncount); - break; - - default: - break; - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_VSPACE_EXTRA + OP_TYPEPLUS: - case OP_VSPACE_EXTRA + OP_TYPEMINPLUS: - case OP_VSPACE_EXTRA + OP_TYPEPOSPLUS: - count = current_state->count; /* Already matched */ - if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } - if (clen > 0) - { - BOOL OK; - switch (c) - { - case 0x000a: - case 0x000b: - case 0x000c: - case 0x000d: - case 0x0085: - case 0x2028: - case 0x2029: - OK = TRUE; - break; - - default: - OK = FALSE; - break; - } - - if (OK == (d == OP_VSPACE)) - { - if (count > 0 && codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSPLUS) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - count++; - ADD_NEW_DATA(-state_offset, count, 0); - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_HSPACE_EXTRA + OP_TYPEPLUS: - case OP_HSPACE_EXTRA + OP_TYPEMINPLUS: - case OP_HSPACE_EXTRA + OP_TYPEPOSPLUS: - count = current_state->count; /* Already matched */ - if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } - if (clen > 0) - { - BOOL OK; - switch (c) - { - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - OK = TRUE; - break; - - default: - OK = FALSE; - break; - } - - if (OK == (d == OP_HSPACE)) - { - if (count > 0 && codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSPLUS) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - count++; - ADD_NEW_DATA(-state_offset, count, 0); - } - } - break; - - /*-----------------------------------------------------------------*/ -#ifdef SUPPORT_UCP - case OP_PROP_EXTRA + OP_TYPEQUERY: - case OP_PROP_EXTRA + OP_TYPEMINQUERY: - case OP_PROP_EXTRA + OP_TYPEPOSQUERY: - count = 4; - goto QS1; - - case OP_PROP_EXTRA + OP_TYPESTAR: - case OP_PROP_EXTRA + OP_TYPEMINSTAR: - case OP_PROP_EXTRA + OP_TYPEPOSSTAR: - count = 0; - - QS1: - - ADD_ACTIVE(state_offset + 4, 0); - if (clen > 0) - { - BOOL OK; - const pcre_uint8 chartype = UCD_CHARTYPE(c); - switch(code[2]) - { - case PT_ANY: - OK = TRUE; - break; - - case PT_LAMP: - OK = chartype == ucp_Lu || chartype == ucp_Ll || - chartype == ucp_Lt; - break; - - case PT_GC: - OK = PRIV(ucp_gentype)[chartype] == code[3]; - break; - - case PT_PC: - OK = chartype == code[3]; - break; - - case PT_SC: - OK = UCD_SCRIPT(c) == code[3]; - break; - - /* These are specials for combination cases. */ - - case PT_ALNUM: - OK = PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N; - break; - - case PT_SPACE: /* Perl space */ - OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR; - break; - - case PT_PXSPACE: /* POSIX space */ - OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR; - break; - - case PT_WORD: - OK = PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N || - c == CHAR_UNDERSCORE; - break; - - /* Should never occur, but keep compilers from grumbling. */ - - default: - OK = codevalue != OP_PROP; - break; - } - - if (OK == (d == OP_PROP)) - { - if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSSTAR || - codevalue == OP_PROP_EXTRA + OP_TYPEPOSQUERY) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - ADD_NEW(state_offset + count, 0); - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_EXTUNI_EXTRA + OP_TYPEQUERY: - case OP_EXTUNI_EXTRA + OP_TYPEMINQUERY: - case OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY: - count = 2; - goto QS2; - - case OP_EXTUNI_EXTRA + OP_TYPESTAR: - case OP_EXTUNI_EXTRA + OP_TYPEMINSTAR: - case OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR: - count = 0; - - QS2: - - ADD_ACTIVE(state_offset + 2, 0); - if (clen > 0 && UCD_CATEGORY(c) != ucp_M) - { - const pcre_uchar *nptr = ptr + clen; - int ncount = 0; - if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR || - codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - while (nptr < end_subject) - { - int nd; - int ndlen = 1; - GETCHARLEN(nd, nptr, ndlen); - if (UCD_CATEGORY(nd) != ucp_M) break; - ncount++; - nptr += ndlen; - } - ADD_NEW_DATA(-(state_offset + count), 0, ncount); - } - break; -#endif - - /*-----------------------------------------------------------------*/ - case OP_ANYNL_EXTRA + OP_TYPEQUERY: - case OP_ANYNL_EXTRA + OP_TYPEMINQUERY: - case OP_ANYNL_EXTRA + OP_TYPEPOSQUERY: - count = 2; - goto QS3; - - case OP_ANYNL_EXTRA + OP_TYPESTAR: - case OP_ANYNL_EXTRA + OP_TYPEMINSTAR: - case OP_ANYNL_EXTRA + OP_TYPEPOSSTAR: - count = 0; - - QS3: - ADD_ACTIVE(state_offset + 2, 0); - if (clen > 0) - { - int ncount = 0; - switch (c) - { - case 0x000b: - case 0x000c: - case 0x0085: - case 0x2028: - case 0x2029: - if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break; - goto ANYNL02; - - case 0x000d: - if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1; - /* Fall through */ - - ANYNL02: - case 0x000a: - if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR || - codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - ADD_NEW_DATA(-(state_offset + count), 0, ncount); - break; - - default: - break; - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_VSPACE_EXTRA + OP_TYPEQUERY: - case OP_VSPACE_EXTRA + OP_TYPEMINQUERY: - case OP_VSPACE_EXTRA + OP_TYPEPOSQUERY: - count = 2; - goto QS4; - - case OP_VSPACE_EXTRA + OP_TYPESTAR: - case OP_VSPACE_EXTRA + OP_TYPEMINSTAR: - case OP_VSPACE_EXTRA + OP_TYPEPOSSTAR: - count = 0; - - QS4: - ADD_ACTIVE(state_offset + 2, 0); - if (clen > 0) - { - BOOL OK; - switch (c) - { - case 0x000a: - case 0x000b: - case 0x000c: - case 0x000d: - case 0x0085: - case 0x2028: - case 0x2029: - OK = TRUE; - break; - - default: - OK = FALSE; - break; - } - if (OK == (d == OP_VSPACE)) - { - if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSSTAR || - codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSQUERY) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - ADD_NEW_DATA(-(state_offset + count), 0, 0); - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_HSPACE_EXTRA + OP_TYPEQUERY: - case OP_HSPACE_EXTRA + OP_TYPEMINQUERY: - case OP_HSPACE_EXTRA + OP_TYPEPOSQUERY: - count = 2; - goto QS5; - - case OP_HSPACE_EXTRA + OP_TYPESTAR: - case OP_HSPACE_EXTRA + OP_TYPEMINSTAR: - case OP_HSPACE_EXTRA + OP_TYPEPOSSTAR: - count = 0; - - QS5: - ADD_ACTIVE(state_offset + 2, 0); - if (clen > 0) - { - BOOL OK; - switch (c) - { - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - OK = TRUE; - break; - - default: - OK = FALSE; - break; - } - - if (OK == (d == OP_HSPACE)) - { - if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSSTAR || - codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSQUERY) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - ADD_NEW_DATA(-(state_offset + count), 0, 0); - } - } - break; - - /*-----------------------------------------------------------------*/ -#ifdef SUPPORT_UCP - case OP_PROP_EXTRA + OP_TYPEEXACT: - case OP_PROP_EXTRA + OP_TYPEUPTO: - case OP_PROP_EXTRA + OP_TYPEMINUPTO: - case OP_PROP_EXTRA + OP_TYPEPOSUPTO: - if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT) - { ADD_ACTIVE(state_offset + 1 + IMM2_SIZE + 3, 0); } - count = current_state->count; /* Number already matched */ - if (clen > 0) - { - BOOL OK; - const pcre_uint8 chartype = UCD_CHARTYPE(c); - switch(code[1 + IMM2_SIZE + 1]) - { - case PT_ANY: - OK = TRUE; - break; - - case PT_LAMP: - OK = chartype == ucp_Lu || chartype == ucp_Ll || - chartype == ucp_Lt; - break; - - case PT_GC: - OK = PRIV(ucp_gentype)[chartype] == code[1 + IMM2_SIZE + 2]; - break; - - case PT_PC: - OK = chartype == code[1 + IMM2_SIZE + 2]; - break; - - case PT_SC: - OK = UCD_SCRIPT(c) == code[1 + IMM2_SIZE + 2]; - break; - - /* These are specials for combination cases. */ - - case PT_ALNUM: - OK = PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N; - break; - - case PT_SPACE: /* Perl space */ - OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR; - break; - - case PT_PXSPACE: /* POSIX space */ - OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR; - break; - - case PT_WORD: - OK = PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N || - c == CHAR_UNDERSCORE; - break; - - /* Should never occur, but keep compilers from grumbling. */ - - default: - OK = codevalue != OP_PROP; - break; - } - - if (OK == (d == OP_PROP)) - { - if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSUPTO) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - if (++count >= GET2(code, 1)) - { ADD_NEW(state_offset + 1 + IMM2_SIZE + 3, 0); } - else - { ADD_NEW(state_offset, count); } - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_EXTUNI_EXTRA + OP_TYPEEXACT: - case OP_EXTUNI_EXTRA + OP_TYPEUPTO: - case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO: - case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO: - if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT) - { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); } - count = current_state->count; /* Number already matched */ - if (clen > 0 && UCD_CATEGORY(c) != ucp_M) - { - const pcre_uchar *nptr = ptr + clen; - int ncount = 0; - if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - while (nptr < end_subject) - { - int nd; - int ndlen = 1; - GETCHARLEN(nd, nptr, ndlen); - if (UCD_CATEGORY(nd) != ucp_M) break; - ncount++; - nptr += ndlen; - } - if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0) - reset_could_continue = TRUE; - if (++count >= GET2(code, 1)) - { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); } - else - { ADD_NEW_DATA(-state_offset, count, ncount); } - } - break; -#endif - - /*-----------------------------------------------------------------*/ - case OP_ANYNL_EXTRA + OP_TYPEEXACT: - case OP_ANYNL_EXTRA + OP_TYPEUPTO: - case OP_ANYNL_EXTRA + OP_TYPEMINUPTO: - case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO: - if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT) - { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); } - count = current_state->count; /* Number already matched */ - if (clen > 0) - { - int ncount = 0; - switch (c) - { - case 0x000b: - case 0x000c: - case 0x0085: - case 0x2028: - case 0x2029: - if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break; - goto ANYNL03; - - case 0x000d: - if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1; - /* Fall through */ - - ANYNL03: - case 0x000a: - if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - if (++count >= GET2(code, 1)) - { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); } - else - { ADD_NEW_DATA(-state_offset, count, ncount); } - break; - - default: - break; - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_VSPACE_EXTRA + OP_TYPEEXACT: - case OP_VSPACE_EXTRA + OP_TYPEUPTO: - case OP_VSPACE_EXTRA + OP_TYPEMINUPTO: - case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO: - if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT) - { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); } - count = current_state->count; /* Number already matched */ - if (clen > 0) - { - BOOL OK; - switch (c) - { - case 0x000a: - case 0x000b: - case 0x000c: - case 0x000d: - case 0x0085: - case 0x2028: - case 0x2029: - OK = TRUE; - break; - - default: - OK = FALSE; - } - - if (OK == (d == OP_VSPACE)) - { - if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSUPTO) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - if (++count >= GET2(code, 1)) - { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); } - else - { ADD_NEW_DATA(-state_offset, count, 0); } - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_HSPACE_EXTRA + OP_TYPEEXACT: - case OP_HSPACE_EXTRA + OP_TYPEUPTO: - case OP_HSPACE_EXTRA + OP_TYPEMINUPTO: - case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO: - if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT) - { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); } - count = current_state->count; /* Number already matched */ - if (clen > 0) - { - BOOL OK; - switch (c) - { - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - OK = TRUE; - break; - - default: - OK = FALSE; - break; - } - - if (OK == (d == OP_HSPACE)) - { - if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSUPTO) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - if (++count >= GET2(code, 1)) - { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); } - else - { ADD_NEW_DATA(-state_offset, count, 0); } - } - } - break; - -/* ========================================================================== */ - /* These opcodes are followed by a character that is usually compared - to the current subject character; it is loaded into d. We still get - here even if there is no subject character, because in some cases zero - repetitions are permitted. */ - - /*-----------------------------------------------------------------*/ - case OP_CHAR: - if (clen > 0 && c == d) { ADD_NEW(state_offset + dlen + 1, 0); } - break; - - /*-----------------------------------------------------------------*/ - case OP_CHARI: - if (clen == 0) break; - -#ifdef SUPPORT_UTF - if (utf) - { - if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else - { - unsigned int othercase; - if (c < 128) - othercase = fcc[c]; - else - /* If we have Unicode property support, we can use it to test the - other case of the character. */ -#ifdef SUPPORT_UCP - othercase = UCD_OTHERCASE(c); -#else - othercase = NOTACHAR; -#endif - - if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); } - } - } - else -#endif /* SUPPORT_UTF */ - /* Not UTF mode */ - { - if (TABLE_GET(c, lcc, c) == TABLE_GET(d, lcc, d)) - { ADD_NEW(state_offset + 2, 0); } - } - break; - - -#ifdef SUPPORT_UCP - /*-----------------------------------------------------------------*/ - /* This is a tricky one because it can match more than one character. - Find out how many characters to skip, and then set up a negative state - to wait for them to pass before continuing. */ - - case OP_EXTUNI: - if (clen > 0 && UCD_CATEGORY(c) != ucp_M) - { - const pcre_uchar *nptr = ptr + clen; - int ncount = 0; - while (nptr < end_subject) - { - int nclen = 1; - GETCHARLEN(c, nptr, nclen); - if (UCD_CATEGORY(c) != ucp_M) break; - ncount++; - nptr += nclen; - } - if (nptr >= end_subject && (md->moptions & PCRE_PARTIAL_HARD) != 0) - reset_could_continue = TRUE; - ADD_NEW_DATA(-(state_offset + 1), 0, ncount); - } - break; -#endif - - /*-----------------------------------------------------------------*/ - /* This is a tricky like EXTUNI because it too can match more than one - character (when CR is followed by LF). In this case, set up a negative - state to wait for one character to pass before continuing. */ - - case OP_ANYNL: - if (clen > 0) switch(c) - { - case 0x000b: - case 0x000c: - case 0x0085: - case 0x2028: - case 0x2029: - if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break; - - case 0x000a: - ADD_NEW(state_offset + 1, 0); - break; - - case 0x000d: - if (ptr + 1 >= end_subject) - { - ADD_NEW(state_offset + 1, 0); - if ((md->moptions & PCRE_PARTIAL_HARD) != 0) - reset_could_continue = TRUE; - } - else if (ptr[1] == 0x0a) - { - ADD_NEW_DATA(-(state_offset + 1), 0, 1); - } - else - { - ADD_NEW(state_offset + 1, 0); - } - break; - } - break; - - /*-----------------------------------------------------------------*/ - case OP_NOT_VSPACE: - if (clen > 0) switch(c) - { - case 0x000a: - case 0x000b: - case 0x000c: - case 0x000d: - case 0x0085: - case 0x2028: - case 0x2029: - break; - - default: - ADD_NEW(state_offset + 1, 0); - break; - } - break; - - /*-----------------------------------------------------------------*/ - case OP_VSPACE: - if (clen > 0) switch(c) - { - case 0x000a: - case 0x000b: - case 0x000c: - case 0x000d: - case 0x0085: - case 0x2028: - case 0x2029: - ADD_NEW(state_offset + 1, 0); - break; - - default: break; - } - break; - - /*-----------------------------------------------------------------*/ - case OP_NOT_HSPACE: - if (clen > 0) switch(c) - { - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - break; - - default: - ADD_NEW(state_offset + 1, 0); - break; - } - break; - - /*-----------------------------------------------------------------*/ - case OP_HSPACE: - if (clen > 0) switch(c) - { - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - ADD_NEW(state_offset + 1, 0); - break; - } - break; - - /*-----------------------------------------------------------------*/ - /* Match a negated single character casefully. */ - - case OP_NOT: - if (clen > 0 && c != d) { ADD_NEW(state_offset + dlen + 1, 0); } - break; - - /*-----------------------------------------------------------------*/ - /* Match a negated single character caselessly. */ - - case OP_NOTI: - if (clen > 0) - { - unsigned int otherd; -#ifdef SUPPORT_UTF - if (utf && d >= 128) - { -#ifdef SUPPORT_UCP - otherd = UCD_OTHERCASE(d); -#endif /* SUPPORT_UCP */ - } - else -#endif /* SUPPORT_UTF */ - otherd = TABLE_GET(d, fcc, d); - if (c != d && c != otherd) - { ADD_NEW(state_offset + dlen + 1, 0); } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_PLUSI: - case OP_MINPLUSI: - case OP_POSPLUSI: - case OP_NOTPLUSI: - case OP_NOTMINPLUSI: - case OP_NOTPOSPLUSI: - caseless = TRUE; - codevalue -= OP_STARI - OP_STAR; - - /* Fall through */ - case OP_PLUS: - case OP_MINPLUS: - case OP_POSPLUS: - case OP_NOTPLUS: - case OP_NOTMINPLUS: - case OP_NOTPOSPLUS: - count = current_state->count; /* Already matched */ - if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); } - if (clen > 0) - { - unsigned int otherd = NOTACHAR; - if (caseless) - { -#ifdef SUPPORT_UTF - if (utf && d >= 128) - { -#ifdef SUPPORT_UCP - otherd = UCD_OTHERCASE(d); -#endif /* SUPPORT_UCP */ - } - else -#endif /* SUPPORT_UTF */ - otherd = TABLE_GET(d, fcc, d); - } - if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) - { - if (count > 0 && - (codevalue == OP_POSPLUS || codevalue == OP_NOTPOSPLUS)) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - count++; - ADD_NEW(state_offset, count); - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_QUERYI: - case OP_MINQUERYI: - case OP_POSQUERYI: - case OP_NOTQUERYI: - case OP_NOTMINQUERYI: - case OP_NOTPOSQUERYI: - caseless = TRUE; - codevalue -= OP_STARI - OP_STAR; - /* Fall through */ - case OP_QUERY: - case OP_MINQUERY: - case OP_POSQUERY: - case OP_NOTQUERY: - case OP_NOTMINQUERY: - case OP_NOTPOSQUERY: - ADD_ACTIVE(state_offset + dlen + 1, 0); - if (clen > 0) - { - unsigned int otherd = NOTACHAR; - if (caseless) - { -#ifdef SUPPORT_UTF - if (utf && d >= 128) - { -#ifdef SUPPORT_UCP - otherd = UCD_OTHERCASE(d); -#endif /* SUPPORT_UCP */ - } - else -#endif /* SUPPORT_UTF */ - otherd = TABLE_GET(d, fcc, d); - } - if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) - { - if (codevalue == OP_POSQUERY || codevalue == OP_NOTPOSQUERY) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - ADD_NEW(state_offset + dlen + 1, 0); - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_STARI: - case OP_MINSTARI: - case OP_POSSTARI: - case OP_NOTSTARI: - case OP_NOTMINSTARI: - case OP_NOTPOSSTARI: - caseless = TRUE; - codevalue -= OP_STARI - OP_STAR; - /* Fall through */ - case OP_STAR: - case OP_MINSTAR: - case OP_POSSTAR: - case OP_NOTSTAR: - case OP_NOTMINSTAR: - case OP_NOTPOSSTAR: - ADD_ACTIVE(state_offset + dlen + 1, 0); - if (clen > 0) - { - unsigned int otherd = NOTACHAR; - if (caseless) - { -#ifdef SUPPORT_UTF - if (utf && d >= 128) - { -#ifdef SUPPORT_UCP - otherd = UCD_OTHERCASE(d); -#endif /* SUPPORT_UCP */ - } - else -#endif /* SUPPORT_UTF */ - otherd = TABLE_GET(d, fcc, d); - } - if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) - { - if (codevalue == OP_POSSTAR || codevalue == OP_NOTPOSSTAR) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - ADD_NEW(state_offset, 0); - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_EXACTI: - case OP_NOTEXACTI: - caseless = TRUE; - codevalue -= OP_STARI - OP_STAR; - /* Fall through */ - case OP_EXACT: - case OP_NOTEXACT: - count = current_state->count; /* Number already matched */ - if (clen > 0) - { - unsigned int otherd = NOTACHAR; - if (caseless) - { -#ifdef SUPPORT_UTF - if (utf && d >= 128) - { -#ifdef SUPPORT_UCP - otherd = UCD_OTHERCASE(d); -#endif /* SUPPORT_UCP */ - } - else -#endif /* SUPPORT_UTF */ - otherd = TABLE_GET(d, fcc, d); - } - if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) - { - if (++count >= GET2(code, 1)) - { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); } - else - { ADD_NEW(state_offset, count); } - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_UPTOI: - case OP_MINUPTOI: - case OP_POSUPTOI: - case OP_NOTUPTOI: - case OP_NOTMINUPTOI: - case OP_NOTPOSUPTOI: - caseless = TRUE; - codevalue -= OP_STARI - OP_STAR; - /* Fall through */ - case OP_UPTO: - case OP_MINUPTO: - case OP_POSUPTO: - case OP_NOTUPTO: - case OP_NOTMINUPTO: - case OP_NOTPOSUPTO: - ADD_ACTIVE(state_offset + dlen + 1 + IMM2_SIZE, 0); - count = current_state->count; /* Number already matched */ - if (clen > 0) - { - unsigned int otherd = NOTACHAR; - if (caseless) - { -#ifdef SUPPORT_UTF - if (utf && d >= 128) - { -#ifdef SUPPORT_UCP - otherd = UCD_OTHERCASE(d); -#endif /* SUPPORT_UCP */ - } - else -#endif /* SUPPORT_UTF */ - otherd = TABLE_GET(d, fcc, d); - } - if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) - { - if (codevalue == OP_POSUPTO || codevalue == OP_NOTPOSUPTO) - { - active_count--; /* Remove non-match possibility */ - next_active_state--; - } - if (++count >= GET2(code, 1)) - { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); } - else - { ADD_NEW(state_offset, count); } - } - } - break; - - -/* ========================================================================== */ - /* These are the class-handling opcodes */ - - case OP_CLASS: - case OP_NCLASS: - case OP_XCLASS: - { - BOOL isinclass = FALSE; - int next_state_offset; - const pcre_uchar *ecode; - - /* For a simple class, there is always just a 32-byte table, and we - can set isinclass from it. */ - - if (codevalue != OP_XCLASS) - { - ecode = code + 1 + (32 / sizeof(pcre_uchar)); - if (clen > 0) - { - isinclass = (c > 255)? (codevalue == OP_NCLASS) : - ((((pcre_uint8 *)(code + 1))[c/8] & (1 << (c&7))) != 0); - } - } - - /* An extended class may have a table or a list of single characters, - ranges, or both, and it may be positive or negative. There's a - function that sorts all this out. */ - - else - { - ecode = code + GET(code, 1); - if (clen > 0) isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, utf); - } - - /* At this point, isinclass is set for all kinds of class, and ecode - points to the byte after the end of the class. If there is a - quantifier, this is where it will be. */ - - next_state_offset = (int)(ecode - start_code); - - switch (*ecode) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - ADD_ACTIVE(next_state_offset + 1, 0); - if (isinclass) { ADD_NEW(state_offset, 0); } - break; - - case OP_CRPLUS: - case OP_CRMINPLUS: - count = current_state->count; /* Already matched */ - if (count > 0) { ADD_ACTIVE(next_state_offset + 1, 0); } - if (isinclass) { count++; ADD_NEW(state_offset, count); } - break; - - case OP_CRQUERY: - case OP_CRMINQUERY: - ADD_ACTIVE(next_state_offset + 1, 0); - if (isinclass) { ADD_NEW(next_state_offset + 1, 0); } - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - count = current_state->count; /* Already matched */ - if (count >= GET2(ecode, 1)) - { ADD_ACTIVE(next_state_offset + 1 + 2 * IMM2_SIZE, 0); } - if (isinclass) - { - int max = GET2(ecode, 1 + IMM2_SIZE); - if (++count >= max && max != 0) /* Max 0 => no limit */ - { ADD_NEW(next_state_offset + 1 + 2 * IMM2_SIZE, 0); } - else - { ADD_NEW(state_offset, count); } - } - break; - - default: - if (isinclass) { ADD_NEW(next_state_offset, 0); } - break; - } - } - break; - -/* ========================================================================== */ - /* These are the opcodes for fancy brackets of various kinds. We have - to use recursion in order to handle them. The "always failing" assertion - (?!) is optimised to OP_FAIL when compiling, so we have to support that, - though the other "backtracking verbs" are not supported. */ - - case OP_FAIL: - forced_fail++; /* Count FAILs for multiple states */ - break; - - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - { - int rc; - int local_offsets[2]; - int local_workspace[1000]; - const pcre_uchar *endasscode = code + GET(code, 1); - - while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1); - - rc = internal_dfa_exec( - md, /* static match data */ - code, /* this subexpression's code */ - ptr, /* where we currently are */ - (int)(ptr - start_subject), /* start offset */ - local_offsets, /* offset vector */ - sizeof(local_offsets)/sizeof(int), /* size of same */ - local_workspace, /* workspace vector */ - sizeof(local_workspace)/sizeof(int), /* size of same */ - rlevel); /* function recursion level */ - - if (rc == PCRE_ERROR_DFA_UITEM) return rc; - if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK)) - { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_COND: - case OP_SCOND: - { - int local_offsets[1000]; - int local_workspace[1000]; - int codelink = GET(code, 1); - int condcode; - - /* Because of the way auto-callout works during compile, a callout item - is inserted between OP_COND and an assertion condition. This does not - happen for the other conditions. */ - - if (code[LINK_SIZE+1] == OP_CALLOUT) - { - rrc = 0; - if (PUBL(callout) != NULL) - { - PUBL(callout_block) cb; - cb.version = 1; /* Version 1 of the callout block */ - cb.callout_number = code[LINK_SIZE+2]; - cb.offset_vector = offsets; -#ifdef COMPILE_PCRE8 - cb.subject = (PCRE_SPTR)start_subject; -#else - cb.subject = (PCRE_SPTR16)start_subject; -#endif - cb.subject_length = (int)(end_subject - start_subject); - cb.start_match = (int)(current_subject - start_subject); - cb.current_position = (int)(ptr - start_subject); - cb.pattern_position = GET(code, LINK_SIZE + 3); - cb.next_item_length = GET(code, 3 + 2*LINK_SIZE); - cb.capture_top = 1; - cb.capture_last = -1; - cb.callout_data = md->callout_data; - cb.mark = NULL; /* No (*MARK) support */ - if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc; /* Abandon */ - } - if (rrc > 0) break; /* Fail this thread */ - code += PRIV(OP_lengths)[OP_CALLOUT]; /* Skip callout data */ - } - - condcode = code[LINK_SIZE+1]; - - /* Back reference conditions are not supported */ - - if (condcode == OP_CREF || condcode == OP_NCREF) - return PCRE_ERROR_DFA_UCOND; - - /* The DEFINE condition is always false */ - - if (condcode == OP_DEF) - { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); } - - /* The only supported version of OP_RREF is for the value RREF_ANY, - which means "test if in any recursion". We can't test for specifically - recursed groups. */ - - else if (condcode == OP_RREF || condcode == OP_NRREF) - { - int value = GET2(code, LINK_SIZE + 2); - if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND; - if (md->recursive != NULL) - { ADD_ACTIVE(state_offset + LINK_SIZE + 2 + IMM2_SIZE, 0); } - else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); } - } - - /* Otherwise, the condition is an assertion */ - - else - { - int rc; - const pcre_uchar *asscode = code + LINK_SIZE + 1; - const pcre_uchar *endasscode = asscode + GET(asscode, 1); - - while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1); - - rc = internal_dfa_exec( - md, /* fixed match data */ - asscode, /* this subexpression's code */ - ptr, /* where we currently are */ - (int)(ptr - start_subject), /* start offset */ - local_offsets, /* offset vector */ - sizeof(local_offsets)/sizeof(int), /* size of same */ - local_workspace, /* workspace vector */ - sizeof(local_workspace)/sizeof(int), /* size of same */ - rlevel); /* function recursion level */ - - if (rc == PCRE_ERROR_DFA_UITEM) return rc; - if ((rc >= 0) == - (condcode == OP_ASSERT || condcode == OP_ASSERTBACK)) - { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); } - else - { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); } - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_RECURSE: - { - dfa_recursion_info *ri; - int local_offsets[1000]; - int local_workspace[1000]; - const pcre_uchar *callpat = start_code + GET(code, 1); - int recno = (callpat == md->start_code)? 0 : - GET2(callpat, 1 + LINK_SIZE); - int rc; - - DPRINTF(("%.*sStarting regex recursion\n", rlevel*2-2, SP)); - - /* Check for repeating a recursion without advancing the subject - pointer. This should catch convoluted mutual recursions. (Some simple - cases are caught at compile time.) */ - - for (ri = md->recursive; ri != NULL; ri = ri->prevrec) - if (recno == ri->group_num && ptr == ri->subject_position) - return PCRE_ERROR_RECURSELOOP; - - /* Remember this recursion and where we started it so as to - catch infinite loops. */ - - new_recursive.group_num = recno; - new_recursive.subject_position = ptr; - new_recursive.prevrec = md->recursive; - md->recursive = &new_recursive; - - rc = internal_dfa_exec( - md, /* fixed match data */ - callpat, /* this subexpression's code */ - ptr, /* where we currently are */ - (int)(ptr - start_subject), /* start offset */ - local_offsets, /* offset vector */ - sizeof(local_offsets)/sizeof(int), /* size of same */ - local_workspace, /* workspace vector */ - sizeof(local_workspace)/sizeof(int), /* size of same */ - rlevel); /* function recursion level */ - - md->recursive = new_recursive.prevrec; /* Done this recursion */ - - DPRINTF(("%.*sReturn from regex recursion: rc=%d\n", rlevel*2-2, SP, - rc)); - - /* Ran out of internal offsets */ - - if (rc == 0) return PCRE_ERROR_DFA_RECURSE; - - /* For each successful matched substring, set up the next state with a - count of characters to skip before trying it. Note that the count is in - characters, not bytes. */ - - if (rc > 0) - { - for (rc = rc*2 - 2; rc >= 0; rc -= 2) - { - int charcount = local_offsets[rc+1] - local_offsets[rc]; -#ifdef SUPPORT_UTF - if (utf) - { - const pcre_uchar *p = start_subject + local_offsets[rc]; - const pcre_uchar *pp = start_subject + local_offsets[rc+1]; - while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--; - } -#endif - if (charcount > 0) - { - ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0, (charcount - 1)); - } - else - { - ADD_ACTIVE(state_offset + LINK_SIZE + 1, 0); - } - } - } - else if (rc != PCRE_ERROR_NOMATCH) return rc; - } - break; - - /*-----------------------------------------------------------------*/ - case OP_BRAPOS: - case OP_SBRAPOS: - case OP_CBRAPOS: - case OP_SCBRAPOS: - case OP_BRAPOSZERO: - { - int charcount, matched_count; - const pcre_uchar *local_ptr = ptr; - BOOL allow_zero; - - if (codevalue == OP_BRAPOSZERO) - { - allow_zero = TRUE; - codevalue = *(++code); /* Codevalue will be one of above BRAs */ - } - else allow_zero = FALSE; - - /* Loop to match the subpattern as many times as possible as if it were - a complete pattern. */ - - for (matched_count = 0;; matched_count++) - { - int local_offsets[2]; - int local_workspace[1000]; - - int rc = internal_dfa_exec( - md, /* fixed match data */ - code, /* this subexpression's code */ - local_ptr, /* where we currently are */ - (int)(ptr - start_subject), /* start offset */ - local_offsets, /* offset vector */ - sizeof(local_offsets)/sizeof(int), /* size of same */ - local_workspace, /* workspace vector */ - sizeof(local_workspace)/sizeof(int), /* size of same */ - rlevel); /* function recursion level */ - - /* Failed to match */ - - if (rc < 0) - { - if (rc != PCRE_ERROR_NOMATCH) return rc; - break; - } - - /* Matched: break the loop if zero characters matched. */ - - charcount = local_offsets[1] - local_offsets[0]; - if (charcount == 0) break; - local_ptr += charcount; /* Advance temporary position ptr */ - } - - /* At this point we have matched the subpattern matched_count - times, and local_ptr is pointing to the character after the end of the - last match. */ - - if (matched_count > 0 || allow_zero) - { - const pcre_uchar *end_subpattern = code; - int next_state_offset; - - do { end_subpattern += GET(end_subpattern, 1); } - while (*end_subpattern == OP_ALT); - next_state_offset = - (int)(end_subpattern - start_code + LINK_SIZE + 1); - - /* Optimization: if there are no more active states, and there - are no new states yet set up, then skip over the subject string - right here, to save looping. Otherwise, set up the new state to swing - into action when the end of the matched substring is reached. */ - - if (i + 1 >= active_count && new_count == 0) - { - ptr = local_ptr; - clen = 0; - ADD_NEW(next_state_offset, 0); - } - else - { - const pcre_uchar *p = ptr; - const pcre_uchar *pp = local_ptr; - charcount = (int)(pp - p); -#ifdef SUPPORT_UTF - if (utf) while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--; -#endif - ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1)); - } - } - } - break; - - /*-----------------------------------------------------------------*/ - case OP_ONCE: - case OP_ONCE_NC: - { - int local_offsets[2]; - int local_workspace[1000]; - - int rc = internal_dfa_exec( - md, /* fixed match data */ - code, /* this subexpression's code */ - ptr, /* where we currently are */ - (int)(ptr - start_subject), /* start offset */ - local_offsets, /* offset vector */ - sizeof(local_offsets)/sizeof(int), /* size of same */ - local_workspace, /* workspace vector */ - sizeof(local_workspace)/sizeof(int), /* size of same */ - rlevel); /* function recursion level */ - - if (rc >= 0) - { - const pcre_uchar *end_subpattern = code; - int charcount = local_offsets[1] - local_offsets[0]; - int next_state_offset, repeat_state_offset; - - do { end_subpattern += GET(end_subpattern, 1); } - while (*end_subpattern == OP_ALT); - next_state_offset = - (int)(end_subpattern - start_code + LINK_SIZE + 1); - - /* If the end of this subpattern is KETRMAX or KETRMIN, we must - arrange for the repeat state also to be added to the relevant list. - Calculate the offset, or set -1 for no repeat. */ - - repeat_state_offset = (*end_subpattern == OP_KETRMAX || - *end_subpattern == OP_KETRMIN)? - (int)(end_subpattern - start_code - GET(end_subpattern, 1)) : -1; - - /* If we have matched an empty string, add the next state at the - current character pointer. This is important so that the duplicate - checking kicks in, which is what breaks infinite loops that match an - empty string. */ - - if (charcount == 0) - { - ADD_ACTIVE(next_state_offset, 0); - } - - /* Optimization: if there are no more active states, and there - are no new states yet set up, then skip over the subject string - right here, to save looping. Otherwise, set up the new state to swing - into action when the end of the matched substring is reached. */ - - else if (i + 1 >= active_count && new_count == 0) - { - ptr += charcount; - clen = 0; - ADD_NEW(next_state_offset, 0); - - /* If we are adding a repeat state at the new character position, - we must fudge things so that it is the only current state. - Otherwise, it might be a duplicate of one we processed before, and - that would cause it to be skipped. */ - - if (repeat_state_offset >= 0) - { - next_active_state = active_states; - active_count = 0; - i = -1; - ADD_ACTIVE(repeat_state_offset, 0); - } - } - else - { -#ifdef SUPPORT_UTF - if (utf) - { - const pcre_uchar *p = start_subject + local_offsets[0]; - const pcre_uchar *pp = start_subject + local_offsets[1]; - while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--; - } -#endif - ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1)); - if (repeat_state_offset >= 0) - { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); } - } - } - else if (rc != PCRE_ERROR_NOMATCH) return rc; - } - break; - - -/* ========================================================================== */ - /* Handle callouts */ - - case OP_CALLOUT: - rrc = 0; - if (PUBL(callout) != NULL) - { - PUBL(callout_block) cb; - cb.version = 1; /* Version 1 of the callout block */ - cb.callout_number = code[1]; - cb.offset_vector = offsets; -#ifdef COMPILE_PCRE8 - cb.subject = (PCRE_SPTR)start_subject; -#else - cb.subject = (PCRE_SPTR16)start_subject; -#endif - cb.subject_length = (int)(end_subject - start_subject); - cb.start_match = (int)(current_subject - start_subject); - cb.current_position = (int)(ptr - start_subject); - cb.pattern_position = GET(code, 2); - cb.next_item_length = GET(code, 2 + LINK_SIZE); - cb.capture_top = 1; - cb.capture_last = -1; - cb.callout_data = md->callout_data; - cb.mark = NULL; /* No (*MARK) support */ - if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc; /* Abandon */ - } - if (rrc == 0) - { ADD_ACTIVE(state_offset + PRIV(OP_lengths)[OP_CALLOUT], 0); } - break; - - -/* ========================================================================== */ - default: /* Unsupported opcode */ - return PCRE_ERROR_DFA_UITEM; - } - - NEXT_ACTIVE_STATE: continue; - - } /* End of loop scanning active states */ - - /* We have finished the processing at the current subject character. If no - new states have been set for the next character, we have found all the - matches that we are going to find. If we are at the top level and partial - matching has been requested, check for appropriate conditions. - - The "forced_ fail" variable counts the number of (*F) encountered for the - character. If it is equal to the original active_count (saved in - workspace[1]) it means that (*F) was found on every active state. In this - case we don't want to give a partial match. - - The "could_continue" variable is true if a state could have continued but - for the fact that the end of the subject was reached. */ - - if (new_count <= 0) - { - if (rlevel == 1 && /* Top level, and */ - could_continue && /* Some could go on, and */ - forced_fail != workspace[1] && /* Not all forced fail & */ - ( /* either... */ - (md->moptions & PCRE_PARTIAL_HARD) != 0 /* Hard partial */ - || /* or... */ - ((md->moptions & PCRE_PARTIAL_SOFT) != 0 && /* Soft partial and */ - match_count < 0) /* no matches */ - ) && /* And... */ - ( - partial_newline || /* Either partial NL */ - ( /* or ... */ - ptr >= end_subject && /* End of subject and */ - ptr > md->start_used_ptr) /* Inspected non-empty string */ - ) - ) - { - if (offsetcount >= 2) - { - offsets[0] = (int)(md->start_used_ptr - start_subject); - offsets[1] = (int)(end_subject - start_subject); - } - match_count = PCRE_ERROR_PARTIAL; - } - - DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n" - "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, match_count, - rlevel*2-2, SP)); - break; /* In effect, "return", but see the comment below */ - } - - /* One or more states are active for the next character. */ - - ptr += clen; /* Advance to next subject character */ - } /* Loop to move along the subject string */ - -/* Control gets here from "break" a few lines above. We do it this way because -if we use "return" above, we have compiler trouble. Some compilers warn if -there's nothing here because they think the function doesn't return a value. On -the other hand, if we put a dummy statement here, some more clever compilers -complain that it can't be reached. Sigh. */ - -return match_count; -} - - - - -/************************************************* -* Execute a Regular Expression - DFA engine * -*************************************************/ - -/* This external function applies a compiled re to a subject string using a DFA -engine. This function calls the internal function multiple times if the pattern -is not anchored. - -Arguments: - argument_re points to the compiled expression - extra_data points to extra data or is NULL - subject points to the subject string - length length of subject string (may contain binary zeros) - start_offset where to start in the subject string - options option bits - offsets vector of match offsets - offsetcount size of same - workspace workspace vector - wscount size of same - -Returns: > 0 => number of match offset pairs placed in offsets - = 0 => offsets overflowed; longest matches are present - -1 => failed to match - < -1 => some kind of unexpected problem -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data, - const char *subject, int length, int start_offset, int options, int *offsets, - int offsetcount, int *workspace, int wscount) -#else -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre16_dfa_exec(const pcre16 *argument_re, const pcre16_extra *extra_data, - PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets, - int offsetcount, int *workspace, int wscount) -#endif -{ -REAL_PCRE *re = (REAL_PCRE *)argument_re; -dfa_match_data match_block; -dfa_match_data *md = &match_block; -BOOL utf, anchored, startline, firstline; -const pcre_uchar *current_subject, *end_subject; -const pcre_study_data *study = NULL; - -const pcre_uchar *req_char_ptr; -const pcre_uint8 *start_bits = NULL; -BOOL has_first_char = FALSE; -BOOL has_req_char = FALSE; -pcre_uchar first_char = 0; -pcre_uchar first_char2 = 0; -pcre_uchar req_char = 0; -pcre_uchar req_char2 = 0; -int newline; - -/* Plausibility checks */ - -if ((options & ~PUBLIC_DFA_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; -if (re == NULL || subject == NULL || workspace == NULL || - (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL; -if (offsetcount < 0) return PCRE_ERROR_BADCOUNT; -if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE; -if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET; - -/* Check that the first field in the block is the magic number. If it is not, -return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to -REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which -means that the pattern is likely compiled with different endianness. */ - -if (re->magic_number != MAGIC_NUMBER) - return re->magic_number == REVERSED_MAGIC_NUMBER? - PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC; -if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; - -/* If restarting after a partial match, do some sanity checks on the contents -of the workspace. */ - -if ((options & PCRE_DFA_RESTART) != 0) - { - if ((workspace[0] & (-2)) != 0 || workspace[1] < 1 || - workspace[1] > (wscount - 2)/INTS_PER_STATEBLOCK) - return PCRE_ERROR_DFA_BADRESTART; - } - -/* Set up study, callout, and table data */ - -md->tables = re->tables; -md->callout_data = NULL; - -if (extra_data != NULL) - { - unsigned int flags = extra_data->flags; - if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) - study = (const pcre_study_data *)extra_data->study_data; - if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) return PCRE_ERROR_DFA_UMLIMIT; - if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0) - return PCRE_ERROR_DFA_UMLIMIT; - if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0) - md->callout_data = extra_data->callout_data; - if ((flags & PCRE_EXTRA_TABLES) != 0) - md->tables = extra_data->tables; - } - -/* Set some local values */ - -current_subject = (const pcre_uchar *)subject + start_offset; -end_subject = (const pcre_uchar *)subject + length; -req_char_ptr = current_subject - 1; - -#ifdef SUPPORT_UTF -/* PCRE_UTF16 has the same value as PCRE_UTF8. */ -utf = (re->options & PCRE_UTF8) != 0; -#else -utf = FALSE; -#endif - -anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 || - (re->options & PCRE_ANCHORED) != 0; - -/* The remaining fixed data for passing around. */ - -md->start_code = (const pcre_uchar *)argument_re + - re->name_table_offset + re->name_count * re->name_entry_size; -md->start_subject = (const pcre_uchar *)subject; -md->end_subject = end_subject; -md->start_offset = start_offset; -md->moptions = options; -md->poptions = re->options; - -/* If the BSR option is not set at match time, copy what was set -at compile time. */ - -if ((md->moptions & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == 0) - { - if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0) - md->moptions |= re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE); -#ifdef BSR_ANYCRLF - else md->moptions |= PCRE_BSR_ANYCRLF; -#endif - } - -/* Handle different types of newline. The three bits give eight cases. If -nothing is set at run time, whatever was used at compile time applies. */ - -switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : (pcre_uint32)options) & - PCRE_NEWLINE_BITS) - { - case 0: newline = NEWLINE; break; /* Compile-time default */ - case PCRE_NEWLINE_CR: newline = CHAR_CR; break; - case PCRE_NEWLINE_LF: newline = CHAR_NL; break; - case PCRE_NEWLINE_CR+ - PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break; - case PCRE_NEWLINE_ANY: newline = -1; break; - case PCRE_NEWLINE_ANYCRLF: newline = -2; break; - default: return PCRE_ERROR_BADNEWLINE; - } - -if (newline == -2) - { - md->nltype = NLTYPE_ANYCRLF; - } -else if (newline < 0) - { - md->nltype = NLTYPE_ANY; - } -else - { - md->nltype = NLTYPE_FIXED; - if (newline > 255) - { - md->nllen = 2; - md->nl[0] = (newline >> 8) & 255; - md->nl[1] = newline & 255; - } - else - { - md->nllen = 1; - md->nl[0] = newline; - } - } - -/* Check a UTF-8 string if required. Unfortunately there's no way of passing -back the character offset. */ - -#ifdef SUPPORT_UTF -if (utf && (options & PCRE_NO_UTF8_CHECK) == 0) - { - int erroroffset; - int errorcode = PRIV(valid_utf)((pcre_uchar *)subject, length, &erroroffset); - if (errorcode != 0) - { - if (offsetcount >= 2) - { - offsets[0] = erroroffset; - offsets[1] = errorcode; - } - return (errorcode <= PCRE_UTF8_ERR5 && (options & PCRE_PARTIAL_HARD) != 0)? - PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8; - } - if (start_offset > 0 && start_offset < length && - NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset])) - return PCRE_ERROR_BADUTF8_OFFSET; - } -#endif - -/* If the exec call supplied NULL for tables, use the inbuilt ones. This -is a feature that makes it possible to save compiled regex and re-use them -in other programs later. */ - -if (md->tables == NULL) md->tables = PRIV(default_tables); - -/* The "must be at the start of a line" flags are used in a loop when finding -where to start. */ - -startline = (re->flags & PCRE_STARTLINE) != 0; -firstline = (re->options & PCRE_FIRSTLINE) != 0; - -/* Set up the first character to match, if available. The first_byte value is -never set for an anchored regular expression, but the anchoring may be forced -at run time, so we have to test for anchoring. The first char may be unset for -an unanchored pattern, of course. If there's no first char and the pattern was -studied, there may be a bitmap of possible first characters. */ - -if (!anchored) - { - if ((re->flags & PCRE_FIRSTSET) != 0) - { - has_first_char = TRUE; - first_char = first_char2 = (pcre_uchar)(re->first_char); - if ((re->flags & PCRE_FCH_CASELESS) != 0) - { - first_char2 = TABLE_GET(first_char, md->tables + fcc_offset, first_char); -#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) - if (utf && first_char > 127) - first_char2 = UCD_OTHERCASE(first_char); -#endif - } - } - else - { - if (!startline && study != NULL && - (study->flags & PCRE_STUDY_MAPPED) != 0) - start_bits = study->start_bits; - } - } - -/* For anchored or unanchored matches, there may be a "last known required -character" set. */ - -if ((re->flags & PCRE_REQCHSET) != 0) - { - has_req_char = TRUE; - req_char = req_char2 = (pcre_uchar)(re->req_char); - if ((re->flags & PCRE_RCH_CASELESS) != 0) - { - req_char2 = TABLE_GET(req_char, md->tables + fcc_offset, req_char); -#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) - if (utf && req_char > 127) - req_char2 = UCD_OTHERCASE(req_char); -#endif - } - } - -/* Call the main matching function, looping for a non-anchored regex after a -failed match. If not restarting, perform certain optimizations at the start of -a match. */ - -for (;;) - { - int rc; - - if ((options & PCRE_DFA_RESTART) == 0) - { - const pcre_uchar *save_end_subject = end_subject; - - /* If firstline is TRUE, the start of the match is constrained to the first - line of a multiline string. Implement this by temporarily adjusting - end_subject so that we stop scanning at a newline. If the match fails at - the newline, later code breaks this loop. */ - - if (firstline) - { - PCRE_PUCHAR t = current_subject; -#ifdef SUPPORT_UTF - if (utf) - { - while (t < md->end_subject && !IS_NEWLINE(t)) - { - t++; - ACROSSCHAR(t < end_subject, *t, t++); - } - } - else -#endif - while (t < md->end_subject && !IS_NEWLINE(t)) t++; - end_subject = t; - } - - /* There are some optimizations that avoid running the match if a known - starting point is not found. However, there is an option that disables - these, for testing and for ensuring that all callouts do actually occur. - The option can be set in the regex by (*NO_START_OPT) or passed in - match-time options. */ - - if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0) - { - /* Advance to a known first char. */ - - if (has_first_char) - { - if (first_char != first_char2) - while (current_subject < end_subject && - *current_subject != first_char && *current_subject != first_char2) - current_subject++; - else - while (current_subject < end_subject && - *current_subject != first_char) - current_subject++; - } - - /* Or to just after a linebreak for a multiline match if possible */ - - else if (startline) - { - if (current_subject > md->start_subject + start_offset) - { -#ifdef SUPPORT_UTF - if (utf) - { - while (current_subject < end_subject && - !WAS_NEWLINE(current_subject)) - { - current_subject++; - ACROSSCHAR(current_subject < end_subject, *current_subject, - current_subject++); - } - } - else -#endif - while (current_subject < end_subject && !WAS_NEWLINE(current_subject)) - current_subject++; - - /* If we have just passed a CR and the newline option is ANY or - ANYCRLF, and we are now at a LF, advance the match position by one - more character. */ - - if (current_subject[-1] == CHAR_CR && - (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) && - current_subject < end_subject && - *current_subject == CHAR_NL) - current_subject++; - } - } - - /* Or to a non-unique first char after study */ - - else if (start_bits != NULL) - { - while (current_subject < end_subject) - { - unsigned int c = *current_subject; -#ifndef COMPILE_PCRE8 - if (c > 255) c = 255; -#endif - if ((start_bits[c/8] & (1 << (c&7))) == 0) - { - current_subject++; -#if defined SUPPORT_UTF && defined COMPILE_PCRE8 - /* In non 8-bit mode, the iteration will stop for - characters > 255 at the beginning or not stop at all. */ - if (utf) - ACROSSCHAR(current_subject < end_subject, *current_subject, - current_subject++); -#endif - } - else break; - } - } - } - - /* Restore fudged end_subject */ - - end_subject = save_end_subject; - - /* The following two optimizations are disabled for partial matching or if - disabling is explicitly requested (and of course, by the test above, this - code is not obeyed when restarting after a partial match). */ - - if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 && - (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0) - { - /* If the pattern was studied, a minimum subject length may be set. This - is a lower bound; no actual string of that length may actually match the - pattern. Although the value is, strictly, in characters, we treat it as - bytes to avoid spending too much time in this optimization. */ - - if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 && - (pcre_uint32)(end_subject - current_subject) < study->minlength) - return PCRE_ERROR_NOMATCH; - - /* If req_char is set, we know that that character must appear in the - subject for the match to succeed. If the first character is set, req_char - must be later in the subject; otherwise the test starts at the match - point. This optimization can save a huge amount of work in patterns with - nested unlimited repeats that aren't going to match. Writing separate - code for cased/caseless versions makes it go faster, as does using an - autoincrement and backing off on a match. - - HOWEVER: when the subject string is very, very long, searching to its end - can take a long time, and give bad performance on quite ordinary - patterns. This showed up when somebody was matching /^C/ on a 32-megabyte - string... so we don't do this when the string is sufficiently long. */ - - if (has_req_char && end_subject - current_subject < REQ_BYTE_MAX) - { - PCRE_PUCHAR p = current_subject + (has_first_char? 1:0); - - /* We don't need to repeat the search if we haven't yet reached the - place we found it at last time. */ - - if (p > req_char_ptr) - { - if (req_char != req_char2) - { - while (p < end_subject) - { - int pp = *p++; - if (pp == req_char || pp == req_char2) { p--; break; } - } - } - else - { - while (p < end_subject) - { - if (*p++ == req_char) { p--; break; } - } - } - - /* If we can't find the required character, break the matching loop, - which will cause a return or PCRE_ERROR_NOMATCH. */ - - if (p >= end_subject) break; - - /* If we have found the required character, save the point where we - found it, so that we don't search again next time round the loop if - the start hasn't passed this character yet. */ - - req_char_ptr = p; - } - } - } - } /* End of optimizations that are done when not restarting */ - - /* OK, now we can do the business */ - - md->start_used_ptr = current_subject; - md->recursive = NULL; - - rc = internal_dfa_exec( - md, /* fixed match data */ - md->start_code, /* this subexpression's code */ - current_subject, /* where we currently are */ - start_offset, /* start offset in subject */ - offsets, /* offset vector */ - offsetcount, /* size of same */ - workspace, /* workspace vector */ - wscount, /* size of same */ - 0); /* function recurse level */ - - /* Anything other than "no match" means we are done, always; otherwise, carry - on only if not anchored. */ - - if (rc != PCRE_ERROR_NOMATCH || anchored) return rc; - - /* Advance to the next subject character unless we are at the end of a line - and firstline is set. */ - - if (firstline && IS_NEWLINE(current_subject)) break; - current_subject++; -#ifdef SUPPORT_UTF - if (utf) - { - ACROSSCHAR(current_subject < end_subject, *current_subject, - current_subject++); - } -#endif - if (current_subject > end_subject) break; - - /* If we have just passed a CR and we are now at a LF, and the pattern does - not contain any explicit matches for \r or \n, and the newline option is CRLF - or ANY or ANYCRLF, advance the match position by one more character. */ - - if (current_subject[-1] == CHAR_CR && - current_subject < end_subject && - *current_subject == CHAR_NL && - (re->flags & PCRE_HASCRORLF) == 0 && - (md->nltype == NLTYPE_ANY || - md->nltype == NLTYPE_ANYCRLF || - md->nllen == 2)) - current_subject++; - - } /* "Bumpalong" loop */ - -return PCRE_ERROR_NOMATCH; -} - -/* End of pcre_dfa_exec.c */ diff --git a/glib/pcre/pcre_exec.c b/glib/pcre/pcre_exec.c deleted file mode 100644 index 4ba3eda01..000000000 --- a/glib/pcre/pcre_exec.c +++ /dev/null @@ -1,7144 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - -/* This module contains pcre_exec(), the externally visible function that does -pattern matching using an NFA algorithm, trying to mimic Perl as closely as -possible. There are also some static supporting functions. */ - -#include "config.h" - -#define NLBLOCK md /* Block containing newline information */ -#define PSSTART start_subject /* Field containing processed string start */ -#define PSEND end_subject /* Field containing processed string end */ - -#include "pcre_internal.h" - -/* Undefine some potentially clashing cpp symbols */ - -#undef min -#undef max - -/* Values for setting in md->match_function_type to indicate two special types -of call to match(). We do it this way to save on using another stack variable, -as stack usage is to be discouraged. */ - -#define MATCH_CONDASSERT 1 /* Called to check a condition assertion */ -#define MATCH_CBEGROUP 2 /* Could-be-empty unlimited repeat group */ - -/* Non-error returns from the match() function. Error returns are externally -defined PCRE_ERROR_xxx codes, which are all negative. */ - -#define MATCH_MATCH 1 -#define MATCH_NOMATCH 0 - -/* Special internal returns from the match() function. Make them sufficiently -negative to avoid the external error codes. */ - -#define MATCH_ACCEPT (-999) -#define MATCH_COMMIT (-998) -#define MATCH_KETRPOS (-997) -#define MATCH_ONCE (-996) -#define MATCH_PRUNE (-995) -#define MATCH_SKIP (-994) -#define MATCH_SKIP_ARG (-993) -#define MATCH_THEN (-992) - -/* Maximum number of ints of offset to save on the stack for recursive calls. -If the offset vector is bigger, malloc is used. This should be a multiple of 3, -because the offset vector is always a multiple of 3 long. */ - -#define REC_STACK_SAVE_MAX 30 - -/* Min and max values for the common repeats; for the maxima, 0 => infinity */ - -static const char rep_min[] = { 0, 0, 1, 1, 0, 0 }; -static const char rep_max[] = { 0, 0, 0, 0, 1, 1 }; - - - -#ifdef PCRE_DEBUG -/************************************************* -* Debugging function to print chars * -*************************************************/ - -/* Print a sequence of chars in printable format, stopping at the end of the -subject if the requested. - -Arguments: - p points to characters - length number to print - is_subject TRUE if printing from within md->start_subject - md pointer to matching data block, if is_subject is TRUE - -Returns: nothing -*/ - -static void -pchars(const pcre_uchar *p, int length, BOOL is_subject, match_data *md) -{ -unsigned int c; -if (is_subject && length > md->end_subject - p) length = md->end_subject - p; -while (length-- > 0) - if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c); -} -#endif - - - -/************************************************* -* Match a back-reference * -*************************************************/ - -/* Normally, if a back reference hasn't been set, the length that is passed is -negative, so the match always fails. However, in JavaScript compatibility mode, -the length passed is zero. Note that in caseless UTF-8 mode, the number of -subject bytes matched may be different to the number of reference bytes. - -Arguments: - offset index into the offset vector - eptr pointer into the subject - length length of reference to be matched (number of bytes) - md points to match data block - caseless TRUE if caseless - -Returns: >= 0 the number of subject bytes matched - -1 no match - -2 partial match; always given if at end subject -*/ - -static int -match_ref(int offset, PCRE_PUCHAR eptr, int length, match_data *md, - BOOL caseless) -{ -PCRE_PUCHAR eptr_start = eptr; -PCRE_PUCHAR p = md->start_subject + md->offset_vector[offset]; - -#ifdef PCRE_DEBUG -if (eptr >= md->end_subject) - printf("matching subject <null>"); -else - { - printf("matching subject "); - pchars(eptr, length, TRUE, md); - } -printf(" against backref "); -pchars(p, length, FALSE, md); -printf("\n"); -#endif - -/* Always fail if reference not set (and not JavaScript compatible - in that -case the length is passed as zero). */ - -if (length < 0) return -1; - -/* Separate the caseless case for speed. In UTF-8 mode we can only do this -properly if Unicode properties are supported. Otherwise, we can check only -ASCII characters. */ - -if (caseless) - { -#ifdef SUPPORT_UTF -#ifdef SUPPORT_UCP - if (md->utf) - { - /* Match characters up to the end of the reference. NOTE: the number of - bytes matched may differ, because there are some characters whose upper and - lower case versions code as different numbers of bytes. For example, U+023A - (2 bytes in UTF-8) is the upper case version of U+2C65 (3 bytes in UTF-8); - a sequence of 3 of the former uses 6 bytes, as does a sequence of two of - the latter. It is important, therefore, to check the length along the - reference, not along the subject (earlier code did this wrong). */ - - PCRE_PUCHAR endptr = p + length; - while (p < endptr) - { - int c, d; - if (eptr >= md->end_subject) return -2; /* Partial match */ - GETCHARINC(c, eptr); - GETCHARINC(d, p); - if (c != d && c != UCD_OTHERCASE(d)) return -1; - } - } - else -#endif -#endif - - /* The same code works when not in UTF-8 mode and in UTF-8 mode when there - is no UCP support. */ - { - while (length-- > 0) - { - if (eptr >= md->end_subject) return -2; /* Partial match */ - if (TABLE_GET(*p, md->lcc, *p) != TABLE_GET(*eptr, md->lcc, *eptr)) return -1; - p++; - eptr++; - } - } - } - -/* In the caseful case, we can just compare the bytes, whether or not we -are in UTF-8 mode. */ - -else - { - while (length-- > 0) - { - if (eptr >= md->end_subject) return -2; /* Partial match */ - if (*p++ != *eptr++) return -1; - } - } - -return (int)(eptr - eptr_start); -} - - - -/*************************************************************************** -**************************************************************************** - RECURSION IN THE match() FUNCTION - -The match() function is highly recursive, though not every recursive call -increases the recursive depth. Nevertheless, some regular expressions can cause -it to recurse to a great depth. I was writing for Unix, so I just let it call -itself recursively. This uses the stack for saving everything that has to be -saved for a recursive call. On Unix, the stack can be large, and this works -fine. - -It turns out that on some non-Unix-like systems there are problems with -programs that use a lot of stack. (This despite the fact that every last chip -has oodles of memory these days, and techniques for extending the stack have -been known for decades.) So.... - -There is a fudge, triggered by defining NO_RECURSE, which avoids recursive -calls by keeping local variables that need to be preserved in blocks of memory -obtained from malloc() instead instead of on the stack. Macros are used to -achieve this so that the actual code doesn't look very different to what it -always used to. - -The original heap-recursive code used longjmp(). However, it seems that this -can be very slow on some operating systems. Following a suggestion from Stan -Switzer, the use of longjmp() has been abolished, at the cost of having to -provide a unique number for each call to RMATCH. There is no way of generating -a sequence of numbers at compile time in C. I have given them names, to make -them stand out more clearly. - -Crude tests on x86 Linux show a small speedup of around 5-8%. However, on -FreeBSD, avoiding longjmp() more than halves the time taken to run the standard -tests. Furthermore, not using longjmp() means that local dynamic variables -don't have indeterminate values; this has meant that the frame size can be -reduced because the result can be "passed back" by straight setting of the -variable instead of being passed in the frame. -**************************************************************************** -***************************************************************************/ - -/* Numbers for RMATCH calls. When this list is changed, the code at HEAP_RETURN -below must be updated in sync. */ - -enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10, - RM11, RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20, - RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30, - RM31, RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40, - RM41, RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50, - RM51, RM52, RM53, RM54, RM55, RM56, RM57, RM58, RM59, RM60, - RM61, RM62, RM63, RM64, RM65, RM66 }; - -/* These versions of the macros use the stack, as normal. There are debugging -versions and production versions. Note that the "rw" argument of RMATCH isn't -actually used in this definition. */ - -#ifndef NO_RECURSE - -#ifdef PCRE_DEBUG -#define RMATCH(ra,rb,rc,rd,re,rw) \ - { \ - printf("match() called in line %d\n", __LINE__); \ - rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1); \ - printf("to line %d\n", __LINE__); \ - } -#define RRETURN(ra) \ - { \ - printf("match() returned %d from line %d ", ra, __LINE__); \ - return ra; \ - } -#else -#define RMATCH(ra,rb,rc,rd,re,rw) \ - rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1) -#define RRETURN(ra) return ra -#endif - -#else - - -/* These versions of the macros manage a private stack on the heap. Note that -the "rd" argument of RMATCH isn't actually used in this definition. It's the md -argument of match(), which never changes. */ - -#define RMATCH(ra,rb,rc,rd,re,rw)\ - {\ - heapframe *newframe = frame->Xnextframe;\ - if (newframe == NULL)\ - {\ - newframe = (heapframe *)(PUBL(stack_malloc))(sizeof(heapframe));\ - if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\ - newframe->Xnextframe = NULL;\ - frame->Xnextframe = newframe;\ - }\ - frame->Xwhere = rw;\ - newframe->Xeptr = ra;\ - newframe->Xecode = rb;\ - newframe->Xmstart = mstart;\ - newframe->Xoffset_top = rc;\ - newframe->Xeptrb = re;\ - newframe->Xrdepth = frame->Xrdepth + 1;\ - newframe->Xprevframe = frame;\ - frame = newframe;\ - DPRINTF(("restarting from line %d\n", __LINE__));\ - goto HEAP_RECURSE;\ - L_##rw:\ - DPRINTF(("jumped back to line %d\n", __LINE__));\ - } - -#define RRETURN(ra)\ - {\ - heapframe *oldframe = frame;\ - frame = oldframe->Xprevframe;\ - if (frame != NULL)\ - {\ - rrc = ra;\ - goto HEAP_RETURN;\ - }\ - return ra;\ - } - - -/* Structure for remembering the local variables in a private frame */ - -typedef struct heapframe { - struct heapframe *Xprevframe; - struct heapframe *Xnextframe; - - /* Function arguments that may change */ - - PCRE_PUCHAR Xeptr; - const pcre_uchar *Xecode; - PCRE_PUCHAR Xmstart; - int Xoffset_top; - eptrblock *Xeptrb; - unsigned int Xrdepth; - - /* Function local variables */ - - PCRE_PUCHAR Xcallpat; -#ifdef SUPPORT_UTF - PCRE_PUCHAR Xcharptr; -#endif - PCRE_PUCHAR Xdata; - PCRE_PUCHAR Xnext; - PCRE_PUCHAR Xpp; - PCRE_PUCHAR Xprev; - PCRE_PUCHAR Xsaved_eptr; - - recursion_info Xnew_recursive; - - BOOL Xcur_is_word; - BOOL Xcondition; - BOOL Xprev_is_word; - -#ifdef SUPPORT_UCP - int Xprop_type; - int Xprop_value; - int Xprop_fail_result; - int Xoclength; - pcre_uchar Xocchars[6]; -#endif - - int Xcodelink; - int Xctype; - unsigned int Xfc; - int Xfi; - int Xlength; - int Xmax; - int Xmin; - int Xnumber; - int Xoffset; - int Xop; - int Xsave_capture_last; - int Xsave_offset1, Xsave_offset2, Xsave_offset3; - int Xstacksave[REC_STACK_SAVE_MAX]; - - eptrblock Xnewptrb; - - /* Where to jump back to */ - - int Xwhere; - -} heapframe; - -#endif - - -/*************************************************************************** -***************************************************************************/ - - - -/************************************************* -* Match from current position * -*************************************************/ - -/* This function is called recursively in many circumstances. Whenever it -returns a negative (error) response, the outer incarnation must also return the -same response. */ - -/* These macros pack up tests that are used for partial matching, and which -appear several times in the code. We set the "hit end" flag if the pointer is -at the end of the subject and also past the start of the subject (i.e. -something has been matched). For hard partial matching, we then return -immediately. The second one is used when we already know we are past the end of -the subject. */ - -#define CHECK_PARTIAL()\ - if (md->partial != 0 && eptr >= md->end_subject && \ - eptr > md->start_used_ptr) \ - { \ - md->hitend = TRUE; \ - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \ - } - -#define SCHECK_PARTIAL()\ - if (md->partial != 0 && eptr > md->start_used_ptr) \ - { \ - md->hitend = TRUE; \ - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \ - } - - -/* Performance note: It might be tempting to extract commonly used fields from -the md structure (e.g. utf, end_subject) into individual variables to improve -performance. Tests using gcc on a SPARC disproved this; in the first case, it -made performance worse. - -Arguments: - eptr pointer to current character in subject - ecode pointer to current position in compiled code - mstart pointer to the current match start position (can be modified - by encountering \K) - offset_top current top pointer - md pointer to "static" info for the match - eptrb pointer to chain of blocks containing eptr at start of - brackets - for testing for empty matches - rdepth the recursion depth - -Returns: MATCH_MATCH if matched ) these values are >= 0 - MATCH_NOMATCH if failed to match ) - a negative MATCH_xxx value for PRUNE, SKIP, etc - a negative PCRE_ERROR_xxx value if aborted by an error condition - (e.g. stopped by repeated call or recursion limit) -*/ - -static int -match(PCRE_PUCHAR eptr, const pcre_uchar *ecode, - PCRE_PUCHAR mstart, int offset_top, match_data *md, eptrblock *eptrb, - unsigned int rdepth) -{ -/* These variables do not need to be preserved over recursion in this function, -so they can be ordinary variables in all cases. Mark some of them with -"register" because they are used a lot in loops. */ - -int rrc; /* Returns from recursive calls */ -int i; /* Used for loops not involving calls to RMATCH() */ -unsigned int c; /* Character values not kept over RMATCH() calls */ -BOOL utf; /* Local copy of UTF flag for speed */ - -BOOL minimize, possessive; /* Quantifier options */ -BOOL caseless; -int condcode; - -/* When recursion is not being used, all "local" variables that have to be -preserved over calls to RMATCH() are part of a "frame". We set up the top-level -frame on the stack here; subsequent instantiations are obtained from the heap -whenever RMATCH() does a "recursion". See the macro definitions above. Putting -the top-level on the stack rather than malloc-ing them all gives a performance -boost in many cases where there is not much "recursion". */ - -#ifdef NO_RECURSE -heapframe *frame = (heapframe *)md->match_frames_base; - -/* Copy in the original argument variables */ - -frame->Xeptr = eptr; -frame->Xecode = ecode; -frame->Xmstart = mstart; -frame->Xoffset_top = offset_top; -frame->Xeptrb = eptrb; -frame->Xrdepth = rdepth; - -/* This is where control jumps back to to effect "recursion" */ - -HEAP_RECURSE: - -/* Macros make the argument variables come from the current frame */ - -#define eptr frame->Xeptr -#define ecode frame->Xecode -#define mstart frame->Xmstart -#define offset_top frame->Xoffset_top -#define eptrb frame->Xeptrb -#define rdepth frame->Xrdepth - -/* Ditto for the local variables */ - -#ifdef SUPPORT_UTF -#define charptr frame->Xcharptr -#endif -#define callpat frame->Xcallpat -#define codelink frame->Xcodelink -#define data frame->Xdata -#define next frame->Xnext -#define pp frame->Xpp -#define prev frame->Xprev -#define saved_eptr frame->Xsaved_eptr - -#define new_recursive frame->Xnew_recursive - -#define cur_is_word frame->Xcur_is_word -#define condition frame->Xcondition -#define prev_is_word frame->Xprev_is_word - -#ifdef SUPPORT_UCP -#define prop_type frame->Xprop_type -#define prop_value frame->Xprop_value -#define prop_fail_result frame->Xprop_fail_result -#define oclength frame->Xoclength -#define occhars frame->Xocchars -#endif - -#define ctype frame->Xctype -#define fc frame->Xfc -#define fi frame->Xfi -#define length frame->Xlength -#define max frame->Xmax -#define min frame->Xmin -#define number frame->Xnumber -#define offset frame->Xoffset -#define op frame->Xop -#define save_capture_last frame->Xsave_capture_last -#define save_offset1 frame->Xsave_offset1 -#define save_offset2 frame->Xsave_offset2 -#define save_offset3 frame->Xsave_offset3 -#define stacksave frame->Xstacksave - -#define newptrb frame->Xnewptrb - -/* When recursion is being used, local variables are allocated on the stack and -get preserved during recursion in the normal way. In this environment, fi and -i, and fc and c, can be the same variables. */ - -#else /* NO_RECURSE not defined */ -#define fi i -#define fc c - -/* Many of the following variables are used only in small blocks of the code. -My normal style of coding would have declared them within each of those blocks. -However, in order to accommodate the version of this code that uses an external -"stack" implemented on the heap, it is easier to declare them all here, so the -declarations can be cut out in a block. The only declarations within blocks -below are for variables that do not have to be preserved over a recursive call -to RMATCH(). */ - -#ifdef SUPPORT_UTF -const pcre_uchar *charptr; -#endif -const pcre_uchar *callpat; -const pcre_uchar *data; -const pcre_uchar *next; -PCRE_PUCHAR pp; -const pcre_uchar *prev; -PCRE_PUCHAR saved_eptr; - -recursion_info new_recursive; - -BOOL cur_is_word; -BOOL condition; -BOOL prev_is_word; - -#ifdef SUPPORT_UCP -int prop_type; -int prop_value; -int prop_fail_result; -int oclength; -pcre_uchar occhars[6]; -#endif - -int codelink; -int ctype; -int length; -int max; -int min; -int number; -int offset; -int op; -int save_capture_last; -int save_offset1, save_offset2, save_offset3; -int stacksave[REC_STACK_SAVE_MAX]; - -eptrblock newptrb; - -/* There is a special fudge for calling match() in a way that causes it to -measure the size of its basic stack frame when the stack is being used for -recursion. The second argument (ecode) being NULL triggers this behaviour. It -cannot normally ever be NULL. The return is the negated value of the frame -size. */ - -if (ecode == NULL) - { - if (rdepth == 0) - return match((PCRE_PUCHAR)&rdepth, NULL, NULL, 0, NULL, NULL, 1); - else - { - int len = (char *)&rdepth - (char *)eptr; - return (len > 0)? -len : len; - } - } -#endif /* NO_RECURSE */ - -/* To save space on the stack and in the heap frame, I have doubled up on some -of the local variables that are used only in localised parts of the code, but -still need to be preserved over recursive calls of match(). These macros define -the alternative names that are used. */ - -#define allow_zero cur_is_word -#define cbegroup condition -#define code_offset codelink -#define condassert condition -#define matched_once prev_is_word -#define foc number -#define save_mark data - -/* These statements are here to stop the compiler complaining about unitialized -variables. */ - -#ifdef SUPPORT_UCP -prop_value = 0; -prop_fail_result = 0; -#endif - - -/* This label is used for tail recursion, which is used in a few cases even -when NO_RECURSE is not defined, in order to reduce the amount of stack that is -used. Thanks to Ian Taylor for noticing this possibility and sending the -original patch. */ - -TAIL_RECURSE: - -/* OK, now we can get on with the real code of the function. Recursive calls -are specified by the macro RMATCH and RRETURN is used to return. When -NO_RECURSE is *not* defined, these just turn into a recursive call to match() -and a "return", respectively (possibly with some debugging if PCRE_DEBUG is -defined). However, RMATCH isn't like a function call because it's quite a -complicated macro. It has to be used in one particular way. This shouldn't, -however, impact performance when true recursion is being used. */ - -#ifdef SUPPORT_UTF -utf = md->utf; /* Local copy of the flag */ -#else -utf = FALSE; -#endif - -/* First check that we haven't called match() too many times, or that we -haven't exceeded the recursive call limit. */ - -if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT); -if (rdepth >= md->match_limit_recursion) RRETURN(PCRE_ERROR_RECURSIONLIMIT); - -/* At the start of a group with an unlimited repeat that may match an empty -string, the variable md->match_function_type is set to MATCH_CBEGROUP. It is -done this way to save having to use another function argument, which would take -up space on the stack. See also MATCH_CONDASSERT below. - -When MATCH_CBEGROUP is set, add the current subject pointer to the chain of -such remembered pointers, to be checked when we hit the closing ket, in order -to break infinite loops that match no characters. When match() is called in -other circumstances, don't add to the chain. The MATCH_CBEGROUP feature must -NOT be used with tail recursion, because the memory block that is used is on -the stack, so a new one may be required for each match(). */ - -if (md->match_function_type == MATCH_CBEGROUP) - { - newptrb.epb_saved_eptr = eptr; - newptrb.epb_prev = eptrb; - eptrb = &newptrb; - md->match_function_type = 0; - } - -/* Now start processing the opcodes. */ - -for (;;) - { - minimize = possessive = FALSE; - op = *ecode; - - switch(op) - { - case OP_MARK: - md->nomatch_mark = ecode + 2; - md->mark = NULL; /* In case previously set by assertion */ - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md, - eptrb, RM55); - if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) && - md->mark == NULL) md->mark = ecode + 2; - - /* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an - argument, and we must check whether that argument matches this MARK's - argument. It is passed back in md->start_match_ptr (an overloading of that - variable). If it does match, we reset that variable to the current subject - position and return MATCH_SKIP. Otherwise, pass back the return code - unaltered. */ - - else if (rrc == MATCH_SKIP_ARG && - STRCMP_UC_UC(ecode + 2, md->start_match_ptr) == 0) - { - md->start_match_ptr = eptr; - RRETURN(MATCH_SKIP); - } - RRETURN(rrc); - - case OP_FAIL: - RRETURN(MATCH_NOMATCH); - - /* COMMIT overrides PRUNE, SKIP, and THEN */ - - case OP_COMMIT: - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, - eptrb, RM52); - if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && - rrc != MATCH_SKIP && rrc != MATCH_SKIP_ARG && - rrc != MATCH_THEN) - RRETURN(rrc); - RRETURN(MATCH_COMMIT); - - /* PRUNE overrides THEN */ - - case OP_PRUNE: - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, - eptrb, RM51); - if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); - RRETURN(MATCH_PRUNE); - - case OP_PRUNE_ARG: - md->nomatch_mark = ecode + 2; - md->mark = NULL; /* In case previously set by assertion */ - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md, - eptrb, RM56); - if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) && - md->mark == NULL) md->mark = ecode + 2; - if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); - RRETURN(MATCH_PRUNE); - - /* SKIP overrides PRUNE and THEN */ - - case OP_SKIP: - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, - eptrb, RM53); - if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN) - RRETURN(rrc); - md->start_match_ptr = eptr; /* Pass back current position */ - RRETURN(MATCH_SKIP); - - /* Note that, for Perl compatibility, SKIP with an argument does NOT set - nomatch_mark. There is a flag that disables this opcode when re-matching a - pattern that ended with a SKIP for which there was not a matching MARK. */ - - case OP_SKIP_ARG: - if (md->ignore_skip_arg) - { - ecode += PRIV(OP_lengths)[*ecode] + ecode[1]; - break; - } - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md, - eptrb, RM57); - if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN) - RRETURN(rrc); - - /* Pass back the current skip name by overloading md->start_match_ptr and - returning the special MATCH_SKIP_ARG return code. This will either be - caught by a matching MARK, or get to the top, where it causes a rematch - with the md->ignore_skip_arg flag set. */ - - md->start_match_ptr = ecode + 2; - RRETURN(MATCH_SKIP_ARG); - - /* For THEN (and THEN_ARG) we pass back the address of the opcode, so that - the branch in which it occurs can be determined. Overload the start of - match pointer to do this. */ - - case OP_THEN: - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, - eptrb, RM54); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - md->start_match_ptr = ecode; - RRETURN(MATCH_THEN); - - case OP_THEN_ARG: - md->nomatch_mark = ecode + 2; - md->mark = NULL; /* In case previously set by assertion */ - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, - md, eptrb, RM58); - if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) && - md->mark == NULL) md->mark = ecode + 2; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - md->start_match_ptr = ecode; - RRETURN(MATCH_THEN); - - /* Handle an atomic group that does not contain any capturing parentheses. - This can be handled like an assertion. Prior to 8.13, all atomic groups - were handled this way. In 8.13, the code was changed as below for ONCE, so - that backups pass through the group and thereby reset captured values. - However, this uses a lot more stack, so in 8.20, atomic groups that do not - contain any captures generate OP_ONCE_NC, which can be handled in the old, - less stack intensive way. - - Check the alternative branches in turn - the matching won't pass the KET - for this kind of subpattern. If any one branch matches, we carry on as at - the end of a normal bracket, leaving the subject pointer, but resetting - the start-of-match value in case it was changed by \K. */ - - case OP_ONCE_NC: - prev = ecode; - saved_eptr = eptr; - save_mark = md->mark; - do - { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM64); - if (rrc == MATCH_MATCH) /* Note: _not_ MATCH_ACCEPT */ - { - mstart = md->start_match_ptr; - break; - } - if (rrc == MATCH_THEN) - { - next = ecode + GET(ecode,1); - if (md->start_match_ptr < next && - (*ecode == OP_ALT || *next == OP_ALT)) - rrc = MATCH_NOMATCH; - } - - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode += GET(ecode,1); - md->mark = save_mark; - } - while (*ecode == OP_ALT); - - /* If hit the end of the group (which could be repeated), fail */ - - if (*ecode != OP_ONCE_NC && *ecode != OP_ALT) RRETURN(MATCH_NOMATCH); - - /* Continue as from after the group, updating the offsets high water - mark, since extracts may have been taken. */ - - do ecode += GET(ecode, 1); while (*ecode == OP_ALT); - - offset_top = md->end_offset_top; - eptr = md->end_match_ptr; - - /* For a non-repeating ket, just continue at this level. This also - happens for a repeating ket if no characters were matched in the group. - This is the forcible breaking of infinite loops as implemented in Perl - 5.005. */ - - if (*ecode == OP_KET || eptr == saved_eptr) - { - ecode += 1+LINK_SIZE; - break; - } - - /* The repeating kets try the rest of the pattern or restart from the - preceding bracket, in the appropriate order. The second "call" of match() - uses tail recursion, to avoid using another stack frame. */ - - if (*ecode == OP_KETRMIN) - { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM65); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode = prev; - goto TAIL_RECURSE; - } - else /* OP_KETRMAX */ - { - RMATCH(eptr, prev, offset_top, md, eptrb, RM66); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode += 1 + LINK_SIZE; - goto TAIL_RECURSE; - } - /* Control never gets here */ - - /* Handle a capturing bracket, other than those that are possessive with an - unlimited repeat. If there is space in the offset vector, save the current - subject position in the working slot at the top of the vector. We mustn't - change the current values of the data slot, because they may be set from a - previous iteration of this group, and be referred to by a reference inside - the group. A failure to match might occur after the group has succeeded, - if something later on doesn't match. For this reason, we need to restore - the working value and also the values of the final offsets, in case they - were set by a previous iteration of the same bracket. - - If there isn't enough space in the offset vector, treat this as if it were - a non-capturing bracket. Don't worry about setting the flag for the error - case here; that is handled in the code for KET. */ - - case OP_CBRA: - case OP_SCBRA: - number = GET2(ecode, 1+LINK_SIZE); - offset = number << 1; - -#ifdef PCRE_DEBUG - printf("start bracket %d\n", number); - printf("subject="); - pchars(eptr, 16, TRUE, md); - printf("\n"); -#endif - - if (offset < md->offset_max) - { - save_offset1 = md->offset_vector[offset]; - save_offset2 = md->offset_vector[offset+1]; - save_offset3 = md->offset_vector[md->offset_end - number]; - save_capture_last = md->capture_last; - save_mark = md->mark; - - DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); - md->offset_vector[md->offset_end - number] = - (int)(eptr - md->start_subject); - - for (;;) - { - if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, - eptrb, RM1); - if (rrc == MATCH_ONCE) break; /* Backing up through an atomic group */ - - /* If we backed up to a THEN, check whether it is within the current - branch by comparing the address of the THEN that is passed back with - the end of the branch. If it is within the current branch, and the - branch is one of two or more alternatives (it either starts or ends - with OP_ALT), we have reached the limit of THEN's action, so convert - the return code to NOMATCH, which will cause normal backtracking to - happen from now on. Otherwise, THEN is passed back to an outer - alternative. This implements Perl's treatment of parenthesized groups, - where a group not containing | does not affect the current alternative, - that is, (X) is NOT the same as (X|(*F)). */ - - if (rrc == MATCH_THEN) - { - next = ecode + GET(ecode,1); - if (md->start_match_ptr < next && - (*ecode == OP_ALT || *next == OP_ALT)) - rrc = MATCH_NOMATCH; - } - - /* Anything other than NOMATCH is passed back. */ - - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - md->capture_last = save_capture_last; - ecode += GET(ecode, 1); - md->mark = save_mark; - if (*ecode != OP_ALT) break; - } - - DPRINTF(("bracket %d failed\n", number)); - md->offset_vector[offset] = save_offset1; - md->offset_vector[offset+1] = save_offset2; - md->offset_vector[md->offset_end - number] = save_offset3; - - /* At this point, rrc will be one of MATCH_ONCE or MATCH_NOMATCH. */ - - RRETURN(rrc); - } - - /* FALL THROUGH ... Insufficient room for saving captured contents. Treat - as a non-capturing bracket. */ - - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ - - DPRINTF(("insufficient capture room: treat as non-capturing\n")); - - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ - - /* Non-capturing or atomic group, except for possessive with unlimited - repeat and ONCE group with no captures. Loop for all the alternatives. - - When we get to the final alternative within the brackets, we used to return - the result of a recursive call to match() whatever happened so it was - possible to reduce stack usage by turning this into a tail recursion, - except in the case of a possibly empty group. However, now that there is - the possiblity of (*THEN) occurring in the final alternative, this - optimization is no longer always possible. - - We can optimize if we know there are no (*THEN)s in the pattern; at present - this is the best that can be done. - - MATCH_ONCE is returned when the end of an atomic group is successfully - reached, but subsequent matching fails. It passes back up the tree (causing - captured values to be reset) until the original atomic group level is - reached. This is tested by comparing md->once_target with the start of the - group. At this point, the return is converted into MATCH_NOMATCH so that - previous backup points can be taken. */ - - case OP_ONCE: - case OP_BRA: - case OP_SBRA: - DPRINTF(("start non-capturing bracket\n")); - - for (;;) - { - if (op >= OP_SBRA || op == OP_ONCE) - md->match_function_type = MATCH_CBEGROUP; - - /* If this is not a possibly empty group, and there are no (*THEN)s in - the pattern, and this is the final alternative, optimize as described - above. */ - - else if (!md->hasthen && ecode[GET(ecode, 1)] != OP_ALT) - { - ecode += PRIV(OP_lengths)[*ecode]; - goto TAIL_RECURSE; - } - - /* In all other cases, we have to make another call to match(). */ - - save_mark = md->mark; - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb, - RM2); - - /* See comment in the code for capturing groups above about handling - THEN. */ - - if (rrc == MATCH_THEN) - { - next = ecode + GET(ecode,1); - if (md->start_match_ptr < next && - (*ecode == OP_ALT || *next == OP_ALT)) - rrc = MATCH_NOMATCH; - } - - if (rrc != MATCH_NOMATCH) - { - if (rrc == MATCH_ONCE) - { - const pcre_uchar *scode = ecode; - if (*scode != OP_ONCE) /* If not at start, find it */ - { - while (*scode == OP_ALT) scode += GET(scode, 1); - scode -= GET(scode, 1); - } - if (md->once_target == scode) rrc = MATCH_NOMATCH; - } - RRETURN(rrc); - } - ecode += GET(ecode, 1); - md->mark = save_mark; - if (*ecode != OP_ALT) break; - } - - RRETURN(MATCH_NOMATCH); - - /* Handle possessive capturing brackets with an unlimited repeat. We come - here from BRAZERO with allow_zero set TRUE. The offset_vector values are - handled similarly to the normal case above. However, the matching is - different. The end of these brackets will always be OP_KETRPOS, which - returns MATCH_KETRPOS without going further in the pattern. By this means - we can handle the group by iteration rather than recursion, thereby - reducing the amount of stack needed. */ - - case OP_CBRAPOS: - case OP_SCBRAPOS: - allow_zero = FALSE; - - POSSESSIVE_CAPTURE: - number = GET2(ecode, 1+LINK_SIZE); - offset = number << 1; - -#ifdef PCRE_DEBUG - printf("start possessive bracket %d\n", number); - printf("subject="); - pchars(eptr, 16, TRUE, md); - printf("\n"); -#endif - - if (offset < md->offset_max) - { - matched_once = FALSE; - code_offset = (int)(ecode - md->start_code); - - save_offset1 = md->offset_vector[offset]; - save_offset2 = md->offset_vector[offset+1]; - save_offset3 = md->offset_vector[md->offset_end - number]; - save_capture_last = md->capture_last; - - DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); - - /* Each time round the loop, save the current subject position for use - when the group matches. For MATCH_MATCH, the group has matched, so we - restart it with a new subject starting position, remembering that we had - at least one match. For MATCH_NOMATCH, carry on with the alternatives, as - usual. If we haven't matched any alternatives in any iteration, check to - see if a previous iteration matched. If so, the group has matched; - continue from afterwards. Otherwise it has failed; restore the previous - capture values before returning NOMATCH. */ - - for (;;) - { - md->offset_vector[md->offset_end - number] = - (int)(eptr - md->start_subject); - if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, - eptrb, RM63); - if (rrc == MATCH_KETRPOS) - { - offset_top = md->end_offset_top; - eptr = md->end_match_ptr; - ecode = md->start_code + code_offset; - save_capture_last = md->capture_last; - matched_once = TRUE; - continue; - } - - /* See comment in the code for capturing groups above about handling - THEN. */ - - if (rrc == MATCH_THEN) - { - next = ecode + GET(ecode,1); - if (md->start_match_ptr < next && - (*ecode == OP_ALT || *next == OP_ALT)) - rrc = MATCH_NOMATCH; - } - - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - md->capture_last = save_capture_last; - ecode += GET(ecode, 1); - if (*ecode != OP_ALT) break; - } - - if (!matched_once) - { - md->offset_vector[offset] = save_offset1; - md->offset_vector[offset+1] = save_offset2; - md->offset_vector[md->offset_end - number] = save_offset3; - } - - if (allow_zero || matched_once) - { - ecode += 1 + LINK_SIZE; - break; - } - - RRETURN(MATCH_NOMATCH); - } - - /* FALL THROUGH ... Insufficient room for saving captured contents. Treat - as a non-capturing bracket. */ - - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ - - DPRINTF(("insufficient capture room: treat as non-capturing\n")); - - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ - /* VVVVVVVVVVVVVVVVVVVVVVVVV */ - - /* Non-capturing possessive bracket with unlimited repeat. We come here - from BRAZERO with allow_zero = TRUE. The code is similar to the above, - without the capturing complication. It is written out separately for speed - and cleanliness. */ - - case OP_BRAPOS: - case OP_SBRAPOS: - allow_zero = FALSE; - - POSSESSIVE_NON_CAPTURE: - matched_once = FALSE; - code_offset = (int)(ecode - md->start_code); - - for (;;) - { - if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; - RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, - eptrb, RM48); - if (rrc == MATCH_KETRPOS) - { - offset_top = md->end_offset_top; - eptr = md->end_match_ptr; - ecode = md->start_code + code_offset; - matched_once = TRUE; - continue; - } - - /* See comment in the code for capturing groups above about handling - THEN. */ - - if (rrc == MATCH_THEN) - { - next = ecode + GET(ecode,1); - if (md->start_match_ptr < next && - (*ecode == OP_ALT || *next == OP_ALT)) - rrc = MATCH_NOMATCH; - } - - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode += GET(ecode, 1); - if (*ecode != OP_ALT) break; - } - - if (matched_once || allow_zero) - { - ecode += 1 + LINK_SIZE; - break; - } - RRETURN(MATCH_NOMATCH); - - /* Control never reaches here. */ - - /* Conditional group: compilation checked that there are no more than - two branches. If the condition is false, skipping the first branch takes us - past the end if there is only one branch, but that's OK because that is - exactly what going to the ket would do. */ - - case OP_COND: - case OP_SCOND: - codelink = GET(ecode, 1); - - /* Because of the way auto-callout works during compile, a callout item is - inserted between OP_COND and an assertion condition. */ - - if (ecode[LINK_SIZE+1] == OP_CALLOUT) - { - if (PUBL(callout) != NULL) - { - PUBL(callout_block) cb; - cb.version = 2; /* Version 1 of the callout block */ - cb.callout_number = ecode[LINK_SIZE+2]; - cb.offset_vector = md->offset_vector; -#ifdef COMPILE_PCRE8 - cb.subject = (PCRE_SPTR)md->start_subject; -#else - cb.subject = (PCRE_SPTR16)md->start_subject; -#endif - cb.subject_length = (int)(md->end_subject - md->start_subject); - cb.start_match = (int)(mstart - md->start_subject); - cb.current_position = (int)(eptr - md->start_subject); - cb.pattern_position = GET(ecode, LINK_SIZE + 3); - cb.next_item_length = GET(ecode, 3 + 2*LINK_SIZE); - cb.capture_top = offset_top/2; - cb.capture_last = md->capture_last; - cb.callout_data = md->callout_data; - cb.mark = md->nomatch_mark; - if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH); - if (rrc < 0) RRETURN(rrc); - } - ecode += PRIV(OP_lengths)[OP_CALLOUT]; - } - - condcode = ecode[LINK_SIZE+1]; - - /* Now see what the actual condition is */ - - if (condcode == OP_RREF || condcode == OP_NRREF) /* Recursion test */ - { - if (md->recursive == NULL) /* Not recursing => FALSE */ - { - condition = FALSE; - ecode += GET(ecode, 1); - } - else - { - int recno = GET2(ecode, LINK_SIZE + 2); /* Recursion group number*/ - condition = (recno == RREF_ANY || recno == md->recursive->group_num); - - /* If the test is for recursion into a specific subpattern, and it is - false, but the test was set up by name, scan the table to see if the - name refers to any other numbers, and test them. The condition is true - if any one is set. */ - - if (!condition && condcode == OP_NRREF) - { - pcre_uchar *slotA = md->name_table; - for (i = 0; i < md->name_count; i++) - { - if (GET2(slotA, 0) == recno) break; - slotA += md->name_entry_size; - } - - /* Found a name for the number - there can be only one; duplicate - names for different numbers are allowed, but not vice versa. First - scan down for duplicates. */ - - if (i < md->name_count) - { - pcre_uchar *slotB = slotA; - while (slotB > md->name_table) - { - slotB -= md->name_entry_size; - if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) - { - condition = GET2(slotB, 0) == md->recursive->group_num; - if (condition) break; - } - else break; - } - - /* Scan up for duplicates */ - - if (!condition) - { - slotB = slotA; - for (i++; i < md->name_count; i++) - { - slotB += md->name_entry_size; - if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) - { - condition = GET2(slotB, 0) == md->recursive->group_num; - if (condition) break; - } - else break; - } - } - } - } - - /* Chose branch according to the condition */ - - ecode += condition? 1 + IMM2_SIZE : GET(ecode, 1); - } - } - - else if (condcode == OP_CREF || condcode == OP_NCREF) /* Group used test */ - { - offset = GET2(ecode, LINK_SIZE+2) << 1; /* Doubled ref number */ - condition = offset < offset_top && md->offset_vector[offset] >= 0; - - /* If the numbered capture is unset, but the reference was by name, - scan the table to see if the name refers to any other numbers, and test - them. The condition is true if any one is set. This is tediously similar - to the code above, but not close enough to try to amalgamate. */ - - if (!condition && condcode == OP_NCREF) - { - int refno = offset >> 1; - pcre_uchar *slotA = md->name_table; - - for (i = 0; i < md->name_count; i++) - { - if (GET2(slotA, 0) == refno) break; - slotA += md->name_entry_size; - } - - /* Found a name for the number - there can be only one; duplicate names - for different numbers are allowed, but not vice versa. First scan down - for duplicates. */ - - if (i < md->name_count) - { - pcre_uchar *slotB = slotA; - while (slotB > md->name_table) - { - slotB -= md->name_entry_size; - if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) - { - offset = GET2(slotB, 0) << 1; - condition = offset < offset_top && - md->offset_vector[offset] >= 0; - if (condition) break; - } - else break; - } - - /* Scan up for duplicates */ - - if (!condition) - { - slotB = slotA; - for (i++; i < md->name_count; i++) - { - slotB += md->name_entry_size; - if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) - { - offset = GET2(slotB, 0) << 1; - condition = offset < offset_top && - md->offset_vector[offset] >= 0; - if (condition) break; - } - else break; - } - } - } - } - - /* Chose branch according to the condition */ - - ecode += condition? 1 + IMM2_SIZE : GET(ecode, 1); - } - - else if (condcode == OP_DEF) /* DEFINE - always false */ - { - condition = FALSE; - ecode += GET(ecode, 1); - } - - /* The condition is an assertion. Call match() to evaluate it - setting - md->match_function_type to MATCH_CONDASSERT causes it to stop at the end of - an assertion. */ - - else - { - md->match_function_type = MATCH_CONDASSERT; - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM3); - if (rrc == MATCH_MATCH) - { - if (md->end_offset_top > offset_top) - offset_top = md->end_offset_top; /* Captures may have happened */ - condition = TRUE; - ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE + 2); - while (*ecode == OP_ALT) ecode += GET(ecode, 1); - } - - /* PCRE doesn't allow the effect of (*THEN) to escape beyond an - assertion; it is therefore treated as NOMATCH. */ - - else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) - { - RRETURN(rrc); /* Need braces because of following else */ - } - else - { - condition = FALSE; - ecode += codelink; - } - } - - /* We are now at the branch that is to be obeyed. As there is only one, can - use tail recursion to avoid using another stack frame, except when there is - unlimited repeat of a possibly empty group. In the latter case, a recursive - call to match() is always required, unless the second alternative doesn't - exist, in which case we can just plough on. Note that, for compatibility - with Perl, the | in a conditional group is NOT treated as creating two - alternatives. If a THEN is encountered in the branch, it propagates out to - the enclosing alternative (unless nested in a deeper set of alternatives, - of course). */ - - if (condition || *ecode == OP_ALT) - { - if (op != OP_SCOND) - { - ecode += 1 + LINK_SIZE; - goto TAIL_RECURSE; - } - - md->match_function_type = MATCH_CBEGROUP; - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM49); - RRETURN(rrc); - } - - /* Condition false & no alternative; continue after the group. */ - - else - { - ecode += 1 + LINK_SIZE; - } - break; - - - /* Before OP_ACCEPT there may be any number of OP_CLOSE opcodes, - to close any currently open capturing brackets. */ - - case OP_CLOSE: - number = GET2(ecode, 1); - offset = number << 1; - -#ifdef PCRE_DEBUG - printf("end bracket %d at *ACCEPT", number); - printf("\n"); -#endif - - md->capture_last = number; - if (offset >= md->offset_max) md->offset_overflow = TRUE; else - { - md->offset_vector[offset] = - md->offset_vector[md->offset_end - number]; - md->offset_vector[offset+1] = (int)(eptr - md->start_subject); - if (offset_top <= offset) offset_top = offset + 2; - } - ecode += 1 + IMM2_SIZE; - break; - - - /* End of the pattern, either real or forced. */ - - case OP_END: - case OP_ACCEPT: - case OP_ASSERT_ACCEPT: - - /* If we have matched an empty string, fail if not in an assertion and not - in a recursion if either PCRE_NOTEMPTY is set, or if PCRE_NOTEMPTY_ATSTART - is set and we have matched at the start of the subject. In both cases, - backtracking will then try other alternatives, if any. */ - - if (eptr == mstart && op != OP_ASSERT_ACCEPT && - md->recursive == NULL && - (md->notempty || - (md->notempty_atstart && - mstart == md->start_subject + md->start_offset))) - RRETURN(MATCH_NOMATCH); - - /* Otherwise, we have a match. */ - - md->end_match_ptr = eptr; /* Record where we ended */ - md->end_offset_top = offset_top; /* and how many extracts were taken */ - md->start_match_ptr = mstart; /* and the start (\K can modify) */ - - /* For some reason, the macros don't work properly if an expression is - given as the argument to RRETURN when the heap is in use. */ - - rrc = (op == OP_END)? MATCH_MATCH : MATCH_ACCEPT; - RRETURN(rrc); - - /* Assertion brackets. Check the alternative branches in turn - the - matching won't pass the KET for an assertion. If any one branch matches, - the assertion is true. Lookbehind assertions have an OP_REVERSE item at the - start of each branch to move the current point backwards, so the code at - this level is identical to the lookahead case. When the assertion is part - of a condition, we want to return immediately afterwards. The caller of - this incarnation of the match() function will have set MATCH_CONDASSERT in - md->match_function type, and one of these opcodes will be the first opcode - that is processed. We use a local variable that is preserved over calls to - match() to remember this case. */ - - case OP_ASSERT: - case OP_ASSERTBACK: - save_mark = md->mark; - if (md->match_function_type == MATCH_CONDASSERT) - { - condassert = TRUE; - md->match_function_type = 0; - } - else condassert = FALSE; - - do - { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM4); - if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) - { - mstart = md->start_match_ptr; /* In case \K reset it */ - break; - } - md->mark = save_mark; - - /* A COMMIT failure must fail the entire assertion, without trying any - subsequent branches. */ - - if (rrc == MATCH_COMMIT) RRETURN(MATCH_NOMATCH); - - /* PCRE does not allow THEN to escape beyond an assertion; it - is treated as NOMATCH. */ - - if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); - ecode += GET(ecode, 1); - } - while (*ecode == OP_ALT); - - if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH); - - /* If checking an assertion for a condition, return MATCH_MATCH. */ - - if (condassert) RRETURN(MATCH_MATCH); - - /* Continue from after the assertion, updating the offsets high water - mark, since extracts may have been taken during the assertion. */ - - do ecode += GET(ecode,1); while (*ecode == OP_ALT); - ecode += 1 + LINK_SIZE; - offset_top = md->end_offset_top; - continue; - - /* Negative assertion: all branches must fail to match. Encountering SKIP, - PRUNE, or COMMIT means we must assume failure without checking subsequent - branches. */ - - case OP_ASSERT_NOT: - case OP_ASSERTBACK_NOT: - save_mark = md->mark; - if (md->match_function_type == MATCH_CONDASSERT) - { - condassert = TRUE; - md->match_function_type = 0; - } - else condassert = FALSE; - - do - { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM5); - md->mark = save_mark; - if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) RRETURN(MATCH_NOMATCH); - if (rrc == MATCH_SKIP || rrc == MATCH_PRUNE || rrc == MATCH_COMMIT) - { - do ecode += GET(ecode,1); while (*ecode == OP_ALT); - break; - } - - /* PCRE does not allow THEN to escape beyond an assertion; it is treated - as NOMATCH. */ - - if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); - ecode += GET(ecode,1); - } - while (*ecode == OP_ALT); - - if (condassert) RRETURN(MATCH_MATCH); /* Condition assertion */ - - ecode += 1 + LINK_SIZE; - continue; - - /* Move the subject pointer back. This occurs only at the start of - each branch of a lookbehind assertion. If we are too close to the start to - move back, this match function fails. When working with UTF-8 we move - back a number of characters, not bytes. */ - - case OP_REVERSE: -#ifdef SUPPORT_UTF - if (utf) - { - i = GET(ecode, 1); - while (i-- > 0) - { - eptr--; - if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); - BACKCHAR(eptr); - } - } - else -#endif - - /* No UTF-8 support, or not in UTF-8 mode: count is byte count */ - - { - eptr -= GET(ecode, 1); - if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); - } - - /* Save the earliest consulted character, then skip to next op code */ - - if (eptr < md->start_used_ptr) md->start_used_ptr = eptr; - ecode += 1 + LINK_SIZE; - break; - - /* The callout item calls an external function, if one is provided, passing - details of the match so far. This is mainly for debugging, though the - function is able to force a failure. */ - - case OP_CALLOUT: - if (PUBL(callout) != NULL) - { - PUBL(callout_block) cb; - cb.version = 2; /* Version 1 of the callout block */ - cb.callout_number = ecode[1]; - cb.offset_vector = md->offset_vector; -#ifdef COMPILE_PCRE8 - cb.subject = (PCRE_SPTR)md->start_subject; -#else - cb.subject = (PCRE_SPTR16)md->start_subject; -#endif - cb.subject_length = (int)(md->end_subject - md->start_subject); - cb.start_match = (int)(mstart - md->start_subject); - cb.current_position = (int)(eptr - md->start_subject); - cb.pattern_position = GET(ecode, 2); - cb.next_item_length = GET(ecode, 2 + LINK_SIZE); - cb.capture_top = offset_top/2; - cb.capture_last = md->capture_last; - cb.callout_data = md->callout_data; - cb.mark = md->nomatch_mark; - if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH); - if (rrc < 0) RRETURN(rrc); - } - ecode += 2 + 2*LINK_SIZE; - break; - - /* Recursion either matches the current regex, or some subexpression. The - offset data is the offset to the starting bracket from the start of the - whole pattern. (This is so that it works from duplicated subpatterns.) - - The state of the capturing groups is preserved over recursion, and - re-instated afterwards. We don't know how many are started and not yet - finished (offset_top records the completed total) so we just have to save - all the potential data. There may be up to 65535 such values, which is too - large to put on the stack, but using malloc for small numbers seems - expensive. As a compromise, the stack is used when there are no more than - REC_STACK_SAVE_MAX values to store; otherwise malloc is used. - - There are also other values that have to be saved. We use a chained - sequence of blocks that actually live on the stack. Thanks to Robin Houston - for the original version of this logic. It has, however, been hacked around - a lot, so he is not to blame for the current way it works. */ - - case OP_RECURSE: - { - recursion_info *ri; - int recno; - - callpat = md->start_code + GET(ecode, 1); - recno = (callpat == md->start_code)? 0 : - GET2(callpat, 1 + LINK_SIZE); - - /* Check for repeating a recursion without advancing the subject pointer. - This should catch convoluted mutual recursions. (Some simple cases are - caught at compile time.) */ - - for (ri = md->recursive; ri != NULL; ri = ri->prevrec) - if (recno == ri->group_num && eptr == ri->subject_position) - RRETURN(PCRE_ERROR_RECURSELOOP); - - /* Add to "recursing stack" */ - - new_recursive.group_num = recno; - new_recursive.subject_position = eptr; - new_recursive.prevrec = md->recursive; - md->recursive = &new_recursive; - - /* Where to continue from afterwards */ - - ecode += 1 + LINK_SIZE; - - /* Now save the offset data */ - - new_recursive.saved_max = md->offset_end; - if (new_recursive.saved_max <= REC_STACK_SAVE_MAX) - new_recursive.offset_save = stacksave; - else - { - new_recursive.offset_save = - (int *)(PUBL(malloc))(new_recursive.saved_max * sizeof(int)); - if (new_recursive.offset_save == NULL) RRETURN(PCRE_ERROR_NOMEMORY); - } - memcpy(new_recursive.offset_save, md->offset_vector, - new_recursive.saved_max * sizeof(int)); - - /* OK, now we can do the recursion. After processing each alternative, - restore the offset data. If there were nested recursions, md->recursive - might be changed, so reset it before looping. */ - - DPRINTF(("Recursing into group %d\n", new_recursive.group_num)); - cbegroup = (*callpat >= OP_SBRA); - do - { - if (cbegroup) md->match_function_type = MATCH_CBEGROUP; - RMATCH(eptr, callpat + PRIV(OP_lengths)[*callpat], offset_top, - md, eptrb, RM6); - memcpy(md->offset_vector, new_recursive.offset_save, - new_recursive.saved_max * sizeof(int)); - md->recursive = new_recursive.prevrec; - if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) - { - DPRINTF(("Recursion matched\n")); - if (new_recursive.offset_save != stacksave) - (PUBL(free))(new_recursive.offset_save); - - /* Set where we got to in the subject, and reset the start in case - it was changed by \K. This *is* propagated back out of a recursion, - for Perl compatibility. */ - - eptr = md->end_match_ptr; - mstart = md->start_match_ptr; - goto RECURSION_MATCHED; /* Exit loop; end processing */ - } - - /* PCRE does not allow THEN or COMMIT to escape beyond a recursion; it - is treated as NOMATCH. */ - - else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN && - rrc != MATCH_COMMIT) - { - DPRINTF(("Recursion gave error %d\n", rrc)); - if (new_recursive.offset_save != stacksave) - (PUBL(free))(new_recursive.offset_save); - RRETURN(rrc); - } - - md->recursive = &new_recursive; - callpat += GET(callpat, 1); - } - while (*callpat == OP_ALT); - - DPRINTF(("Recursion didn't match\n")); - md->recursive = new_recursive.prevrec; - if (new_recursive.offset_save != stacksave) - (PUBL(free))(new_recursive.offset_save); - RRETURN(MATCH_NOMATCH); - } - - RECURSION_MATCHED: - break; - - /* An alternation is the end of a branch; scan along to find the end of the - bracketed group and go to there. */ - - case OP_ALT: - do ecode += GET(ecode,1); while (*ecode == OP_ALT); - break; - - /* BRAZERO, BRAMINZERO and SKIPZERO occur just before a bracket group, - indicating that it may occur zero times. It may repeat infinitely, or not - at all - i.e. it could be ()* or ()? or even (){0} in the pattern. Brackets - with fixed upper repeat limits are compiled as a number of copies, with the - optional ones preceded by BRAZERO or BRAMINZERO. */ - - case OP_BRAZERO: - next = ecode + 1; - RMATCH(eptr, next, offset_top, md, eptrb, RM10); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - do next += GET(next, 1); while (*next == OP_ALT); - ecode = next + 1 + LINK_SIZE; - break; - - case OP_BRAMINZERO: - next = ecode + 1; - do next += GET(next, 1); while (*next == OP_ALT); - RMATCH(eptr, next + 1+LINK_SIZE, offset_top, md, eptrb, RM11); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - ecode++; - break; - - case OP_SKIPZERO: - next = ecode+1; - do next += GET(next,1); while (*next == OP_ALT); - ecode = next + 1 + LINK_SIZE; - break; - - /* BRAPOSZERO occurs before a possessive bracket group. Don't do anything - here; just jump to the group, with allow_zero set TRUE. */ - - case OP_BRAPOSZERO: - op = *(++ecode); - allow_zero = TRUE; - if (op == OP_CBRAPOS || op == OP_SCBRAPOS) goto POSSESSIVE_CAPTURE; - goto POSSESSIVE_NON_CAPTURE; - - /* End of a group, repeated or non-repeating. */ - - case OP_KET: - case OP_KETRMIN: - case OP_KETRMAX: - case OP_KETRPOS: - prev = ecode - GET(ecode, 1); - - /* If this was a group that remembered the subject start, in order to break - infinite repeats of empty string matches, retrieve the subject start from - the chain. Otherwise, set it NULL. */ - - if (*prev >= OP_SBRA || *prev == OP_ONCE) - { - saved_eptr = eptrb->epb_saved_eptr; /* Value at start of group */ - eptrb = eptrb->epb_prev; /* Backup to previous group */ - } - else saved_eptr = NULL; - - /* If we are at the end of an assertion group or a non-capturing atomic - group, stop matching and return MATCH_MATCH, but record the current high - water mark for use by positive assertions. We also need to record the match - start in case it was changed by \K. */ - - if ((*prev >= OP_ASSERT && *prev <= OP_ASSERTBACK_NOT) || - *prev == OP_ONCE_NC) - { - md->end_match_ptr = eptr; /* For ONCE_NC */ - md->end_offset_top = offset_top; - md->start_match_ptr = mstart; - RRETURN(MATCH_MATCH); /* Sets md->mark */ - } - - /* For capturing groups we have to check the group number back at the start - and if necessary complete handling an extraction by setting the offsets and - bumping the high water mark. Whole-pattern recursion is coded as a recurse - into group 0, so it won't be picked up here. Instead, we catch it when the - OP_END is reached. Other recursion is handled here. We just have to record - the current subject position and start match pointer and give a MATCH - return. */ - - if (*prev == OP_CBRA || *prev == OP_SCBRA || - *prev == OP_CBRAPOS || *prev == OP_SCBRAPOS) - { - number = GET2(prev, 1+LINK_SIZE); - offset = number << 1; - -#ifdef PCRE_DEBUG - printf("end bracket %d", number); - printf("\n"); -#endif - - /* Handle a recursively called group. */ - - if (md->recursive != NULL && md->recursive->group_num == number) - { - md->end_match_ptr = eptr; - md->start_match_ptr = mstart; - RRETURN(MATCH_MATCH); - } - - /* Deal with capturing */ - - md->capture_last = number; - if (offset >= md->offset_max) md->offset_overflow = TRUE; else - { - /* If offset is greater than offset_top, it means that we are - "skipping" a capturing group, and that group's offsets must be marked - unset. In earlier versions of PCRE, all the offsets were unset at the - start of matching, but this doesn't work because atomic groups and - assertions can cause a value to be set that should later be unset. - Example: matching /(?>(a))b|(a)c/ against "ac". This sets group 1 as - part of the atomic group, but this is not on the final matching path, - so must be unset when 2 is set. (If there is no group 2, there is no - problem, because offset_top will then be 2, indicating no capture.) */ - - if (offset > offset_top) - { - int *iptr = md->offset_vector + offset_top; - int *iend = md->offset_vector + offset; - while (iptr < iend) *iptr++ = -1; - } - - /* Now make the extraction */ - - md->offset_vector[offset] = - md->offset_vector[md->offset_end - number]; - md->offset_vector[offset+1] = (int)(eptr - md->start_subject); - if (offset_top <= offset) offset_top = offset + 2; - } - } - - /* For an ordinary non-repeating ket, just continue at this level. This - also happens for a repeating ket if no characters were matched in the - group. This is the forcible breaking of infinite loops as implemented in - Perl 5.005. For a non-repeating atomic group that includes captures, - establish a backup point by processing the rest of the pattern at a lower - level. If this results in a NOMATCH return, pass MATCH_ONCE back to the - original OP_ONCE level, thereby bypassing intermediate backup points, but - resetting any captures that happened along the way. */ - - if (*ecode == OP_KET || eptr == saved_eptr) - { - if (*prev == OP_ONCE) - { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM12); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - md->once_target = prev; /* Level at which to change to MATCH_NOMATCH */ - RRETURN(MATCH_ONCE); - } - ecode += 1 + LINK_SIZE; /* Carry on at this level */ - break; - } - - /* OP_KETRPOS is a possessive repeating ket. Remember the current position, - and return the MATCH_KETRPOS. This makes it possible to do the repeats one - at a time from the outer level, thus saving stack. */ - - if (*ecode == OP_KETRPOS) - { - md->end_match_ptr = eptr; - md->end_offset_top = offset_top; - RRETURN(MATCH_KETRPOS); - } - - /* The normal repeating kets try the rest of the pattern or restart from - the preceding bracket, in the appropriate order. In the second case, we can - use tail recursion to avoid using another stack frame, unless we have an - an atomic group or an unlimited repeat of a group that can match an empty - string. */ - - if (*ecode == OP_KETRMIN) - { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM7); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (*prev == OP_ONCE) - { - RMATCH(eptr, prev, offset_top, md, eptrb, RM8); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - md->once_target = prev; /* Level at which to change to MATCH_NOMATCH */ - RRETURN(MATCH_ONCE); - } - if (*prev >= OP_SBRA) /* Could match an empty string */ - { - RMATCH(eptr, prev, offset_top, md, eptrb, RM50); - RRETURN(rrc); - } - ecode = prev; - goto TAIL_RECURSE; - } - else /* OP_KETRMAX */ - { - RMATCH(eptr, prev, offset_top, md, eptrb, RM13); - if (rrc == MATCH_ONCE && md->once_target == prev) rrc = MATCH_NOMATCH; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (*prev == OP_ONCE) - { - RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM9); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - md->once_target = prev; - RRETURN(MATCH_ONCE); - } - ecode += 1 + LINK_SIZE; - goto TAIL_RECURSE; - } - /* Control never gets here */ - - /* Not multiline mode: start of subject assertion, unless notbol. */ - - case OP_CIRC: - if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH); - - /* Start of subject assertion */ - - case OP_SOD: - if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH); - ecode++; - break; - - /* Multiline mode: start of subject unless notbol, or after any newline. */ - - case OP_CIRCM: - if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH); - if (eptr != md->start_subject && - (eptr == md->end_subject || !WAS_NEWLINE(eptr))) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - /* Start of match assertion */ - - case OP_SOM: - if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH); - ecode++; - break; - - /* Reset the start of match point */ - - case OP_SET_SOM: - mstart = eptr; - ecode++; - break; - - /* Multiline mode: assert before any newline, or before end of subject - unless noteol is set. */ - - case OP_DOLLM: - if (eptr < md->end_subject) - { - if (!IS_NEWLINE(eptr)) - { - if (md->partial != 0 && - eptr + 1 >= md->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - *eptr == NLBLOCK->nl[0]) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - RRETURN(MATCH_NOMATCH); - } - } - else - { - if (md->noteol) RRETURN(MATCH_NOMATCH); - SCHECK_PARTIAL(); - } - ecode++; - break; - - /* Not multiline mode: assert before a terminating newline or before end of - subject unless noteol is set. */ - - case OP_DOLL: - if (md->noteol) RRETURN(MATCH_NOMATCH); - if (!md->endonly) goto ASSERT_NL_OR_EOS; - - /* ... else fall through for endonly */ - - /* End of subject assertion (\z) */ - - case OP_EOD: - if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH); - SCHECK_PARTIAL(); - ecode++; - break; - - /* End of subject or ending \n assertion (\Z) */ - - case OP_EODN: - ASSERT_NL_OR_EOS: - if (eptr < md->end_subject && - (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen)) - { - if (md->partial != 0 && - eptr + 1 >= md->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - *eptr == NLBLOCK->nl[0]) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - RRETURN(MATCH_NOMATCH); - } - - /* Either at end of string or \n before end. */ - - SCHECK_PARTIAL(); - ecode++; - break; - - /* Word boundary assertions */ - - case OP_NOT_WORD_BOUNDARY: - case OP_WORD_BOUNDARY: - { - - /* Find out if the previous and current characters are "word" characters. - It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to - be "non-word" characters. Remember the earliest consulted character for - partial matching. */ - -#ifdef SUPPORT_UTF - if (utf) - { - /* Get status of previous character */ - - if (eptr == md->start_subject) prev_is_word = FALSE; else - { - PCRE_PUCHAR lastptr = eptr - 1; - BACKCHAR(lastptr); - if (lastptr < md->start_used_ptr) md->start_used_ptr = lastptr; - GETCHAR(c, lastptr); -#ifdef SUPPORT_UCP - if (md->use_ucp) - { - if (c == '_') prev_is_word = TRUE; else - { - int cat = UCD_CATEGORY(c); - prev_is_word = (cat == ucp_L || cat == ucp_N); - } - } - else -#endif - prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; - } - - /* Get status of next character */ - - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - cur_is_word = FALSE; - } - else - { - GETCHAR(c, eptr); -#ifdef SUPPORT_UCP - if (md->use_ucp) - { - if (c == '_') cur_is_word = TRUE; else - { - int cat = UCD_CATEGORY(c); - cur_is_word = (cat == ucp_L || cat == ucp_N); - } - } - else -#endif - cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; - } - } - else -#endif - - /* Not in UTF-8 mode, but we may still have PCRE_UCP set, and for - consistency with the behaviour of \w we do use it in this case. */ - - { - /* Get status of previous character */ - - if (eptr == md->start_subject) prev_is_word = FALSE; else - { - if (eptr <= md->start_used_ptr) md->start_used_ptr = eptr - 1; -#ifdef SUPPORT_UCP - if (md->use_ucp) - { - c = eptr[-1]; - if (c == '_') prev_is_word = TRUE; else - { - int cat = UCD_CATEGORY(c); - prev_is_word = (cat == ucp_L || cat == ucp_N); - } - } - else -#endif - prev_is_word = MAX_255(eptr[-1]) - && ((md->ctypes[eptr[-1]] & ctype_word) != 0); - } - - /* Get status of next character */ - - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - cur_is_word = FALSE; - } - else -#ifdef SUPPORT_UCP - if (md->use_ucp) - { - c = *eptr; - if (c == '_') cur_is_word = TRUE; else - { - int cat = UCD_CATEGORY(c); - cur_is_word = (cat == ucp_L || cat == ucp_N); - } - } - else -#endif - cur_is_word = MAX_255(*eptr) - && ((md->ctypes[*eptr] & ctype_word) != 0); - } - - /* Now see if the situation is what we want */ - - if ((*ecode++ == OP_WORD_BOUNDARY)? - cur_is_word == prev_is_word : cur_is_word != prev_is_word) - RRETURN(MATCH_NOMATCH); - } - break; - - /* Match any single character type except newline; have to take care with - CRLF newlines and partial matching. */ - - case OP_ANY: - if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); - if (md->partial != 0 && - eptr + 1 >= md->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - *eptr == NLBLOCK->nl[0]) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - - /* Fall through */ - - /* Match any single character whatsoever. */ - - case OP_ALLANY: - if (eptr >= md->end_subject) /* DO NOT merge the eptr++ here; it must */ - { /* not be updated before SCHECK_PARTIAL. */ - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - eptr++; -#ifdef SUPPORT_UTF - if (utf) ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); -#endif - ecode++; - break; - - /* Match a single byte, even in UTF-8 mode. This opcode really does match - any byte, even newline, independent of the setting of PCRE_DOTALL. */ - - case OP_ANYBYTE: - if (eptr >= md->end_subject) /* DO NOT merge the eptr++ here; it must */ - { /* not be updated before SCHECK_PARTIAL. */ - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - eptr++; - ecode++; - break; - - case OP_NOT_DIGIT: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ( -#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) - c < 256 && -#endif - (md->ctypes[c] & ctype_digit) != 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_DIGIT: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ( -#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) - c > 255 || -#endif - (md->ctypes[c] & ctype_digit) == 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_NOT_WHITESPACE: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ( -#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) - c < 256 && -#endif - (md->ctypes[c] & ctype_space) != 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_WHITESPACE: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ( -#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) - c > 255 || -#endif - (md->ctypes[c] & ctype_space) == 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_NOT_WORDCHAR: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ( -#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) - c < 256 && -#endif - (md->ctypes[c] & ctype_word) != 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_WORDCHAR: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ( -#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) - c > 255 || -#endif - (md->ctypes[c] & ctype_word) == 0 - ) - RRETURN(MATCH_NOMATCH); - ecode++; - break; - - case OP_ANYNL: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - - case 0x000d: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - } - else if (*eptr == 0x0a) eptr++; - break; - - case 0x000a: - break; - - case 0x000b: - case 0x000c: - case 0x0085: - case 0x2028: - case 0x2029: - if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); - break; - } - ecode++; - break; - - case OP_NOT_HSPACE: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - switch(c) - { - default: break; - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - RRETURN(MATCH_NOMATCH); - } - ecode++; - break; - - case OP_HSPACE: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - break; - } - ecode++; - break; - - case OP_NOT_VSPACE: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - switch(c) - { - default: break; - case 0x0a: /* LF */ - case 0x0b: /* VT */ - case 0x0c: /* FF */ - case 0x0d: /* CR */ - case 0x85: /* NEL */ - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ - RRETURN(MATCH_NOMATCH); - } - ecode++; - break; - - case OP_VSPACE: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - case 0x0a: /* LF */ - case 0x0b: /* VT */ - case 0x0c: /* FF */ - case 0x0d: /* CR */ - case 0x85: /* NEL */ - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ - break; - } - ecode++; - break; - -#ifdef SUPPORT_UCP - /* Check the next character by Unicode property. We will get here only - if the support is in the binary; otherwise a compile-time error occurs. */ - - case OP_PROP: - case OP_NOTPROP: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - { - const pcre_uint8 chartype = UCD_CHARTYPE(c); - - switch(ecode[1]) - { - case PT_ANY: - if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH); - break; - - case PT_LAMP: - if ((chartype == ucp_Lu || - chartype == ucp_Ll || - chartype == ucp_Lt) == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_GC: - if ((ecode[2] != PRIV(ucp_gentype)[chartype]) == (op == OP_PROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_PC: - if ((ecode[2] != chartype) == (op == OP_PROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_SC: - if ((ecode[2] != UCD_SCRIPT(c)) == (op == OP_PROP)) - RRETURN(MATCH_NOMATCH); - break; - - /* These are specials */ - - case PT_ALNUM: - if ((PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N) == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_SPACE: /* Perl space */ - if ((PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR) - == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_PXSPACE: /* POSIX space */ - if ((PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR) - == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_WORD: - if ((PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N || - c == CHAR_UNDERSCORE) == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; - - /* This should never occur */ - - default: - RRETURN(PCRE_ERROR_INTERNAL); - } - - ecode += 3; - } - break; - - /* Match an extended Unicode sequence. We will get here only if the support - is in the binary; otherwise a compile-time error occurs. */ - - case OP_EXTUNI: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH); - while (eptr < md->end_subject) - { - int len = 1; - if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } - if (UCD_CATEGORY(c) != ucp_M) break; - eptr += len; - } - CHECK_PARTIAL(); - ecode++; - break; -#endif - - - /* Match a back reference, possibly repeatedly. Look past the end of the - item to see if there is repeat information following. The code is similar - to that for character classes, but repeated for efficiency. Then obey - similar code to character type repeats - written out again for speed. - However, if the referenced string is the empty string, always treat - it as matched, any number of times (otherwise there could be infinite - loops). */ - - case OP_REF: - case OP_REFI: - caseless = op == OP_REFI; - offset = GET2(ecode, 1) << 1; /* Doubled ref number */ - ecode += 1 + IMM2_SIZE; - - /* If the reference is unset, there are two possibilities: - - (a) In the default, Perl-compatible state, set the length negative; - this ensures that every attempt at a match fails. We can't just fail - here, because of the possibility of quantifiers with zero minima. - - (b) If the JavaScript compatibility flag is set, set the length to zero - so that the back reference matches an empty string. - - Otherwise, set the length to the length of what was matched by the - referenced subpattern. */ - - if (offset >= offset_top || md->offset_vector[offset] < 0) - length = (md->jscript_compat)? 0 : -1; - else - length = md->offset_vector[offset+1] - md->offset_vector[offset]; - - /* Set up for repetition, or handle the non-repeated case */ - - switch (*ecode) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRPLUS: - case OP_CRMINPLUS: - case OP_CRQUERY: - case OP_CRMINQUERY: - c = *ecode++ - OP_CRSTAR; - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - minimize = (*ecode == OP_CRMINRANGE); - min = GET2(ecode, 1); - max = GET2(ecode, 1 + IMM2_SIZE); - if (max == 0) max = INT_MAX; - ecode += 1 + 2 * IMM2_SIZE; - break; - - default: /* No repeat follows */ - if ((length = match_ref(offset, eptr, length, md, caseless)) < 0) - { - if (length == -2) eptr = md->end_subject; /* Partial match */ - CHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - eptr += length; - continue; /* With the main loop */ - } - - /* Handle repeated back references. If the length of the reference is - zero, just continue with the main loop. If the length is negative, it - means the reference is unset in non-Java-compatible mode. If the minimum is - zero, we can continue at the same level without recursion. For any other - minimum, carrying on will result in NOMATCH. */ - - if (length == 0) continue; - if (length < 0 && min == 0) continue; - - /* First, ensure the minimum number of matches are present. We get back - the length of the reference string explicitly rather than passing the - address of eptr, so that eptr can be a register variable. */ - - for (i = 1; i <= min; i++) - { - int slength; - if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) - { - if (slength == -2) eptr = md->end_subject; /* Partial match */ - CHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - eptr += slength; - } - - /* If min = max, continue at the same level without recursion. - They are not both allowed to be zero. */ - - if (min == max) continue; - - /* If minimizing, keep trying and advancing the pointer */ - - if (minimize) - { - for (fi = min;; fi++) - { - int slength; - RMATCH(eptr, ecode, offset_top, md, eptrb, RM14); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) - { - if (slength == -2) eptr = md->end_subject; /* Partial match */ - CHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - eptr += slength; - } - /* Control never gets here */ - } - - /* If maximizing, find the longest string and work backwards */ - - else - { - pp = eptr; - for (i = min; i < max; i++) - { - int slength; - if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) - { - /* Can't use CHECK_PARTIAL because we don't want to update eptr in - the soft partial matching case. */ - - if (slength == -2 && md->partial != 0 && - md->end_subject > md->start_used_ptr) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - break; - } - eptr += slength; - } - - while (eptr >= pp) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM15); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr -= length; - } - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - - /* Match a bit-mapped character class, possibly repeatedly. This op code is - used when all the characters in the class have values in the range 0-255, - and either the matching is caseful, or the characters are in the range - 0-127 when UTF-8 processing is enabled. The only difference between - OP_CLASS and OP_NCLASS occurs when a data character outside the range is - encountered. - - First, look past the end of the item to see if there is repeat information - following. Then obey similar code to character type repeats - written out - again for speed. */ - - case OP_NCLASS: - case OP_CLASS: - { - /* The data variable is saved across frames, so the byte map needs to - be stored there. */ -#define BYTE_MAP ((pcre_uint8 *)data) - data = ecode + 1; /* Save for matching */ - ecode += 1 + (32 / sizeof(pcre_uchar)); /* Advance past the item */ - - switch (*ecode) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRPLUS: - case OP_CRMINPLUS: - case OP_CRQUERY: - case OP_CRMINQUERY: - c = *ecode++ - OP_CRSTAR; - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - minimize = (*ecode == OP_CRMINRANGE); - min = GET2(ecode, 1); - max = GET2(ecode, 1 + IMM2_SIZE); - if (max == 0) max = INT_MAX; - ecode += 1 + 2 * IMM2_SIZE; - break; - - default: /* No repeat follows */ - min = max = 1; - break; - } - - /* First, ensure the minimum number of matches are present. */ - -#ifdef SUPPORT_UTF - if (utf) - { - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(c, eptr); - if (c > 255) - { - if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); - } - else - if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); - } - } - else -#endif - /* Not UTF mode */ - { - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - c = *eptr++; -#ifndef COMPILE_PCRE8 - if (c > 255) - { - if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); - } - else -#endif - if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); - } - } - - /* If max == min we can continue with the main loop without the - need to recurse. */ - - if (min == max) continue; - - /* If minimizing, keep testing the rest of the expression and advancing - the pointer while it matches the class. */ - - if (minimize) - { -#ifdef SUPPORT_UTF - if (utf) - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM16); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(c, eptr); - if (c > 255) - { - if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); - } - else - if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); - } - } - else -#endif - /* Not UTF mode */ - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM17); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - c = *eptr++; -#ifndef COMPILE_PCRE8 - if (c > 255) - { - if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); - } - else -#endif - if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - } - - /* If maximizing, find the longest possible run, then work backwards. */ - - else - { - pp = eptr; - -#ifdef SUPPORT_UTF - if (utf) - { - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(c, eptr, len); - if (c > 255) - { - if (op == OP_CLASS) break; - } - else - if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break; - eptr += len; - } - for (;;) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM18); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ - BACKCHAR(eptr); - } - } - else -#endif - /* Not UTF mode */ - { - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - c = *eptr; -#ifndef COMPILE_PCRE8 - if (c > 255) - { - if (op == OP_CLASS) break; - } - else -#endif - if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break; - eptr++; - } - while (eptr >= pp) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM19); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - } - } - - RRETURN(MATCH_NOMATCH); - } -#undef BYTE_MAP - } - /* Control never gets here */ - - - /* Match an extended character class. This opcode is encountered only - when UTF-8 mode mode is supported. Nevertheless, we may not be in UTF-8 - mode, because Unicode properties are supported in non-UTF-8 mode. */ - -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - case OP_XCLASS: - { - data = ecode + 1 + LINK_SIZE; /* Save for matching */ - ecode += GET(ecode, 1); /* Advance past the item */ - - switch (*ecode) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRPLUS: - case OP_CRMINPLUS: - case OP_CRQUERY: - case OP_CRMINQUERY: - c = *ecode++ - OP_CRSTAR; - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - minimize = (*ecode == OP_CRMINRANGE); - min = GET2(ecode, 1); - max = GET2(ecode, 1 + IMM2_SIZE); - if (max == 0) max = INT_MAX; - ecode += 1 + 2 * IMM2_SIZE; - break; - - default: /* No repeat follows */ - min = max = 1; - break; - } - - /* First, ensure the minimum number of matches are present. */ - - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH); - } - - /* If max == min we can continue with the main loop without the - need to recurse. */ - - if (min == max) continue; - - /* If minimizing, keep testing the rest of the expression and advancing - the pointer while it matches the class. */ - - if (minimize) - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM20); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - } - - /* If maximizing, find the longest possible run, then work backwards. */ - - else - { - pp = eptr; - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } -#ifdef SUPPORT_UTF - GETCHARLENTEST(c, eptr, len); -#else - c = *eptr; -#endif - if (!PRIV(xclass)(c, data, utf)) break; - eptr += len; - } - for(;;) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM21); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ -#ifdef SUPPORT_UTF - if (utf) BACKCHAR(eptr); -#endif - } - RRETURN(MATCH_NOMATCH); - } - - /* Control never gets here */ - } -#endif /* End of XCLASS */ - - /* Match a single character, casefully */ - - case OP_CHAR: -#ifdef SUPPORT_UTF - if (utf) - { - length = 1; - ecode++; - GETCHARLEN(fc, ecode, length); - if (length > md->end_subject - eptr) - { - CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */ - RRETURN(MATCH_NOMATCH); - } - while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH); - } - else -#endif - /* Not UTF mode */ - { - if (md->end_subject - eptr < 1) - { - SCHECK_PARTIAL(); /* This one can use SCHECK_PARTIAL() */ - RRETURN(MATCH_NOMATCH); - } - if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH); - ecode += 2; - } - break; - - /* Match a single character, caselessly. If we are at the end of the - subject, give up immediately. */ - - case OP_CHARI: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - -#ifdef SUPPORT_UTF - if (utf) - { - length = 1; - ecode++; - GETCHARLEN(fc, ecode, length); - - /* If the pattern character's value is < 128, we have only one byte, and - we know that its other case must also be one byte long, so we can use the - fast lookup table. We know that there is at least one byte left in the - subject. */ - - if (fc < 128) - { - if (md->lcc[fc] - != TABLE_GET(*eptr, md->lcc, *eptr)) RRETURN(MATCH_NOMATCH); - ecode++; - eptr++; - } - - /* Otherwise we must pick up the subject character. Note that we cannot - use the value of "length" to check for sufficient bytes left, because the - other case of the character may have more or fewer bytes. */ - - else - { - unsigned int dc; - GETCHARINC(dc, eptr); - ecode += length; - - /* If we have Unicode property support, we can use it to test the other - case of the character, if there is one. */ - - if (fc != dc) - { -#ifdef SUPPORT_UCP - if (dc != UCD_OTHERCASE(fc)) -#endif - RRETURN(MATCH_NOMATCH); - } - } - } - else -#endif /* SUPPORT_UTF */ - - /* Not UTF mode */ - { - if (TABLE_GET(ecode[1], md->lcc, ecode[1]) - != TABLE_GET(*eptr, md->lcc, *eptr)) RRETURN(MATCH_NOMATCH); - eptr++; - ecode += 2; - } - break; - - /* Match a single character repeatedly. */ - - case OP_EXACT: - case OP_EXACTI: - min = max = GET2(ecode, 1); - ecode += 1 + IMM2_SIZE; - goto REPEATCHAR; - - case OP_POSUPTO: - case OP_POSUPTOI: - possessive = TRUE; - /* Fall through */ - - case OP_UPTO: - case OP_UPTOI: - case OP_MINUPTO: - case OP_MINUPTOI: - min = 0; - max = GET2(ecode, 1); - minimize = *ecode == OP_MINUPTO || *ecode == OP_MINUPTOI; - ecode += 1 + IMM2_SIZE; - goto REPEATCHAR; - - case OP_POSSTAR: - case OP_POSSTARI: - possessive = TRUE; - min = 0; - max = INT_MAX; - ecode++; - goto REPEATCHAR; - - case OP_POSPLUS: - case OP_POSPLUSI: - possessive = TRUE; - min = 1; - max = INT_MAX; - ecode++; - goto REPEATCHAR; - - case OP_POSQUERY: - case OP_POSQUERYI: - possessive = TRUE; - min = 0; - max = 1; - ecode++; - goto REPEATCHAR; - - case OP_STAR: - case OP_STARI: - case OP_MINSTAR: - case OP_MINSTARI: - case OP_PLUS: - case OP_PLUSI: - case OP_MINPLUS: - case OP_MINPLUSI: - case OP_QUERY: - case OP_QUERYI: - case OP_MINQUERY: - case OP_MINQUERYI: - c = *ecode++ - ((op < OP_STARI)? OP_STAR : OP_STARI); - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - - /* Common code for all repeated single-character matches. */ - - REPEATCHAR: -#ifdef SUPPORT_UTF - if (utf) - { - length = 1; - charptr = ecode; - GETCHARLEN(fc, ecode, length); - ecode += length; - - /* Handle multibyte character matching specially here. There is - support for caseless matching if UCP support is present. */ - - if (length > 1) - { -#ifdef SUPPORT_UCP - unsigned int othercase; - if (op >= OP_STARI && /* Caseless */ - (othercase = UCD_OTHERCASE(fc)) != fc) - oclength = PRIV(ord2utf)(othercase, occhars); - else oclength = 0; -#endif /* SUPPORT_UCP */ - - for (i = 1; i <= min; i++) - { - if (eptr <= md->end_subject - length && - memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length; -#ifdef SUPPORT_UCP - else if (oclength > 0 && - eptr <= md->end_subject - oclength && - memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength; -#endif /* SUPPORT_UCP */ - else - { - CHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - } - - if (min == max) continue; - - if (minimize) - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM22); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr <= md->end_subject - length && - memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length; -#ifdef SUPPORT_UCP - else if (oclength > 0 && - eptr <= md->end_subject - oclength && - memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength; -#endif /* SUPPORT_UCP */ - else - { - CHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - } - - else /* Maximize */ - { - pp = eptr; - for (i = min; i < max; i++) - { - if (eptr <= md->end_subject - length && - memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length; -#ifdef SUPPORT_UCP - else if (oclength > 0 && - eptr <= md->end_subject - oclength && - memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength; -#endif /* SUPPORT_UCP */ - else - { - CHECK_PARTIAL(); - break; - } - } - - if (possessive) continue; - - for(;;) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM23); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr == pp) { RRETURN(MATCH_NOMATCH); } -#ifdef SUPPORT_UCP - eptr--; - BACKCHAR(eptr); -#else /* without SUPPORT_UCP */ - eptr -= length; -#endif /* SUPPORT_UCP */ - } - } - /* Control never gets here */ - } - - /* If the length of a UTF-8 character is 1, we fall through here, and - obey the code as for non-UTF-8 characters below, though in this case the - value of fc will always be < 128. */ - } - else -#endif /* SUPPORT_UTF */ - /* When not in UTF-8 mode, load a single-byte character. */ - fc = *ecode++; - - /* The value of fc at this point is always one character, though we may - or may not be in UTF mode. The code is duplicated for the caseless and - caseful cases, for speed, since matching characters is likely to be quite - common. First, ensure the minimum number of matches are present. If min = - max, continue at the same level without recursing. Otherwise, if - minimizing, keep trying the rest of the expression and advancing one - matching character if failing, up to the maximum. Alternatively, if - maximizing, find the maximum number of characters and work backwards. */ - - DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max, - max, (char *)eptr)); - - if (op >= OP_STARI) /* Caseless */ - { -#ifdef COMPILE_PCRE8 - /* fc must be < 128 if UTF is enabled. */ - foc = md->fcc[fc]; -#else -#ifdef SUPPORT_UTF -#ifdef SUPPORT_UCP - if (utf && fc > 127) - foc = UCD_OTHERCASE(fc); -#else - if (utf && fc > 127) - foc = fc; -#endif /* SUPPORT_UCP */ - else -#endif /* SUPPORT_UTF */ - foc = TABLE_GET(fc, md->fcc, fc); -#endif /* COMPILE_PCRE8 */ - - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc != *eptr && foc != *eptr) RRETURN(MATCH_NOMATCH); - eptr++; - } - if (min == max) continue; - if (minimize) - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM24); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc != *eptr && foc != *eptr) RRETURN(MATCH_NOMATCH); - eptr++; - } - /* Control never gets here */ - } - else /* Maximize */ - { - pp = eptr; - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (fc != *eptr && foc != *eptr) break; - eptr++; - } - - if (possessive) continue; - - while (eptr >= pp) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM25); - eptr--; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - } - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - } - - /* Caseful comparisons (includes all multi-byte characters) */ - - else - { - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc != *eptr++) RRETURN(MATCH_NOMATCH); - } - - if (min == max) continue; - - if (minimize) - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM26); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc != *eptr++) RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - } - else /* Maximize */ - { - pp = eptr; - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (fc != *eptr) break; - eptr++; - } - if (possessive) continue; - - while (eptr >= pp) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM27); - eptr--; - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - } - RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - - /* Match a negated single one-byte character. The character we are - checking can be multibyte. */ - - case OP_NOT: - case OP_NOTI: - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } -#ifdef SUPPORT_UTF - if (utf) - { - unsigned int ch, och; - - ecode++; - GETCHARINC(ch, ecode); - GETCHARINC(c, eptr); - - if (op == OP_NOT) - { - if (ch == c) RRETURN(MATCH_NOMATCH); - } - else - { -#ifdef SUPPORT_UCP - if (ch > 127) - och = UCD_OTHERCASE(ch); -#else - if (ch > 127) - och = ch; -#endif /* SUPPORT_UCP */ - else - och = TABLE_GET(ch, md->fcc, ch); - if (ch == c || och == c) RRETURN(MATCH_NOMATCH); - } - } - else -#endif - { - unsigned int ch = ecode[1]; - c = *eptr++; - if (ch == c || (op == OP_NOTI && TABLE_GET(ch, md->fcc, ch) == c)) - RRETURN(MATCH_NOMATCH); - ecode += 2; - } - break; - - /* Match a negated single one-byte character repeatedly. This is almost a - repeat of the code for a repeated single character, but I haven't found a - nice way of commoning these up that doesn't require a test of the - positive/negative option for each character match. Maybe that wouldn't add - very much to the time taken, but character matching *is* what this is all - about... */ - - case OP_NOTEXACT: - case OP_NOTEXACTI: - min = max = GET2(ecode, 1); - ecode += 1 + IMM2_SIZE; - goto REPEATNOTCHAR; - - case OP_NOTUPTO: - case OP_NOTUPTOI: - case OP_NOTMINUPTO: - case OP_NOTMINUPTOI: - min = 0; - max = GET2(ecode, 1); - minimize = *ecode == OP_NOTMINUPTO || *ecode == OP_NOTMINUPTOI; - ecode += 1 + IMM2_SIZE; - goto REPEATNOTCHAR; - - case OP_NOTPOSSTAR: - case OP_NOTPOSSTARI: - possessive = TRUE; - min = 0; - max = INT_MAX; - ecode++; - goto REPEATNOTCHAR; - - case OP_NOTPOSPLUS: - case OP_NOTPOSPLUSI: - possessive = TRUE; - min = 1; - max = INT_MAX; - ecode++; - goto REPEATNOTCHAR; - - case OP_NOTPOSQUERY: - case OP_NOTPOSQUERYI: - possessive = TRUE; - min = 0; - max = 1; - ecode++; - goto REPEATNOTCHAR; - - case OP_NOTPOSUPTO: - case OP_NOTPOSUPTOI: - possessive = TRUE; - min = 0; - max = GET2(ecode, 1); - ecode += 1 + IMM2_SIZE; - goto REPEATNOTCHAR; - - case OP_NOTSTAR: - case OP_NOTSTARI: - case OP_NOTMINSTAR: - case OP_NOTMINSTARI: - case OP_NOTPLUS: - case OP_NOTPLUSI: - case OP_NOTMINPLUS: - case OP_NOTMINPLUSI: - case OP_NOTQUERY: - case OP_NOTQUERYI: - case OP_NOTMINQUERY: - case OP_NOTMINQUERYI: - c = *ecode++ - ((op >= OP_NOTSTARI)? OP_NOTSTARI: OP_NOTSTAR); - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - - /* Common code for all repeated single-byte matches. */ - - REPEATNOTCHAR: - GETCHARINCTEST(fc, ecode); - - /* The code is duplicated for the caseless and caseful cases, for speed, - since matching characters is likely to be quite common. First, ensure the - minimum number of matches are present. If min = max, continue at the same - level without recursing. Otherwise, if minimizing, keep trying the rest of - the expression and advancing one matching character if failing, up to the - maximum. Alternatively, if maximizing, find the maximum number of - characters and work backwards. */ - - DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max, - max, (char *)eptr)); - - if (op >= OP_NOTSTARI) /* Caseless */ - { -#ifdef SUPPORT_UTF -#ifdef SUPPORT_UCP - if (utf && fc > 127) - foc = UCD_OTHERCASE(fc); -#else - if (utf && fc > 127) - foc = fc; -#endif /* SUPPORT_UCP */ - else -#endif /* SUPPORT_UTF */ - foc = TABLE_GET(fc, md->fcc, fc); - -#ifdef SUPPORT_UTF - if (utf) - { - unsigned int d; - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(d, eptr); - if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH); - } - } - else -#endif - /* Not UTF mode */ - { - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH); - eptr++; - } - } - - if (min == max) continue; - - if (minimize) - { -#ifdef SUPPORT_UTF - if (utf) - { - unsigned int d; - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM28); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(d, eptr); - if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH); - } - } - else -#endif - /* Not UTF mode */ - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM29); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH); - eptr++; - } - } - /* Control never gets here */ - } - - /* Maximize case */ - - else - { - pp = eptr; - -#ifdef SUPPORT_UTF - if (utf) - { - unsigned int d; - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(d, eptr, len); - if (fc == d || (unsigned int)foc == d) break; - eptr += len; - } - if (possessive) continue; - for(;;) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM30); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ - BACKCHAR(eptr); - } - } - else -#endif - /* Not UTF mode */ - { - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (fc == *eptr || foc == *eptr) break; - eptr++; - } - if (possessive) continue; - while (eptr >= pp) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM31); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - } - } - - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - } - - /* Caseful comparisons */ - - else - { -#ifdef SUPPORT_UTF - if (utf) - { - unsigned int d; - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(d, eptr); - if (fc == d) RRETURN(MATCH_NOMATCH); - } - } - else -#endif - /* Not UTF mode */ - { - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc == *eptr++) RRETURN(MATCH_NOMATCH); - } - } - - if (min == max) continue; - - if (minimize) - { -#ifdef SUPPORT_UTF - if (utf) - { - unsigned int d; - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM32); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(d, eptr); - if (fc == d) RRETURN(MATCH_NOMATCH); - } - } - else -#endif - /* Not UTF mode */ - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM33); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (fc == *eptr++) RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - } - - /* Maximize case */ - - else - { - pp = eptr; - -#ifdef SUPPORT_UTF - if (utf) - { - unsigned int d; - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(d, eptr, len); - if (fc == d) break; - eptr += len; - } - if (possessive) continue; - for(;;) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM34); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ - BACKCHAR(eptr); - } - } - else -#endif - /* Not UTF mode */ - { - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (fc == *eptr) break; - eptr++; - } - if (possessive) continue; - while (eptr >= pp) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM35); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - } - } - - RRETURN(MATCH_NOMATCH); - } - } - /* Control never gets here */ - - /* Match a single character type repeatedly; several different opcodes - share code. This is very similar to the code for single characters, but we - repeat it in the interests of efficiency. */ - - case OP_TYPEEXACT: - min = max = GET2(ecode, 1); - minimize = TRUE; - ecode += 1 + IMM2_SIZE; - goto REPEATTYPE; - - case OP_TYPEUPTO: - case OP_TYPEMINUPTO: - min = 0; - max = GET2(ecode, 1); - minimize = *ecode == OP_TYPEMINUPTO; - ecode += 1 + IMM2_SIZE; - goto REPEATTYPE; - - case OP_TYPEPOSSTAR: - possessive = TRUE; - min = 0; - max = INT_MAX; - ecode++; - goto REPEATTYPE; - - case OP_TYPEPOSPLUS: - possessive = TRUE; - min = 1; - max = INT_MAX; - ecode++; - goto REPEATTYPE; - - case OP_TYPEPOSQUERY: - possessive = TRUE; - min = 0; - max = 1; - ecode++; - goto REPEATTYPE; - - case OP_TYPEPOSUPTO: - possessive = TRUE; - min = 0; - max = GET2(ecode, 1); - ecode += 1 + IMM2_SIZE; - goto REPEATTYPE; - - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEQUERY: - case OP_TYPEMINQUERY: - c = *ecode++ - OP_TYPESTAR; - minimize = (c & 1) != 0; - min = rep_min[c]; /* Pick up values from tables; */ - max = rep_max[c]; /* zero for max => infinity */ - if (max == 0) max = INT_MAX; - - /* Common code for all repeated single character type matches. Note that - in UTF-8 mode, '.' matches a character of any length, but for the other - character types, the valid characters are all one-byte long. */ - - REPEATTYPE: - ctype = *ecode++; /* Code for the character type */ - -#ifdef SUPPORT_UCP - if (ctype == OP_PROP || ctype == OP_NOTPROP) - { - prop_fail_result = ctype == OP_NOTPROP; - prop_type = *ecode++; - prop_value = *ecode++; - } - else prop_type = -1; -#endif - - /* First, ensure the minimum number of matches are present. Use inline - code for maximizing the speed, and do the type test once at the start - (i.e. keep it out of the loop). Separate the UTF-8 code completely as that - is tidier. Also separate the UCP code, which can be the same for both UTF-8 - and single-bytes. */ - - if (min > 0) - { -#ifdef SUPPORT_UCP - if (prop_type >= 0) - { - switch(prop_type) - { - case PT_ANY: - if (prop_fail_result) RRETURN(MATCH_NOMATCH); - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - } - break; - - case PT_LAMP: - for (i = 1; i <= min; i++) - { - int chartype; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - chartype = UCD_CHARTYPE(c); - if ((chartype == ucp_Lu || - chartype == ucp_Ll || - chartype == ucp_Lt) == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - break; - - case PT_GC: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - break; - - case PT_PC: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - break; - - case PT_SC: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - break; - - case PT_ALNUM: - for (i = 1; i <= min; i++) - { - int category; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - category = UCD_CATEGORY(c); - if ((category == ucp_L || category == ucp_N) == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - break; - - case PT_SPACE: /* Perl space */ - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL || - c == CHAR_FF || c == CHAR_CR) - == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - break; - - case PT_PXSPACE: /* POSIX space */ - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL || - c == CHAR_VT || c == CHAR_FF || c == CHAR_CR) - == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - break; - - case PT_WORD: - for (i = 1; i <= min; i++) - { - int category; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - category = UCD_CATEGORY(c); - if ((category == ucp_L || category == ucp_N || c == CHAR_UNDERSCORE) - == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - break; - - /* This should not occur */ - - default: - RRETURN(PCRE_ERROR_INTERNAL); - } - } - - /* Match extended Unicode sequences. We will get here only if the - support is in the binary; otherwise a compile-time error occurs. */ - - else if (ctype == OP_EXTUNI) - { - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH); - while (eptr < md->end_subject) - { - int len = 1; - if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } - if (UCD_CATEGORY(c) != ucp_M) break; - eptr += len; - } - CHECK_PARTIAL(); - } - } - - else -#endif /* SUPPORT_UCP */ - -/* Handle all other cases when the coding is UTF-8 */ - -#ifdef SUPPORT_UTF - if (utf) switch(ctype) - { - case OP_ANY: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); - if (md->partial != 0 && - eptr + 1 >= md->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - *eptr == NLBLOCK->nl[0]) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - eptr++; - ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); - } - break; - - case OP_ALLANY: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - eptr++; - ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); - } - break; - - case OP_ANYBYTE: - if (eptr > md->end_subject - min) RRETURN(MATCH_NOMATCH); - eptr += min; - break; - - case OP_ANYNL: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(c, eptr); - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - - case 0x000d: - if (eptr < md->end_subject && *eptr == 0x0a) eptr++; - break; - - case 0x000a: - break; - - case 0x000b: - case 0x000c: - case 0x0085: - case 0x2028: - case 0x2029: - if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); - break; - } - } - break; - - case OP_NOT_HSPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(c, eptr); - switch(c) - { - default: break; - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - RRETURN(MATCH_NOMATCH); - } - } - break; - - case OP_HSPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(c, eptr); - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - break; - } - } - break; - - case OP_NOT_VSPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(c, eptr); - switch(c) - { - default: break; - case 0x0a: /* LF */ - case 0x0b: /* VT */ - case 0x0c: /* FF */ - case 0x0d: /* CR */ - case 0x85: /* NEL */ - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ - RRETURN(MATCH_NOMATCH); - } - } - break; - - case OP_VSPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(c, eptr); - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - case 0x0a: /* LF */ - case 0x0b: /* VT */ - case 0x0c: /* FF */ - case 0x0d: /* CR */ - case 0x85: /* NEL */ - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ - break; - } - } - break; - - case OP_NOT_DIGIT: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINC(c, eptr); - if (c < 128 && (md->ctypes[c] & ctype_digit) != 0) - RRETURN(MATCH_NOMATCH); - } - break; - - case OP_DIGIT: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (*eptr >= 128 || (md->ctypes[*eptr] & ctype_digit) == 0) - RRETURN(MATCH_NOMATCH); - eptr++; - /* No need to skip more bytes - we know it's a 1-byte character */ - } - break; - - case OP_NOT_WHITESPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0) - RRETURN(MATCH_NOMATCH); - eptr++; - ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); - } - break; - - case OP_WHITESPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (*eptr >= 128 || (md->ctypes[*eptr] & ctype_space) == 0) - RRETURN(MATCH_NOMATCH); - eptr++; - /* No need to skip more bytes - we know it's a 1-byte character */ - } - break; - - case OP_NOT_WORDCHAR: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (*eptr < 128 && (md->ctypes[*eptr] & ctype_word) != 0) - RRETURN(MATCH_NOMATCH); - eptr++; - ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); - } - break; - - case OP_WORDCHAR: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (*eptr >= 128 || (md->ctypes[*eptr] & ctype_word) == 0) - RRETURN(MATCH_NOMATCH); - eptr++; - /* No need to skip more bytes - we know it's a 1-byte character */ - } - break; - - default: - RRETURN(PCRE_ERROR_INTERNAL); - } /* End switch(ctype) */ - - else -#endif /* SUPPORT_UTF */ - - /* Code for the non-UTF-8 case for minimum matching of operators other - than OP_PROP and OP_NOTPROP. */ - - switch(ctype) - { - case OP_ANY: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); - if (md->partial != 0 && - eptr + 1 >= md->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - *eptr == NLBLOCK->nl[0]) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - eptr++; - } - break; - - case OP_ALLANY: - if (eptr > md->end_subject - min) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - eptr += min; - break; - - case OP_ANYBYTE: - if (eptr > md->end_subject - min) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - eptr += min; - break; - - case OP_ANYNL: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - switch(*eptr++) - { - default: RRETURN(MATCH_NOMATCH); - - case 0x000d: - if (eptr < md->end_subject && *eptr == 0x0a) eptr++; - break; - - case 0x000a: - break; - - case 0x000b: - case 0x000c: - case 0x0085: -#ifdef COMPILE_PCRE16 - case 0x2028: - case 0x2029: -#endif - if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); - break; - } - } - break; - - case OP_NOT_HSPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - switch(*eptr++) - { - default: break; - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ -#ifdef COMPILE_PCRE16 - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ -#endif - RRETURN(MATCH_NOMATCH); - } - } - break; - - case OP_HSPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - switch(*eptr++) - { - default: RRETURN(MATCH_NOMATCH); - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ -#ifdef COMPILE_PCRE16 - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ -#endif - break; - } - } - break; - - case OP_NOT_VSPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - switch(*eptr++) - { - default: break; - case 0x0a: /* LF */ - case 0x0b: /* VT */ - case 0x0c: /* FF */ - case 0x0d: /* CR */ - case 0x85: /* NEL */ -#ifdef COMPILE_PCRE16 - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ -#endif - RRETURN(MATCH_NOMATCH); - } - } - break; - - case OP_VSPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - switch(*eptr++) - { - default: RRETURN(MATCH_NOMATCH); - case 0x0a: /* LF */ - case 0x0b: /* VT */ - case 0x0c: /* FF */ - case 0x0d: /* CR */ - case 0x85: /* NEL */ -#ifdef COMPILE_PCRE16 - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ -#endif - break; - } - } - break; - - case OP_NOT_DIGIT: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0) - RRETURN(MATCH_NOMATCH); - eptr++; - } - break; - - case OP_DIGIT: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0) - RRETURN(MATCH_NOMATCH); - eptr++; - } - break; - - case OP_NOT_WHITESPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0) - RRETURN(MATCH_NOMATCH); - eptr++; - } - break; - - case OP_WHITESPACE: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0) - RRETURN(MATCH_NOMATCH); - eptr++; - } - break; - - case OP_NOT_WORDCHAR: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0) - RRETURN(MATCH_NOMATCH); - eptr++; - } - break; - - case OP_WORDCHAR: - for (i = 1; i <= min; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0) - RRETURN(MATCH_NOMATCH); - eptr++; - } - break; - - default: - RRETURN(PCRE_ERROR_INTERNAL); - } - } - - /* If min = max, continue at the same level without recursing */ - - if (min == max) continue; - - /* If minimizing, we have to test the rest of the pattern before each - subsequent match. Again, separate the UTF-8 case for speed, and also - separate the UCP cases. */ - - if (minimize) - { -#ifdef SUPPORT_UCP - if (prop_type >= 0) - { - switch(prop_type) - { - case PT_ANY: - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM36); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if (prop_fail_result) RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - - case PT_LAMP: - for (fi = min;; fi++) - { - int chartype; - RMATCH(eptr, ecode, offset_top, md, eptrb, RM37); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - chartype = UCD_CHARTYPE(c); - if ((chartype == ucp_Lu || - chartype == ucp_Ll || - chartype == ucp_Lt) == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - - case PT_GC: - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM38); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - - case PT_PC: - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM39); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - - case PT_SC: - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM40); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - - case PT_ALNUM: - for (fi = min;; fi++) - { - int category; - RMATCH(eptr, ecode, offset_top, md, eptrb, RM59); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - category = UCD_CATEGORY(c); - if ((category == ucp_L || category == ucp_N) == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - - case PT_SPACE: /* Perl space */ - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM60); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL || - c == CHAR_FF || c == CHAR_CR) - == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - - case PT_PXSPACE: /* POSIX space */ - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM61); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL || - c == CHAR_VT || c == CHAR_FF || c == CHAR_CR) - == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - - case PT_WORD: - for (fi = min;; fi++) - { - int category; - RMATCH(eptr, ecode, offset_top, md, eptrb, RM62); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - category = UCD_CATEGORY(c); - if ((category == ucp_L || - category == ucp_N || - c == CHAR_UNDERSCORE) - == prop_fail_result) - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - - /* This should never occur */ - - default: - RRETURN(PCRE_ERROR_INTERNAL); - } - } - - /* Match extended Unicode sequences. We will get here only if the - support is in the binary; otherwise a compile-time error occurs. */ - - else if (ctype == OP_EXTUNI) - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM41); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - GETCHARINCTEST(c, eptr); - if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH); - while (eptr < md->end_subject) - { - int len = 1; - if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } - if (UCD_CATEGORY(c) != ucp_M) break; - eptr += len; - } - CHECK_PARTIAL(); - } - } - else -#endif /* SUPPORT_UCP */ - -#ifdef SUPPORT_UTF - if (utf) - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM42); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (ctype == OP_ANY && IS_NEWLINE(eptr)) - RRETURN(MATCH_NOMATCH); - GETCHARINC(c, eptr); - switch(ctype) - { - case OP_ANY: /* This is the non-NL case */ - if (md->partial != 0 && /* Take care with CRLF partial */ - eptr >= md->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - c == NLBLOCK->nl[0]) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - break; - - case OP_ALLANY: - case OP_ANYBYTE: - break; - - case OP_ANYNL: - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - case 0x000d: - if (eptr < md->end_subject && *eptr == 0x0a) eptr++; - break; - case 0x000a: - break; - - case 0x000b: - case 0x000c: - case 0x0085: - case 0x2028: - case 0x2029: - if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); - break; - } - break; - - case OP_NOT_HSPACE: - switch(c) - { - default: break; - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - RRETURN(MATCH_NOMATCH); - } - break; - - case OP_HSPACE: - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - break; - } - break; - - case OP_NOT_VSPACE: - switch(c) - { - default: break; - case 0x0a: /* LF */ - case 0x0b: /* VT */ - case 0x0c: /* FF */ - case 0x0d: /* CR */ - case 0x85: /* NEL */ - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ - RRETURN(MATCH_NOMATCH); - } - break; - - case OP_VSPACE: - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - case 0x0a: /* LF */ - case 0x0b: /* VT */ - case 0x0c: /* FF */ - case 0x0d: /* CR */ - case 0x85: /* NEL */ - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ - break; - } - break; - - case OP_NOT_DIGIT: - if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) - RRETURN(MATCH_NOMATCH); - break; - - case OP_DIGIT: - if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0) - RRETURN(MATCH_NOMATCH); - break; - - case OP_NOT_WHITESPACE: - if (c < 256 && (md->ctypes[c] & ctype_space) != 0) - RRETURN(MATCH_NOMATCH); - break; - - case OP_WHITESPACE: - if (c >= 256 || (md->ctypes[c] & ctype_space) == 0) - RRETURN(MATCH_NOMATCH); - break; - - case OP_NOT_WORDCHAR: - if (c < 256 && (md->ctypes[c] & ctype_word) != 0) - RRETURN(MATCH_NOMATCH); - break; - - case OP_WORDCHAR: - if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) - RRETURN(MATCH_NOMATCH); - break; - - default: - RRETURN(PCRE_ERROR_INTERNAL); - } - } - } - else -#endif - /* Not UTF mode */ - { - for (fi = min;; fi++) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM43); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (fi >= max) RRETURN(MATCH_NOMATCH); - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - RRETURN(MATCH_NOMATCH); - } - if (ctype == OP_ANY && IS_NEWLINE(eptr)) - RRETURN(MATCH_NOMATCH); - c = *eptr++; - switch(ctype) - { - case OP_ANY: /* This is the non-NL case */ - if (md->partial != 0 && /* Take care with CRLF partial */ - eptr >= md->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - c == NLBLOCK->nl[0]) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - break; - - case OP_ALLANY: - case OP_ANYBYTE: - break; - - case OP_ANYNL: - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - case 0x000d: - if (eptr < md->end_subject && *eptr == 0x0a) eptr++; - break; - - case 0x000a: - break; - - case 0x000b: - case 0x000c: - case 0x0085: -#ifdef COMPILE_PCRE16 - case 0x2028: - case 0x2029: -#endif - if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); - break; - } - break; - - case OP_NOT_HSPACE: - switch(c) - { - default: break; - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ -#ifdef COMPILE_PCRE16 - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ -#endif - RRETURN(MATCH_NOMATCH); - } - break; - - case OP_HSPACE: - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ -#ifdef COMPILE_PCRE16 - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ -#endif - break; - } - break; - - case OP_NOT_VSPACE: - switch(c) - { - default: break; - case 0x0a: /* LF */ - case 0x0b: /* VT */ - case 0x0c: /* FF */ - case 0x0d: /* CR */ - case 0x85: /* NEL */ -#ifdef COMPILE_PCRE16 - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ -#endif - RRETURN(MATCH_NOMATCH); - } - break; - - case OP_VSPACE: - switch(c) - { - default: RRETURN(MATCH_NOMATCH); - case 0x0a: /* LF */ - case 0x0b: /* VT */ - case 0x0c: /* FF */ - case 0x0d: /* CR */ - case 0x85: /* NEL */ -#ifdef COMPILE_PCRE16 - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ -#endif - break; - } - break; - - case OP_NOT_DIGIT: - if (MAX_255(c) && (md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_DIGIT: - if (!MAX_255(c) || (md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_NOT_WHITESPACE: - if (MAX_255(c) && (md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_WHITESPACE: - if (!MAX_255(c) || (md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_NOT_WORDCHAR: - if (MAX_255(c) && (md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); - break; - - case OP_WORDCHAR: - if (!MAX_255(c) || (md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); - break; - - default: - RRETURN(PCRE_ERROR_INTERNAL); - } - } - } - /* Control never gets here */ - } - - /* If maximizing, it is worth using inline code for speed, doing the type - test once at the start (i.e. keep it out of the loop). Again, keep the - UTF-8 and UCP stuff separate. */ - - else - { - pp = eptr; /* Remember where we started */ - -#ifdef SUPPORT_UCP - if (prop_type >= 0) - { - switch(prop_type) - { - case PT_ANY: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLENTEST(c, eptr, len); - if (prop_fail_result) break; - eptr+= len; - } - break; - - case PT_LAMP: - for (i = min; i < max; i++) - { - int chartype; - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLENTEST(c, eptr, len); - chartype = UCD_CHARTYPE(c); - if ((chartype == ucp_Lu || - chartype == ucp_Ll || - chartype == ucp_Lt) == prop_fail_result) - break; - eptr+= len; - } - break; - - case PT_GC: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLENTEST(c, eptr, len); - if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) break; - eptr+= len; - } - break; - - case PT_PC: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLENTEST(c, eptr, len); - if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) break; - eptr+= len; - } - break; - - case PT_SC: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLENTEST(c, eptr, len); - if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) break; - eptr+= len; - } - break; - - case PT_ALNUM: - for (i = min; i < max; i++) - { - int category; - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLENTEST(c, eptr, len); - category = UCD_CATEGORY(c); - if ((category == ucp_L || category == ucp_N) == prop_fail_result) - break; - eptr+= len; - } - break; - - case PT_SPACE: /* Perl space */ - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLENTEST(c, eptr, len); - if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL || - c == CHAR_FF || c == CHAR_CR) - == prop_fail_result) - break; - eptr+= len; - } - break; - - case PT_PXSPACE: /* POSIX space */ - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLENTEST(c, eptr, len); - if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL || - c == CHAR_VT || c == CHAR_FF || c == CHAR_CR) - == prop_fail_result) - break; - eptr+= len; - } - break; - - case PT_WORD: - for (i = min; i < max; i++) - { - int category; - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLENTEST(c, eptr, len); - category = UCD_CATEGORY(c); - if ((category == ucp_L || category == ucp_N || - c == CHAR_UNDERSCORE) == prop_fail_result) - break; - eptr+= len; - } - break; - - default: - RRETURN(PCRE_ERROR_INTERNAL); - } - - /* eptr is now past the end of the maximum run */ - - if (possessive) continue; - for(;;) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM44); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ - if (utf) BACKCHAR(eptr); - } - } - - /* Match extended Unicode sequences. We will get here only if the - support is in the binary; otherwise a compile-time error occurs. */ - - else if (ctype == OP_EXTUNI) - { - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } - if (UCD_CATEGORY(c) == ucp_M) break; - eptr += len; - while (eptr < md->end_subject) - { - len = 1; - if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } - if (UCD_CATEGORY(c) != ucp_M) break; - eptr += len; - } - CHECK_PARTIAL(); - } - - /* eptr is now past the end of the maximum run */ - - if (possessive) continue; - - for(;;) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM45); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ - for (;;) /* Move back over one extended */ - { - if (!utf) c = *eptr; else - { - BACKCHAR(eptr); - GETCHAR(c, eptr); - } - if (UCD_CATEGORY(c) != ucp_M) break; - eptr--; - } - } - } - - else -#endif /* SUPPORT_UCP */ - -#ifdef SUPPORT_UTF - if (utf) - { - switch(ctype) - { - case OP_ANY: - if (max < INT_MAX) - { - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (IS_NEWLINE(eptr)) break; - if (md->partial != 0 && /* Take care with CRLF partial */ - eptr + 1 >= md->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - *eptr == NLBLOCK->nl[0]) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - eptr++; - ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); - } - } - - /* Handle unlimited UTF-8 repeat */ - - else - { - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (IS_NEWLINE(eptr)) break; - if (md->partial != 0 && /* Take care with CRLF partial */ - eptr + 1 >= md->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - *eptr == NLBLOCK->nl[0]) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - eptr++; - ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); - } - } - break; - - case OP_ALLANY: - if (max < INT_MAX) - { - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - eptr++; - ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); - } - } - else - { - eptr = md->end_subject; /* Unlimited UTF-8 repeat */ - SCHECK_PARTIAL(); - } - break; - - /* The byte case is the same as non-UTF8 */ - - case OP_ANYBYTE: - c = max - min; - if (c > (unsigned int)(md->end_subject - eptr)) - { - eptr = md->end_subject; - SCHECK_PARTIAL(); - } - else eptr += c; - break; - - case OP_ANYNL: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(c, eptr, len); - if (c == 0x000d) - { - if (++eptr >= md->end_subject) break; - if (*eptr == 0x000a) eptr++; - } - else - { - if (c != 0x000a && - (md->bsr_anycrlf || - (c != 0x000b && c != 0x000c && - c != 0x0085 && c != 0x2028 && c != 0x2029))) - break; - eptr += len; - } - } - break; - - case OP_NOT_HSPACE: - case OP_HSPACE: - for (i = min; i < max; i++) - { - BOOL gotspace; - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(c, eptr, len); - switch(c) - { - default: gotspace = FALSE; break; - case 0x09: /* HT */ - case 0x20: /* SPACE */ - case 0xa0: /* NBSP */ - case 0x1680: /* OGHAM SPACE MARK */ - case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ - case 0x2000: /* EN QUAD */ - case 0x2001: /* EM QUAD */ - case 0x2002: /* EN SPACE */ - case 0x2003: /* EM SPACE */ - case 0x2004: /* THREE-PER-EM SPACE */ - case 0x2005: /* FOUR-PER-EM SPACE */ - case 0x2006: /* SIX-PER-EM SPACE */ - case 0x2007: /* FIGURE SPACE */ - case 0x2008: /* PUNCTUATION SPACE */ - case 0x2009: /* THIN SPACE */ - case 0x200A: /* HAIR SPACE */ - case 0x202f: /* NARROW NO-BREAK SPACE */ - case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ - case 0x3000: /* IDEOGRAPHIC SPACE */ - gotspace = TRUE; - break; - } - if (gotspace == (ctype == OP_NOT_HSPACE)) break; - eptr += len; - } - break; - - case OP_NOT_VSPACE: - case OP_VSPACE: - for (i = min; i < max; i++) - { - BOOL gotspace; - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(c, eptr, len); - switch(c) - { - default: gotspace = FALSE; break; - case 0x0a: /* LF */ - case 0x0b: /* VT */ - case 0x0c: /* FF */ - case 0x0d: /* CR */ - case 0x85: /* NEL */ - case 0x2028: /* LINE SEPARATOR */ - case 0x2029: /* PARAGRAPH SEPARATOR */ - gotspace = TRUE; - break; - } - if (gotspace == (ctype == OP_NOT_VSPACE)) break; - eptr += len; - } - break; - - case OP_NOT_DIGIT: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(c, eptr, len); - if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break; - eptr+= len; - } - break; - - case OP_DIGIT: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(c, eptr, len); - if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break; - eptr+= len; - } - break; - - case OP_NOT_WHITESPACE: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(c, eptr, len); - if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break; - eptr+= len; - } - break; - - case OP_WHITESPACE: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(c, eptr, len); - if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break; - eptr+= len; - } - break; - - case OP_NOT_WORDCHAR: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(c, eptr, len); - if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break; - eptr+= len; - } - break; - - case OP_WORDCHAR: - for (i = min; i < max; i++) - { - int len = 1; - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - GETCHARLEN(c, eptr, len); - if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break; - eptr+= len; - } - break; - - default: - RRETURN(PCRE_ERROR_INTERNAL); - } - - /* eptr is now past the end of the maximum run. If possessive, we are - done (no backing up). Otherwise, match at this position; anything other - than no match is immediately returned. For nomatch, back up one - character, unless we are matching \R and the last thing matched was - \r\n, in which case, back up two bytes. */ - - if (possessive) continue; - for(;;) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM46); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - if (eptr-- == pp) break; /* Stop if tried at original pos */ - BACKCHAR(eptr); - if (ctype == OP_ANYNL && eptr > pp && *eptr == '\n' && - eptr[-1] == '\r') eptr--; - } - } - else -#endif /* SUPPORT_UTF */ - /* Not UTF mode */ - { - switch(ctype) - { - case OP_ANY: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (IS_NEWLINE(eptr)) break; - if (md->partial != 0 && /* Take care with CRLF partial */ - eptr + 1 >= md->end_subject && - NLBLOCK->nltype == NLTYPE_FIXED && - NLBLOCK->nllen == 2 && - *eptr == NLBLOCK->nl[0]) - { - md->hitend = TRUE; - if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); - } - eptr++; - } - break; - - case OP_ALLANY: - case OP_ANYBYTE: - c = max - min; - if (c > (unsigned int)(md->end_subject - eptr)) - { - eptr = md->end_subject; - SCHECK_PARTIAL(); - } - else eptr += c; - break; - - case OP_ANYNL: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - c = *eptr; - if (c == 0x000d) - { - if (++eptr >= md->end_subject) break; - if (*eptr == 0x000a) eptr++; - } - else - { - if (c != 0x000a && (md->bsr_anycrlf || - (c != 0x000b && c != 0x000c && c != 0x0085 -#ifdef COMPILE_PCRE16 - && c != 0x2028 && c != 0x2029 -#endif - ))) break; - eptr++; - } - } - break; - - case OP_NOT_HSPACE: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - c = *eptr; - if (c == 0x09 || c == 0x20 || c == 0xa0 -#ifdef COMPILE_PCRE16 - || c == 0x1680 || c == 0x180e || (c >= 0x2000 && c <= 0x200A) - || c == 0x202f || c == 0x205f || c == 0x3000 -#endif - ) break; - eptr++; - } - break; - - case OP_HSPACE: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - c = *eptr; - if (c != 0x09 && c != 0x20 && c != 0xa0 -#ifdef COMPILE_PCRE16 - && c != 0x1680 && c != 0x180e && (c < 0x2000 || c > 0x200A) - && c != 0x202f && c != 0x205f && c != 0x3000 -#endif - ) break; - eptr++; - } - break; - - case OP_NOT_VSPACE: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - c = *eptr; - if (c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d || c == 0x85 -#ifdef COMPILE_PCRE16 - || c == 0x2028 || c == 0x2029 -#endif - ) break; - eptr++; - } - break; - - case OP_VSPACE: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - c = *eptr; - if (c != 0x0a && c != 0x0b && c != 0x0c && c != 0x0d && c != 0x85 -#ifdef COMPILE_PCRE16 - && c != 0x2028 && c != 0x2029 -#endif - ) break; - eptr++; - } - break; - - case OP_NOT_DIGIT: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0) break; - eptr++; - } - break; - - case OP_DIGIT: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0) break; - eptr++; - } - break; - - case OP_NOT_WHITESPACE: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0) break; - eptr++; - } - break; - - case OP_WHITESPACE: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0) break; - eptr++; - } - break; - - case OP_NOT_WORDCHAR: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0) break; - eptr++; - } - break; - - case OP_WORDCHAR: - for (i = min; i < max; i++) - { - if (eptr >= md->end_subject) - { - SCHECK_PARTIAL(); - break; - } - if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0) break; - eptr++; - } - break; - - default: - RRETURN(PCRE_ERROR_INTERNAL); - } - - /* eptr is now past the end of the maximum run. If possessive, we are - done (no backing up). Otherwise, match at this position; anything other - than no match is immediately returned. For nomatch, back up one - character (byte), unless we are matching \R and the last thing matched - was \r\n, in which case, back up two bytes. */ - - if (possessive) continue; - while (eptr >= pp) - { - RMATCH(eptr, ecode, offset_top, md, eptrb, RM47); - if (rrc != MATCH_NOMATCH) RRETURN(rrc); - eptr--; - if (ctype == OP_ANYNL && eptr > pp && *eptr == '\n' && - eptr[-1] == '\r') eptr--; - } - } - - /* Get here if we can't make it match with any permitted repetitions */ - - RRETURN(MATCH_NOMATCH); - } - /* Control never gets here */ - - /* There's been some horrible disaster. Arrival here can only mean there is - something seriously wrong in the code above or the OP_xxx definitions. */ - - default: - DPRINTF(("Unknown opcode %d\n", *ecode)); - RRETURN(PCRE_ERROR_UNKNOWN_OPCODE); - } - - /* Do not stick any code in here without much thought; it is assumed - that "continue" in the code above comes out to here to repeat the main - loop. */ - - } /* End of main loop */ -/* Control never reaches here */ - - -/* When compiling to use the heap rather than the stack for recursive calls to -match(), the RRETURN() macro jumps here. The number that is saved in -frame->Xwhere indicates which label we actually want to return to. */ - -#ifdef NO_RECURSE -#define LBL(val) case val: goto L_RM##val; -HEAP_RETURN: -switch (frame->Xwhere) - { - LBL( 1) LBL( 2) LBL( 3) LBL( 4) LBL( 5) LBL( 6) LBL( 7) LBL( 8) - LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17) - LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33) - LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52) - LBL(53) LBL(54) LBL(55) LBL(56) LBL(57) LBL(58) LBL(63) LBL(64) - LBL(65) LBL(66) -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - LBL(21) -#endif -#ifdef SUPPORT_UTF - LBL(16) LBL(18) LBL(20) - LBL(22) LBL(23) LBL(28) LBL(30) - LBL(32) LBL(34) LBL(42) LBL(46) -#ifdef SUPPORT_UCP - LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45) - LBL(59) LBL(60) LBL(61) LBL(62) -#endif /* SUPPORT_UCP */ -#endif /* SUPPORT_UTF */ - default: - DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere)); - -printf("+++jump error in pcre match: label %d non-existent\n", frame->Xwhere); - - return PCRE_ERROR_INTERNAL; - } -#undef LBL -#endif /* NO_RECURSE */ -} - - -/*************************************************************************** -**************************************************************************** - RECURSION IN THE match() FUNCTION - -Undefine all the macros that were defined above to handle this. */ - -#ifdef NO_RECURSE -#undef eptr -#undef ecode -#undef mstart -#undef offset_top -#undef eptrb -#undef flags - -#undef callpat -#undef charptr -#undef data -#undef next -#undef pp -#undef prev -#undef saved_eptr - -#undef new_recursive - -#undef cur_is_word -#undef condition -#undef prev_is_word - -#undef ctype -#undef length -#undef max -#undef min -#undef number -#undef offset -#undef op -#undef save_capture_last -#undef save_offset1 -#undef save_offset2 -#undef save_offset3 -#undef stacksave - -#undef newptrb - -#endif - -/* These two are defined as macros in both cases */ - -#undef fc -#undef fi - -/*************************************************************************** -***************************************************************************/ - - -#ifdef NO_RECURSE -/************************************************* -* Release allocated heap frames * -*************************************************/ - -/* This function releases all the allocated frames. The base frame is on the -machine stack, and so must not be freed. - -Argument: the address of the base frame -Returns: nothing -*/ - -static void -release_match_heapframes (heapframe *frame_base) -{ -heapframe *nextframe = frame_base->Xnextframe; -while (nextframe != NULL) - { - heapframe *oldframe = nextframe; - nextframe = nextframe->Xnextframe; - (PUBL(stack_free))(oldframe); - } -} -#endif - - -/************************************************* -* Execute a Regular Expression * -*************************************************/ - -/* This function applies a compiled re to a subject string and picks out -portions of the string if it matches. Two elements in the vector are set for -each substring: the offsets to the start and end of the substring. - -Arguments: - argument_re points to the compiled expression - extra_data points to extra data or is NULL - subject points to the subject string - length length of subject string (may contain binary zeros) - start_offset where to start in the subject string - options option bits - offsets points to a vector of ints to be filled in with offsets - offsetcount the number of elements in the vector - -Returns: > 0 => success; value is the number of elements filled in - = 0 => success, but offsets is not big enough - -1 => failed to match - < -1 => some kind of unexpected problem -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre_exec(const pcre *argument_re, const pcre_extra *extra_data, - PCRE_SPTR subject, int length, int start_offset, int options, int *offsets, - int offsetcount) -#else -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre16_exec(const pcre16 *argument_re, const pcre16_extra *extra_data, - PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets, - int offsetcount) -#endif -{ -int rc, ocount, arg_offset_max; -int newline; -BOOL using_temporary_offsets = FALSE; -BOOL anchored; -BOOL startline; -BOOL firstline; -BOOL utf; -BOOL has_first_char = FALSE; -BOOL has_req_char = FALSE; -pcre_uchar first_char = 0; -pcre_uchar first_char2 = 0; -pcre_uchar req_char = 0; -pcre_uchar req_char2 = 0; -match_data match_block; -match_data *md = &match_block; -const pcre_uint8 *tables; -const pcre_uint8 *start_bits = NULL; -PCRE_PUCHAR start_match = (PCRE_PUCHAR)subject + start_offset; -PCRE_PUCHAR end_subject; -PCRE_PUCHAR start_partial = NULL; -PCRE_PUCHAR req_char_ptr = start_match - 1; - -const pcre_study_data *study; -const REAL_PCRE *re = (const REAL_PCRE *)argument_re; - -#ifdef NO_RECURSE -heapframe frame_zero; -frame_zero.Xprevframe = NULL; /* Marks the top level */ -frame_zero.Xnextframe = NULL; /* None are allocated yet */ -md->match_frames_base = &frame_zero; -#endif - -/* Check for the special magic call that measures the size of the stack used -per recursive call of match(). Without the funny casting for sizeof, a Windows -compiler gave this error: "unary minus operator applied to unsigned type, -result still unsigned". Hopefully the cast fixes that. */ - -if (re == NULL && extra_data == NULL && subject == NULL && length == -999 && - start_offset == -999) -#ifdef NO_RECURSE - return -((int)sizeof(heapframe)); -#else - return match(NULL, NULL, NULL, 0, NULL, NULL, 0); -#endif - -/* Plausibility checks */ - -if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; -if (re == NULL || subject == NULL || (offsets == NULL && offsetcount > 0)) - return PCRE_ERROR_NULL; -if (offsetcount < 0) return PCRE_ERROR_BADCOUNT; -if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET; - -/* Check that the first field in the block is the magic number. If it is not, -return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to -REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which -means that the pattern is likely compiled with different endianness. */ - -if (re->magic_number != MAGIC_NUMBER) - return re->magic_number == REVERSED_MAGIC_NUMBER? - PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC; -if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; - -/* These two settings are used in the code for checking a UTF-8 string that -follows immediately afterwards. Other values in the md block are used only -during "normal" pcre_exec() processing, not when the JIT support is in use, -so they are set up later. */ - -/* PCRE_UTF16 has the same value as PCRE_UTF8. */ -utf = md->utf = (re->options & PCRE_UTF8) != 0; -md->partial = ((options & PCRE_PARTIAL_HARD) != 0)? 2 : - ((options & PCRE_PARTIAL_SOFT) != 0)? 1 : 0; - -/* Check a UTF-8 string if required. Pass back the character offset and error -code for an invalid string if a results vector is available. */ - -#ifdef SUPPORT_UTF -if (utf && (options & PCRE_NO_UTF8_CHECK) == 0) - { - int erroroffset; - int errorcode = PRIV(valid_utf)((PCRE_PUCHAR)subject, length, &erroroffset); - if (errorcode != 0) - { - if (offsetcount >= 2) - { - offsets[0] = erroroffset; - offsets[1] = errorcode; - } -#ifdef COMPILE_PCRE16 - return (errorcode <= PCRE_UTF16_ERR1 && md->partial > 1)? - PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16; -#else - return (errorcode <= PCRE_UTF8_ERR5 && md->partial > 1)? - PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8; -#endif - } - - /* Check that a start_offset points to the start of a UTF character. */ - if (start_offset > 0 && start_offset < length && - NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset])) - return PCRE_ERROR_BADUTF8_OFFSET; - } -#endif - -/* If the pattern was successfully studied with JIT support, run the JIT -executable instead of the rest of this function. Most options must be set at -compile time for the JIT code to be usable. Fallback to the normal code path if -an unsupported flag is set. */ - -#ifdef SUPPORT_JIT -if (extra_data != NULL - && (extra_data->flags & (PCRE_EXTRA_EXECUTABLE_JIT | - PCRE_EXTRA_TABLES)) == PCRE_EXTRA_EXECUTABLE_JIT - && extra_data->executable_jit != NULL - && (options & ~(PCRE_NO_UTF8_CHECK | PCRE_NOTBOL | PCRE_NOTEOL | - PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART | - PCRE_PARTIAL_SOFT | PCRE_PARTIAL_HARD)) == 0) - { - rc = PRIV(jit_exec)(re, extra_data, (const pcre_uchar *)subject, length, - start_offset, options, offsets, offsetcount); - - /* PCRE_ERROR_NULL means that the selected normal or partial matching - mode is not compiled. In this case we simply fallback to interpreter. */ - - if (rc != PCRE_ERROR_NULL) return rc; - } -#endif - -/* Carry on with non-JIT matching. This information is for finding all the -numbers associated with a given name, for condition testing. */ - -md->name_table = (pcre_uchar *)re + re->name_table_offset; -md->name_count = re->name_count; -md->name_entry_size = re->name_entry_size; - -/* Fish out the optional data from the extra_data structure, first setting -the default values. */ - -study = NULL; -md->match_limit = MATCH_LIMIT; -md->match_limit_recursion = MATCH_LIMIT_RECURSION; -md->callout_data = NULL; - -/* The table pointer is always in native byte order. */ - -tables = re->tables; - -if (extra_data != NULL) - { - unsigned int flags = extra_data->flags; - if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) - study = (const pcre_study_data *)extra_data->study_data; - if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) - md->match_limit = extra_data->match_limit; - if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0) - md->match_limit_recursion = extra_data->match_limit_recursion; - if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0) - md->callout_data = extra_data->callout_data; - if ((flags & PCRE_EXTRA_TABLES) != 0) tables = extra_data->tables; - } - -/* If the exec call supplied NULL for tables, use the inbuilt ones. This -is a feature that makes it possible to save compiled regex and re-use them -in other programs later. */ - -if (tables == NULL) tables = PRIV(default_tables); - -/* Set up other data */ - -anchored = ((re->options | options) & PCRE_ANCHORED) != 0; -startline = (re->flags & PCRE_STARTLINE) != 0; -firstline = (re->options & PCRE_FIRSTLINE) != 0; - -/* The code starts after the real_pcre block and the capture name table. */ - -md->start_code = (const pcre_uchar *)re + re->name_table_offset + - re->name_count * re->name_entry_size; - -md->start_subject = (PCRE_PUCHAR)subject; -md->start_offset = start_offset; -md->end_subject = md->start_subject + length; -end_subject = md->end_subject; - -md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; -md->use_ucp = (re->options & PCRE_UCP) != 0; -md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0; -md->ignore_skip_arg = FALSE; - -/* Some options are unpacked into BOOL variables in the hope that testing -them will be faster than individual option bits. */ - -md->notbol = (options & PCRE_NOTBOL) != 0; -md->noteol = (options & PCRE_NOTEOL) != 0; -md->notempty = (options & PCRE_NOTEMPTY) != 0; -md->notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0; - -md->hitend = FALSE; -md->mark = md->nomatch_mark = NULL; /* In case never set */ - -md->recursive = NULL; /* No recursion at top level */ -md->hasthen = (re->flags & PCRE_HASTHEN) != 0; - -md->lcc = tables + lcc_offset; -md->fcc = tables + fcc_offset; -md->ctypes = tables + ctypes_offset; - -/* Handle different \R options. */ - -switch (options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) - { - case 0: - if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0) - md->bsr_anycrlf = (re->options & PCRE_BSR_ANYCRLF) != 0; - else -#ifdef BSR_ANYCRLF - md->bsr_anycrlf = TRUE; -#else - md->bsr_anycrlf = FALSE; -#endif - break; - - case PCRE_BSR_ANYCRLF: - md->bsr_anycrlf = TRUE; - break; - - case PCRE_BSR_UNICODE: - md->bsr_anycrlf = FALSE; - break; - - default: return PCRE_ERROR_BADNEWLINE; - } - -/* Handle different types of newline. The three bits give eight cases. If -nothing is set at run time, whatever was used at compile time applies. */ - -switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : - (pcre_uint32)options) & PCRE_NEWLINE_BITS) - { - case 0: newline = NEWLINE; break; /* Compile-time default */ - case PCRE_NEWLINE_CR: newline = CHAR_CR; break; - case PCRE_NEWLINE_LF: newline = CHAR_NL; break; - case PCRE_NEWLINE_CR+ - PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break; - case PCRE_NEWLINE_ANY: newline = -1; break; - case PCRE_NEWLINE_ANYCRLF: newline = -2; break; - default: return PCRE_ERROR_BADNEWLINE; - } - -if (newline == -2) - { - md->nltype = NLTYPE_ANYCRLF; - } -else if (newline < 0) - { - md->nltype = NLTYPE_ANY; - } -else - { - md->nltype = NLTYPE_FIXED; - if (newline > 255) - { - md->nllen = 2; - md->nl[0] = (newline >> 8) & 255; - md->nl[1] = newline & 255; - } - else - { - md->nllen = 1; - md->nl[0] = newline; - } - } - -/* Partial matching was originally supported only for a restricted set of -regexes; from release 8.00 there are no restrictions, but the bits are still -defined (though never set). So there's no harm in leaving this code. */ - -if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0) - return PCRE_ERROR_BADPARTIAL; - -/* If the expression has got more back references than the offsets supplied can -hold, we get a temporary chunk of working store to use during the matching. -Otherwise, we can use the vector supplied, rounding down its size to a multiple -of 3. */ - -ocount = offsetcount - (offsetcount % 3); -arg_offset_max = (2*ocount)/3; - -if (re->top_backref > 0 && re->top_backref >= ocount/3) - { - ocount = re->top_backref * 3 + 3; - md->offset_vector = (int *)(PUBL(malloc))(ocount * sizeof(int)); - if (md->offset_vector == NULL) return PCRE_ERROR_NOMEMORY; - using_temporary_offsets = TRUE; - DPRINTF(("Got memory to hold back references\n")); - } -else md->offset_vector = offsets; - -md->offset_end = ocount; -md->offset_max = (2*ocount)/3; -md->offset_overflow = FALSE; -md->capture_last = -1; - -/* Reset the working variable associated with each extraction. These should -never be used unless previously set, but they get saved and restored, and so we -initialize them to avoid reading uninitialized locations. Also, unset the -offsets for the matched string. This is really just for tidiness with callouts, -in case they inspect these fields. */ - -if (md->offset_vector != NULL) - { - int *iptr = md->offset_vector + ocount; - int *iend = iptr - re->top_bracket; - if (iend < md->offset_vector + 2) iend = md->offset_vector + 2; - while (--iptr >= iend) *iptr = -1; - md->offset_vector[0] = md->offset_vector[1] = -1; - } - -/* Set up the first character to match, if available. The first_char value is -never set for an anchored regular expression, but the anchoring may be forced -at run time, so we have to test for anchoring. The first char may be unset for -an unanchored pattern, of course. If there's no first char and the pattern was -studied, there may be a bitmap of possible first characters. */ - -if (!anchored) - { - if ((re->flags & PCRE_FIRSTSET) != 0) - { - has_first_char = TRUE; - first_char = first_char2 = (pcre_uchar)(re->first_char); - if ((re->flags & PCRE_FCH_CASELESS) != 0) - { - first_char2 = TABLE_GET(first_char, md->fcc, first_char); -#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) - if (utf && first_char > 127) - first_char2 = UCD_OTHERCASE(first_char); -#endif - } - } - else - if (!startline && study != NULL && - (study->flags & PCRE_STUDY_MAPPED) != 0) - start_bits = study->start_bits; - } - -/* For anchored or unanchored matches, there may be a "last known required -character" set. */ - -if ((re->flags & PCRE_REQCHSET) != 0) - { - has_req_char = TRUE; - req_char = req_char2 = (pcre_uchar)(re->req_char); - if ((re->flags & PCRE_RCH_CASELESS) != 0) - { - req_char2 = TABLE_GET(req_char, md->fcc, req_char); -#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) - if (utf && req_char > 127) - req_char2 = UCD_OTHERCASE(req_char); -#endif - } - } - - -/* ==========================================================================*/ - -/* Loop for handling unanchored repeated matching attempts; for anchored regexs -the loop runs just once. */ - -for(;;) - { - PCRE_PUCHAR save_end_subject = end_subject; - PCRE_PUCHAR new_start_match; - - /* If firstline is TRUE, the start of the match is constrained to the first - line of a multiline string. That is, the match must be before or at the first - newline. Implement this by temporarily adjusting end_subject so that we stop - scanning at a newline. If the match fails at the newline, later code breaks - this loop. */ - - if (firstline) - { - PCRE_PUCHAR t = start_match; -#ifdef SUPPORT_UTF - if (utf) - { - while (t < md->end_subject && !IS_NEWLINE(t)) - { - t++; - ACROSSCHAR(t < end_subject, *t, t++); - } - } - else -#endif - while (t < md->end_subject && !IS_NEWLINE(t)) t++; - end_subject = t; - } - - /* There are some optimizations that avoid running the match if a known - starting point is not found, or if a known later character is not present. - However, there is an option that disables these, for testing and for ensuring - that all callouts do actually occur. The option can be set in the regex by - (*NO_START_OPT) or passed in match-time options. */ - - if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0) - { - /* Advance to a unique first char if there is one. */ - - if (has_first_char) - { - if (first_char != first_char2) - while (start_match < end_subject && - *start_match != first_char && *start_match != first_char2) - start_match++; - else - while (start_match < end_subject && *start_match != first_char) - start_match++; - } - - /* Or to just after a linebreak for a multiline match */ - - else if (startline) - { - if (start_match > md->start_subject + start_offset) - { -#ifdef SUPPORT_UTF - if (utf) - { - while (start_match < end_subject && !WAS_NEWLINE(start_match)) - { - start_match++; - ACROSSCHAR(start_match < end_subject, *start_match, - start_match++); - } - } - else -#endif - while (start_match < end_subject && !WAS_NEWLINE(start_match)) - start_match++; - - /* If we have just passed a CR and the newline option is ANY or ANYCRLF, - and we are now at a LF, advance the match position by one more character. - */ - - if (start_match[-1] == CHAR_CR && - (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) && - start_match < end_subject && - *start_match == CHAR_NL) - start_match++; - } - } - - /* Or to a non-unique first byte after study */ - - else if (start_bits != NULL) - { - while (start_match < end_subject) - { - unsigned int c = *start_match; -#ifndef COMPILE_PCRE8 - if (c > 255) c = 255; -#endif - if ((start_bits[c/8] & (1 << (c&7))) == 0) - { - start_match++; -#if defined SUPPORT_UTF && defined COMPILE_PCRE8 - /* In non 8-bit mode, the iteration will stop for - characters > 255 at the beginning or not stop at all. */ - if (utf) - ACROSSCHAR(start_match < end_subject, *start_match, - start_match++); -#endif - } - else break; - } - } - } /* Starting optimizations */ - - /* Restore fudged end_subject */ - - end_subject = save_end_subject; - - /* The following two optimizations are disabled for partial matching or if - disabling is explicitly requested. */ - - if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 && !md->partial) - { - /* If the pattern was studied, a minimum subject length may be set. This is - a lower bound; no actual string of that length may actually match the - pattern. Although the value is, strictly, in characters, we treat it as - bytes to avoid spending too much time in this optimization. */ - - if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 && - (pcre_uint32)(end_subject - start_match) < study->minlength) - { - rc = MATCH_NOMATCH; - break; - } - - /* If req_char is set, we know that that character must appear in the - subject for the match to succeed. If the first character is set, req_char - must be later in the subject; otherwise the test starts at the match point. - This optimization can save a huge amount of backtracking in patterns with - nested unlimited repeats that aren't going to match. Writing separate code - for cased/caseless versions makes it go faster, as does using an - autoincrement and backing off on a match. - - HOWEVER: when the subject string is very, very long, searching to its end - can take a long time, and give bad performance on quite ordinary patterns. - This showed up when somebody was matching something like /^\d+C/ on a - 32-megabyte string... so we don't do this when the string is sufficiently - long. */ - - if (has_req_char && end_subject - start_match < REQ_BYTE_MAX) - { - PCRE_PUCHAR p = start_match + (has_first_char? 1:0); - - /* We don't need to repeat the search if we haven't yet reached the - place we found it at last time. */ - - if (p > req_char_ptr) - { - if (req_char != req_char2) - { - while (p < end_subject) - { - int pp = *p++; - if (pp == req_char || pp == req_char2) { p--; break; } - } - } - else - { - while (p < end_subject) - { - if (*p++ == req_char) { p--; break; } - } - } - - /* If we can't find the required character, break the matching loop, - forcing a match failure. */ - - if (p >= end_subject) - { - rc = MATCH_NOMATCH; - break; - } - - /* If we have found the required character, save the point where we - found it, so that we don't search again next time round the loop if - the start hasn't passed this character yet. */ - - req_char_ptr = p; - } - } - } - -#ifdef PCRE_DEBUG /* Sigh. Some compilers never learn. */ - printf(">>>> Match against: "); - pchars(start_match, end_subject - start_match, TRUE, md); - printf("\n"); -#endif - - /* OK, we can now run the match. If "hitend" is set afterwards, remember the - first starting point for which a partial match was found. */ - - md->start_match_ptr = start_match; - md->start_used_ptr = start_match; - md->match_call_count = 0; - md->match_function_type = 0; - md->end_offset_top = 0; - rc = match(start_match, md->start_code, start_match, 2, md, NULL, 0); - if (md->hitend && start_partial == NULL) start_partial = md->start_used_ptr; - - switch(rc) - { - /* If MATCH_SKIP_ARG reaches this level it means that a MARK that matched - the SKIP's arg was not found. In this circumstance, Perl ignores the SKIP - entirely. The only way we can do that is to re-do the match at the same - point, with a flag to force SKIP with an argument to be ignored. Just - treating this case as NOMATCH does not work because it does not check other - alternatives in patterns such as A(*SKIP:A)B|AC when the subject is AC. */ - - case MATCH_SKIP_ARG: - new_start_match = start_match; - md->ignore_skip_arg = TRUE; - break; - - /* SKIP passes back the next starting point explicitly, but if it is the - same as the match we have just done, treat it as NOMATCH. */ - - case MATCH_SKIP: - if (md->start_match_ptr != start_match) - { - new_start_match = md->start_match_ptr; - break; - } - /* Fall through */ - - /* NOMATCH and PRUNE advance by one character. THEN at this level acts - exactly like PRUNE. Unset the ignore SKIP-with-argument flag. */ - - case MATCH_NOMATCH: - case MATCH_PRUNE: - case MATCH_THEN: - md->ignore_skip_arg = FALSE; - new_start_match = start_match + 1; -#ifdef SUPPORT_UTF - if (utf) - ACROSSCHAR(new_start_match < end_subject, *new_start_match, - new_start_match++); -#endif - break; - - /* COMMIT disables the bumpalong, but otherwise behaves as NOMATCH. */ - - case MATCH_COMMIT: - rc = MATCH_NOMATCH; - goto ENDLOOP; - - /* Any other return is either a match, or some kind of error. */ - - default: - goto ENDLOOP; - } - - /* Control reaches here for the various types of "no match at this point" - result. Reset the code to MATCH_NOMATCH for subsequent checking. */ - - rc = MATCH_NOMATCH; - - /* If PCRE_FIRSTLINE is set, the match must happen before or at the first - newline in the subject (though it may continue over the newline). Therefore, - if we have just failed to match, starting at a newline, do not continue. */ - - if (firstline && IS_NEWLINE(start_match)) break; - - /* Advance to new matching position */ - - start_match = new_start_match; - - /* Break the loop if the pattern is anchored or if we have passed the end of - the subject. */ - - if (anchored || start_match > end_subject) break; - - /* If we have just passed a CR and we are now at a LF, and the pattern does - not contain any explicit matches for \r or \n, and the newline option is CRLF - or ANY or ANYCRLF, advance the match position by one more character. In - normal matching start_match will aways be greater than the first position at - this stage, but a failed *SKIP can cause a return at the same point, which is - why the first test exists. */ - - if (start_match > (PCRE_PUCHAR)subject + start_offset && - start_match[-1] == CHAR_CR && - start_match < end_subject && - *start_match == CHAR_NL && - (re->flags & PCRE_HASCRORLF) == 0 && - (md->nltype == NLTYPE_ANY || - md->nltype == NLTYPE_ANYCRLF || - md->nllen == 2)) - start_match++; - - md->mark = NULL; /* Reset for start of next match attempt */ - } /* End of for(;;) "bumpalong" loop */ - -/* ==========================================================================*/ - -/* We reach here when rc is not MATCH_NOMATCH, or if one of the stopping -conditions is true: - -(1) The pattern is anchored or the match was failed by (*COMMIT); - -(2) We are past the end of the subject; - -(3) PCRE_FIRSTLINE is set and we have failed to match at a newline, because - this option requests that a match occur at or before the first newline in - the subject. - -When we have a match and the offset vector is big enough to deal with any -backreferences, captured substring offsets will already be set up. In the case -where we had to get some local store to hold offsets for backreference -processing, copy those that we can. In this case there need not be overflow if -certain parts of the pattern were not used, even though there are more -capturing parentheses than vector slots. */ - -ENDLOOP: - -if (rc == MATCH_MATCH || rc == MATCH_ACCEPT) - { - if (using_temporary_offsets) - { - if (arg_offset_max >= 4) - { - memcpy(offsets + 2, md->offset_vector + 2, - (arg_offset_max - 2) * sizeof(int)); - DPRINTF(("Copied offsets from temporary memory\n")); - } - if (md->end_offset_top > arg_offset_max) md->offset_overflow = TRUE; - DPRINTF(("Freeing temporary memory\n")); - (PUBL(free))(md->offset_vector); - } - - /* Set the return code to the number of captured strings, or 0 if there were - too many to fit into the vector. */ - - rc = (md->offset_overflow && md->end_offset_top >= arg_offset_max)? - 0 : md->end_offset_top/2; - - /* If there is space in the offset vector, set any unused pairs at the end of - the pattern to -1 for backwards compatibility. It is documented that this - happens. In earlier versions, the whole set of potential capturing offsets - was set to -1 each time round the loop, but this is handled differently now. - "Gaps" are set to -1 dynamically instead (this fixes a bug). Thus, it is only - those at the end that need unsetting here. We can't just unset them all at - the start of the whole thing because they may get set in one branch that is - not the final matching branch. */ - - if (md->end_offset_top/2 <= re->top_bracket && offsets != NULL) - { - int *iptr, *iend; - int resetcount = 2 + re->top_bracket * 2; - if (resetcount > offsetcount) resetcount = offsetcount; - iptr = offsets + md->end_offset_top; - iend = offsets + resetcount; - while (iptr < iend) *iptr++ = -1; - } - - /* If there is space, set up the whole thing as substring 0. The value of - md->start_match_ptr might be modified if \K was encountered on the success - matching path. */ - - if (offsetcount < 2) rc = 0; else - { - offsets[0] = (int)(md->start_match_ptr - md->start_subject); - offsets[1] = (int)(md->end_match_ptr - md->start_subject); - } - - /* Return MARK data if requested */ - - if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0) - *(extra_data->mark) = (pcre_uchar *)md->mark; - DPRINTF((">>>> returning %d\n", rc)); -#ifdef NO_RECURSE - release_match_heapframes(&frame_zero); -#endif - return rc; - } - -/* Control gets here if there has been an error, or if the overall match -attempt has failed at all permitted starting positions. */ - -if (using_temporary_offsets) - { - DPRINTF(("Freeing temporary memory\n")); - (PUBL(free))(md->offset_vector); - } - -/* For anything other than nomatch or partial match, just return the code. */ - -if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL) - { - DPRINTF((">>>> error: returning %d\n", rc)); -#ifdef NO_RECURSE - release_match_heapframes(&frame_zero); -#endif - return rc; - } - -/* Handle partial matches - disable any mark data */ - -if (start_partial != NULL) - { - DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n")); - md->mark = NULL; - if (offsetcount > 1) - { - offsets[0] = (int)(start_partial - (PCRE_PUCHAR)subject); - offsets[1] = (int)(end_subject - (PCRE_PUCHAR)subject); - } - rc = PCRE_ERROR_PARTIAL; - } - -/* This is the classic nomatch case */ - -else - { - DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n")); - rc = PCRE_ERROR_NOMATCH; - } - -/* Return the MARK data if it has been requested. */ - -if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0) - *(extra_data->mark) = (pcre_uchar *)md->nomatch_mark; -#ifdef NO_RECURSE - release_match_heapframes(&frame_zero); -#endif -return rc; -} - -/* End of pcre_exec.c */ diff --git a/glib/pcre/pcre_fullinfo.c b/glib/pcre/pcre_fullinfo.c deleted file mode 100644 index 2fe785a13..000000000 --- a/glib/pcre/pcre_fullinfo.c +++ /dev/null @@ -1,204 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains the external function pcre_fullinfo(), which returns -information about a compiled pattern. */ - - -#include "config.h" - -#include "pcre_internal.h" - - -/************************************************* -* Return info about compiled pattern * -*************************************************/ - -/* This is a newer "info" function which has an extensible interface so -that additional items can be added compatibly. - -Arguments: - argument_re points to compiled code - extra_data points extra data, or NULL - what what information is required - where where to put the information - -Returns: 0 if data returned, negative on error -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data, - int what, void *where) -#else -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre16_fullinfo(const pcre16 *argument_re, const pcre16_extra *extra_data, - int what, void *where) -#endif -{ -const REAL_PCRE *re = (const REAL_PCRE *)argument_re; -const pcre_study_data *study = NULL; - -if (re == NULL || where == NULL) return PCRE_ERROR_NULL; - -if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0) - study = (const pcre_study_data *)extra_data->study_data; - -/* Check that the first field in the block is the magic number. If it is not, -return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to -REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which -means that the pattern is likely compiled with different endianness. */ - -if (re->magic_number != MAGIC_NUMBER) - return re->magic_number == REVERSED_MAGIC_NUMBER? - PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC; - -/* Check that this pattern was compiled in the correct bit mode */ - -if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; - -switch (what) - { - case PCRE_INFO_OPTIONS: - *((unsigned long int *)where) = re->options & PUBLIC_COMPILE_OPTIONS; - break; - - case PCRE_INFO_SIZE: - *((size_t *)where) = re->size; - break; - - case PCRE_INFO_STUDYSIZE: - *((size_t *)where) = (study == NULL)? 0 : study->size; - break; - - case PCRE_INFO_JITSIZE: -#ifdef SUPPORT_JIT - *((size_t *)where) = - (extra_data != NULL && - (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && - extra_data->executable_jit != NULL)? - PRIV(jit_get_size)(extra_data->executable_jit) : 0; -#else - *((size_t *)where) = 0; -#endif - break; - - case PCRE_INFO_CAPTURECOUNT: - *((int *)where) = re->top_bracket; - break; - - case PCRE_INFO_BACKREFMAX: - *((int *)where) = re->top_backref; - break; - - case PCRE_INFO_FIRSTBYTE: - *((int *)where) = - ((re->flags & PCRE_FIRSTSET) != 0)? re->first_char : - ((re->flags & PCRE_STARTLINE) != 0)? -1 : -2; - break; - - /* Make sure we pass back the pointer to the bit vector in the external - block, not the internal copy (with flipped integer fields). */ - - case PCRE_INFO_FIRSTTABLE: - *((const pcre_uint8 **)where) = - (study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)? - ((const pcre_study_data *)extra_data->study_data)->start_bits : NULL; - break; - - case PCRE_INFO_MINLENGTH: - *((int *)where) = - (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0)? - (int)(study->minlength) : -1; - break; - - case PCRE_INFO_JIT: - *((int *)where) = extra_data != NULL && - (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && - extra_data->executable_jit != NULL; - break; - - case PCRE_INFO_LASTLITERAL: - *((int *)where) = - ((re->flags & PCRE_REQCHSET) != 0)? re->req_char : -1; - break; - - case PCRE_INFO_NAMEENTRYSIZE: - *((int *)where) = re->name_entry_size; - break; - - case PCRE_INFO_NAMECOUNT: - *((int *)where) = re->name_count; - break; - - case PCRE_INFO_NAMETABLE: - *((const pcre_uchar **)where) = (const pcre_uchar *)re + re->name_table_offset; - break; - - case PCRE_INFO_DEFAULT_TABLES: - *((const pcre_uint8 **)where) = (const pcre_uint8 *)(PRIV(default_tables)); - break; - - /* From release 8.00 this will always return TRUE because NOPARTIAL is - no longer ever set (the restrictions have been removed). */ - - case PCRE_INFO_OKPARTIAL: - *((int *)where) = (re->flags & PCRE_NOPARTIAL) == 0; - break; - - case PCRE_INFO_JCHANGED: - *((int *)where) = (re->flags & PCRE_JCHANGED) != 0; - break; - - case PCRE_INFO_HASCRORLF: - *((int *)where) = (re->flags & PCRE_HASCRORLF) != 0; - break; - - case PCRE_INFO_MAXLOOKBEHIND: - *((int *)where) = re->max_lookbehind; - break; - - default: return PCRE_ERROR_BADOPTION; - } - -return 0; -} - -/* End of pcre_fullinfo.c */ diff --git a/glib/pcre/pcre_get.c b/glib/pcre/pcre_get.c deleted file mode 100644 index 61147efe8..000000000 --- a/glib/pcre/pcre_get.c +++ /dev/null @@ -1,585 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains some convenience functions for extracting substrings -from the subject string after a regex match has succeeded. The original idea -for these functions came from Scott Wimer. */ - - -#include "config.h" - -#include "pcre_internal.h" - - -/************************************************* -* Find number for named string * -*************************************************/ - -/* This function is used by the get_first_set() function below, as well -as being generally available. It assumes that names are unique. - -Arguments: - code the compiled regex - stringname the name whose number is required - -Returns: the number of the named parentheses, or a negative number - (PCRE_ERROR_NOSUBSTRING) if not found -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre_get_stringnumber(const pcre *code, const char *stringname) -#else -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre16_get_stringnumber(const pcre16 *code, PCRE_SPTR16 stringname) -#endif -{ -int rc; -int entrysize; -int top, bot; -pcre_uchar *nametable; - -#ifdef COMPILE_PCRE8 -if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) - return rc; -if (top <= 0) return PCRE_ERROR_NOSUBSTRING; - -if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) - return rc; -if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) - return rc; -#endif -#ifdef COMPILE_PCRE16 -if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) - return rc; -if (top <= 0) return PCRE_ERROR_NOSUBSTRING; - -if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) - return rc; -if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) - return rc; -#endif - -bot = 0; -while (top > bot) - { - int mid = (top + bot) / 2; - pcre_uchar *entry = nametable + entrysize*mid; - int c = STRCMP_UC_UC((pcre_uchar *)stringname, - (pcre_uchar *)(entry + IMM2_SIZE)); - if (c == 0) return GET2(entry, 0); - if (c > 0) bot = mid + 1; else top = mid; - } - -return PCRE_ERROR_NOSUBSTRING; -} - - - -/************************************************* -* Find (multiple) entries for named string * -*************************************************/ - -/* This is used by the get_first_set() function below, as well as being -generally available. It is used when duplicated names are permitted. - -Arguments: - code the compiled regex - stringname the name whose entries required - firstptr where to put the pointer to the first entry - lastptr where to put the pointer to the last entry - -Returns: the length of each entry, or a negative number - (PCRE_ERROR_NOSUBSTRING) if not found -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre_get_stringtable_entries(const pcre *code, const char *stringname, - char **firstptr, char **lastptr) -#else -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 stringname, - PCRE_UCHAR16 **firstptr, PCRE_UCHAR16 **lastptr) -#endif -{ -int rc; -int entrysize; -int top, bot; -pcre_uchar *nametable, *lastentry; - -#ifdef COMPILE_PCRE8 -if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) - return rc; -if (top <= 0) return PCRE_ERROR_NOSUBSTRING; - -if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) - return rc; -if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) - return rc; -#endif -#ifdef COMPILE_PCRE16 -if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) - return rc; -if (top <= 0) return PCRE_ERROR_NOSUBSTRING; - -if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) - return rc; -if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) - return rc; -#endif - -lastentry = nametable + entrysize * (top - 1); -bot = 0; -while (top > bot) - { - int mid = (top + bot) / 2; - pcre_uchar *entry = nametable + entrysize*mid; - int c = STRCMP_UC_UC((pcre_uchar *)stringname, - (pcre_uchar *)(entry + IMM2_SIZE)); - if (c == 0) - { - pcre_uchar *first = entry; - pcre_uchar *last = entry; - while (first > nametable) - { - if (STRCMP_UC_UC((pcre_uchar *)stringname, - (pcre_uchar *)(first - entrysize + IMM2_SIZE)) != 0) break; - first -= entrysize; - } - while (last < lastentry) - { - if (STRCMP_UC_UC((pcre_uchar *)stringname, - (pcre_uchar *)(last + entrysize + IMM2_SIZE)) != 0) break; - last += entrysize; - } -#ifdef COMPILE_PCRE8 - *firstptr = (char *)first; - *lastptr = (char *)last; -#else - *firstptr = (PCRE_UCHAR16 *)first; - *lastptr = (PCRE_UCHAR16 *)last; -#endif - return entrysize; - } - if (c > 0) bot = mid + 1; else top = mid; - } - -return PCRE_ERROR_NOSUBSTRING; -} - - - -/************************************************* -* Find first set of multiple named strings * -*************************************************/ - -/* This function allows for duplicate names in the table of named substrings. -It returns the number of the first one that was set in a pattern match. - -Arguments: - code the compiled regex - stringname the name of the capturing substring - ovector the vector of matched substrings - -Returns: the number of the first that is set, - or the number of the last one if none are set, - or a negative number on error -*/ - -#ifdef COMPILE_PCRE8 -static int -get_first_set(const pcre *code, const char *stringname, int *ovector) -#else -static int -get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector) -#endif -{ -const REAL_PCRE *re = (const REAL_PCRE *)code; -int entrysize; -pcre_uchar *entry; -#ifdef COMPILE_PCRE8 -char *first, *last; -#else -PCRE_UCHAR16 *first, *last; -#endif - -#ifdef COMPILE_PCRE8 -if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0) - return pcre_get_stringnumber(code, stringname); -entrysize = pcre_get_stringtable_entries(code, stringname, &first, &last); -#else -if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0) - return pcre16_get_stringnumber(code, stringname); -entrysize = pcre16_get_stringtable_entries(code, stringname, &first, &last); -#endif -if (entrysize <= 0) return entrysize; -for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize) - { - int n = GET2(entry, 0); - if (ovector[n*2] >= 0) return n; - } -return GET2(entry, 0); -} - - - - -/************************************************* -* Copy captured string to given buffer * -*************************************************/ - -/* This function copies a single captured substring into a given buffer. -Note that we use memcpy() rather than strncpy() in case there are binary zeros -in the string. - -Arguments: - subject the subject string that was matched - ovector pointer to the offsets table - stringcount the number of substrings that were captured - (i.e. the yield of the pcre_exec call, unless - that was zero, in which case it should be 1/3 - of the offset table size) - stringnumber the number of the required substring - buffer where to put the substring - size the size of the buffer - -Returns: if successful: - the length of the copied string, not including the zero - that is put on the end; can be zero - if not successful: - PCRE_ERROR_NOMEMORY (-6) buffer too small - PCRE_ERROR_NOSUBSTRING (-7) no such captured substring -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre_copy_substring(const char *subject, int *ovector, int stringcount, - int stringnumber, char *buffer, int size) -#else -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, - int stringnumber, PCRE_UCHAR16 *buffer, int size) -#endif -{ -int yield; -if (stringnumber < 0 || stringnumber >= stringcount) - return PCRE_ERROR_NOSUBSTRING; -stringnumber *= 2; -yield = ovector[stringnumber+1] - ovector[stringnumber]; -if (size < yield + 1) return PCRE_ERROR_NOMEMORY; -memcpy(buffer, subject + ovector[stringnumber], IN_UCHARS(yield)); -buffer[yield] = 0; -return yield; -} - - - -/************************************************* -* Copy named captured string to given buffer * -*************************************************/ - -/* This function copies a single captured substring into a given buffer, -identifying it by name. If the regex permits duplicate names, the first -substring that is set is chosen. - -Arguments: - code the compiled regex - subject the subject string that was matched - ovector pointer to the offsets table - stringcount the number of substrings that were captured - (i.e. the yield of the pcre_exec call, unless - that was zero, in which case it should be 1/3 - of the offset table size) - stringname the name of the required substring - buffer where to put the substring - size the size of the buffer - -Returns: if successful: - the length of the copied string, not including the zero - that is put on the end; can be zero - if not successful: - PCRE_ERROR_NOMEMORY (-6) buffer too small - PCRE_ERROR_NOSUBSTRING (-7) no such captured substring -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre_copy_named_substring(const pcre *code, const char *subject, - int *ovector, int stringcount, const char *stringname, - char *buffer, int size) -#else -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre16_copy_named_substring(const pcre16 *code, PCRE_SPTR16 subject, - int *ovector, int stringcount, PCRE_SPTR16 stringname, - PCRE_UCHAR16 *buffer, int size) -#endif -{ -int n = get_first_set(code, stringname, ovector); -if (n <= 0) return n; -#ifdef COMPILE_PCRE8 -return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size); -#else -return pcre16_copy_substring(subject, ovector, stringcount, n, buffer, size); -#endif -} - - - -/************************************************* -* Copy all captured strings to new store * -*************************************************/ - -/* This function gets one chunk of store and builds a list of pointers and all -of the captured substrings in it. A NULL pointer is put on the end of the list. - -Arguments: - subject the subject string that was matched - ovector pointer to the offsets table - stringcount the number of substrings that were captured - (i.e. the yield of the pcre_exec call, unless - that was zero, in which case it should be 1/3 - of the offset table size) - listptr set to point to the list of pointers - -Returns: if successful: 0 - if not successful: - PCRE_ERROR_NOMEMORY (-6) failed to get store -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre_get_substring_list(const char *subject, int *ovector, int stringcount, - const char ***listptr) -#else -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount, - PCRE_SPTR16 **listptr) -#endif -{ -int i; -int size = sizeof(pcre_uchar *); -int double_count = stringcount * 2; -pcre_uchar **stringlist; -pcre_uchar *p; - -for (i = 0; i < double_count; i += 2) - size += sizeof(pcre_uchar *) + IN_UCHARS(ovector[i+1] - ovector[i] + 1); - -stringlist = (pcre_uchar **)(PUBL(malloc))(size); -if (stringlist == NULL) return PCRE_ERROR_NOMEMORY; - -#ifdef COMPILE_PCRE8 -*listptr = (const char **)stringlist; -#else -*listptr = (PCRE_SPTR16 *)stringlist; -#endif -p = (pcre_uchar *)(stringlist + stringcount + 1); - -for (i = 0; i < double_count; i += 2) - { - int len = ovector[i+1] - ovector[i]; - memcpy(p, subject + ovector[i], IN_UCHARS(len)); - *stringlist++ = p; - p += len; - *p++ = 0; - } - -*stringlist = NULL; -return 0; -} - - - -/************************************************* -* Free store obtained by get_substring_list * -*************************************************/ - -/* This function exists for the benefit of people calling PCRE from non-C -programs that can call its functions, but not free() or (PUBL(free))() -directly. - -Argument: the result of a previous pcre_get_substring_list() -Returns: nothing -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN void PCRE_CALL_CONVENTION -pcre_free_substring_list(const char **pointer) -#else -PCRE_EXP_DEFN void PCRE_CALL_CONVENTION -pcre16_free_substring_list(PCRE_SPTR16 *pointer) -#endif -{ -(PUBL(free))((void *)pointer); -} - - - -/************************************************* -* Copy captured string to new store * -*************************************************/ - -/* This function copies a single captured substring into a piece of new -store - -Arguments: - subject the subject string that was matched - ovector pointer to the offsets table - stringcount the number of substrings that were captured - (i.e. the yield of the pcre_exec call, unless - that was zero, in which case it should be 1/3 - of the offset table size) - stringnumber the number of the required substring - stringptr where to put a pointer to the substring - -Returns: if successful: - the length of the string, not including the zero that - is put on the end; can be zero - if not successful: - PCRE_ERROR_NOMEMORY (-6) failed to get store - PCRE_ERROR_NOSUBSTRING (-7) substring not present -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre_get_substring(const char *subject, int *ovector, int stringcount, - int stringnumber, const char **stringptr) -#else -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, - int stringnumber, PCRE_SPTR16 *stringptr) -#endif -{ -int yield; -pcre_uchar *substring; -if (stringnumber < 0 || stringnumber >= stringcount) - return PCRE_ERROR_NOSUBSTRING; -stringnumber *= 2; -yield = ovector[stringnumber+1] - ovector[stringnumber]; -substring = (pcre_uchar *)(PUBL(malloc))(IN_UCHARS(yield + 1)); -if (substring == NULL) return PCRE_ERROR_NOMEMORY; -memcpy(substring, subject + ovector[stringnumber], IN_UCHARS(yield)); -substring[yield] = 0; -#ifdef COMPILE_PCRE8 -*stringptr = (const char *)substring; -#else -*stringptr = (PCRE_SPTR16)substring; -#endif -return yield; -} - - - -/************************************************* -* Copy named captured string to new store * -*************************************************/ - -/* This function copies a single captured substring, identified by name, into -new store. If the regex permits duplicate names, the first substring that is -set is chosen. - -Arguments: - code the compiled regex - subject the subject string that was matched - ovector pointer to the offsets table - stringcount the number of substrings that were captured - (i.e. the yield of the pcre_exec call, unless - that was zero, in which case it should be 1/3 - of the offset table size) - stringname the name of the required substring - stringptr where to put the pointer - -Returns: if successful: - the length of the copied string, not including the zero - that is put on the end; can be zero - if not successful: - PCRE_ERROR_NOMEMORY (-6) couldn't get memory - PCRE_ERROR_NOSUBSTRING (-7) no such captured substring -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre_get_named_substring(const pcre *code, const char *subject, - int *ovector, int stringcount, const char *stringname, - const char **stringptr) -#else -PCRE_EXP_DEFN int PCRE_CALL_CONVENTION -pcre16_get_named_substring(const pcre16 *code, PCRE_SPTR16 subject, - int *ovector, int stringcount, PCRE_SPTR16 stringname, - PCRE_SPTR16 *stringptr) -#endif -{ -int n = get_first_set(code, stringname, ovector); -if (n <= 0) return n; -#ifdef COMPILE_PCRE8 -return pcre_get_substring(subject, ovector, stringcount, n, stringptr); -#else -return pcre16_get_substring(subject, ovector, stringcount, n, stringptr); -#endif -} - - - - -/************************************************* -* Free store obtained by get_substring * -*************************************************/ - -/* This function exists for the benefit of people calling PCRE from non-C -programs that can call its functions, but not free() or (PUBL(free))() -directly. - -Argument: the result of a previous pcre_get_substring() -Returns: nothing -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN void PCRE_CALL_CONVENTION -pcre_free_substring(const char *pointer) -#else -PCRE_EXP_DEFN void PCRE_CALL_CONVENTION -pcre16_free_substring(PCRE_SPTR16 pointer) -#endif -{ -(PUBL(free))((void *)pointer); -} - -/* End of pcre_get.c */ diff --git a/glib/pcre/pcre_globals.c b/glib/pcre/pcre_globals.c deleted file mode 100644 index 383ec7311..000000000 --- a/glib/pcre/pcre_globals.c +++ /dev/null @@ -1,88 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains global variables that are exported by the PCRE library. -PCRE is thread-clean and doesn't use any global variables in the normal sense. -However, it calls memory allocation and freeing functions via the four -indirections below, and it can optionally do callouts, using the fifth -indirection. These values can be changed by the caller, but are shared between -all threads. - -For MS Visual Studio and Symbian OS, there are problems in initializing these -variables to non-local functions. In these cases, therefore, an indirection via -a local function is used. - -Also, when compiling for Virtual Pascal, things are done differently, and -global variables are not used. */ - -#include "config.h" - -#include "pcre_internal.h" - -#ifdef GLIB_COMPILATION -#include "gmem.h" -#else -#include <glib.h> -#endif /* GLIB_COMPILATION */ - -#if defined _MSC_VER || defined __SYMBIAN32__ -static void* LocalPcreMalloc(size_t aSize) - { - return malloc(aSize); - } -static void LocalPcreFree(void* aPtr) - { - free(aPtr); - } -PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = LocalPcreMalloc; -PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = LocalPcreFree; -PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = LocalPcreMalloc; -PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = LocalPcreFree; -PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL; - -#elif !defined VPCOMPAT -PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = g_try_malloc; -PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = g_free; -PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = g_try_malloc; -PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = g_free; -PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL; -#endif - -/* End of pcre_globals.c */ diff --git a/glib/pcre/pcre_internal.h b/glib/pcre/pcre_internal.h deleted file mode 100644 index 9918e71a4..000000000 --- a/glib/pcre/pcre_internal.h +++ /dev/null @@ -1,2334 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - -/* This header contains definitions that are shared between the different -modules, but which are not relevant to the exported API. This includes some -functions whose names all begin with "_pcre_" or "_pcre16_" depending on -the PRIV macro. */ - -#ifndef PCRE_INTERNAL_H -#define PCRE_INTERNAL_H - -/* Define PCRE_DEBUG to get debugging output on stdout. */ - -#if 0 -#define PCRE_DEBUG -#endif - -/* PCRE is compiled as an 8 bit library if it is not requested otherwise. */ -#ifndef COMPILE_PCRE16 -#define COMPILE_PCRE8 -#endif - -/* If SUPPORT_UCP is defined, SUPPORT_UTF must also be defined. The -"configure" script ensures this, but not everybody uses "configure". */ - -#if defined SUPPORT_UCP && !(defined SUPPORT_UTF) -#define SUPPORT_UTF 1 -#endif - -/* We define SUPPORT_UTF if SUPPORT_UTF8 is enabled for compatibility -reasons with existing code. */ - -#if defined SUPPORT_UTF8 && !(defined SUPPORT_UTF) -#define SUPPORT_UTF 1 -#endif - -/* Fixme: SUPPORT_UTF8 should be eventually disappear from the code. -Until then we define it if SUPPORT_UTF is defined. */ - -#if defined SUPPORT_UTF && !(defined SUPPORT_UTF8) -#define SUPPORT_UTF8 1 -#endif - -/* We do not support both EBCDIC and UTF-8/16 at the same time. The "configure" -script prevents both being selected, but not everybody uses "configure". */ - -#if defined EBCDIC && defined SUPPORT_UTF -#error The use of both EBCDIC and SUPPORT_UTF8/16 is not supported. -#endif - -/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef -inline, and there are *still* stupid compilers about that don't like indented -pre-processor statements, or at least there were when I first wrote this. After -all, it had only been about 10 years then... - -It turns out that the Mac Debugging.h header also defines the macro DPRINTF, so -be absolutely sure we get our version. */ - -#undef DPRINTF -#ifdef PCRE_DEBUG -#define DPRINTF(p) printf p -#else -#define DPRINTF(p) /* Nothing */ -#endif - - -/* Standard C headers plus the external interface definition. The only time -setjmp and stdarg are used is when NO_RECURSE is set. */ - -#include <ctype.h> -#include <limits.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* When compiling a DLL for Windows, the exported symbols have to be declared -using some MS magic. I found some useful information on this web page: -http://msdn2.microsoft.com/en-us/library/y4h7bcy6(VS.80).aspx. According to the -information there, using __declspec(dllexport) without "extern" we have a -definition; with "extern" we have a declaration. The settings here override the -setting in pcre.h (which is included below); it defines only PCRE_EXP_DECL, -which is all that is needed for applications (they just import the symbols). We -use: - - PCRE_EXP_DECL for declarations - PCRE_EXP_DEFN for definitions of exported functions - PCRE_EXP_DATA_DEFN for definitions of exported variables - -The reason for the two DEFN macros is that in non-Windows environments, one -does not want to have "extern" before variable definitions because it leads to -compiler warnings. So we distinguish between functions and variables. In -Windows, the two should always be the same. - -The reason for wrapping this in #ifndef PCRE_EXP_DECL is so that pcretest, -which is an application, but needs to import this file in order to "peek" at -internals, can #include pcre.h first to get an application's-eye view. - -In principle, people compiling for non-Windows, non-Unix-like (i.e. uncommon, -special-purpose environments) might want to stick other stuff in front of -exported symbols. That's why, in the non-Windows case, we set PCRE_EXP_DEFN and -PCRE_EXP_DATA_DEFN only if they are not already set. */ - -#ifndef PCRE_EXP_DECL -# ifdef _WIN32 -# ifndef PCRE_STATIC -# define PCRE_EXP_DECL extern __declspec(dllexport) -# define PCRE_EXP_DEFN __declspec(dllexport) -# define PCRE_EXP_DATA_DEFN __declspec(dllexport) -# else -# define PCRE_EXP_DECL extern -# define PCRE_EXP_DEFN -# define PCRE_EXP_DATA_DEFN -# endif -# else -# ifdef __cplusplus -# define PCRE_EXP_DECL extern "C" -# else -# define PCRE_EXP_DECL extern -# endif -# ifndef PCRE_EXP_DEFN -# define PCRE_EXP_DEFN PCRE_EXP_DECL -# endif -# ifndef PCRE_EXP_DATA_DEFN -# define PCRE_EXP_DATA_DEFN -# endif -# endif -#endif - -/* When compiling with the MSVC compiler, it is sometimes necessary to include -a "calling convention" before exported function names. (This is secondhand -information; I know nothing about MSVC myself). For example, something like - - void __cdecl function(....) - -might be needed. In order so make this easy, all the exported functions have -PCRE_CALL_CONVENTION just before their names. It is rarely needed; if not -set, we ensure here that it has no effect. */ - -#ifndef PCRE_CALL_CONVENTION -#define PCRE_CALL_CONVENTION -#endif - -/* We need to have types that specify unsigned 8, 16 and 32-bit integers. We -cannot determine these outside the compilation (e.g. by running a program as -part of "configure") because PCRE is often cross-compiled for use on other -systems. Instead we make use of the maximum sizes that are available at -preprocessor time in standard C environments. */ - -typedef unsigned char pcre_uint8; - -#if USHRT_MAX == 65535 - typedef unsigned short pcre_uint16; - typedef short pcre_int16; -#elif UINT_MAX == 65535 - typedef unsigned int pcre_uint16; - typedef int pcre_int16; -#else - #error Cannot determine a type for 16-bit unsigned integers -#endif - -#if UINT_MAX == 4294967295 - typedef unsigned int pcre_uint32; - typedef int pcre_int32; -#elif ULONG_MAX == 4294967295 - typedef unsigned long int pcre_uint32; - typedef long int pcre_int32; -#else - #error Cannot determine a type for 32-bit unsigned integers -#endif - -/* When checking for integer overflow in pcre_compile(), we need to handle -large integers. If a 64-bit integer type is available, we can use that. -Otherwise we have to cast to double, which of course requires floating point -arithmetic. Handle this by defining a macro for the appropriate type. If -stdint.h is available, include it; it may define INT64_MAX. Systems that do not -have stdint.h (e.g. Solaris) may have inttypes.h. The macro int64_t may be set -by "configure". */ - -#if HAVE_STDINT_H -#include <stdint.h> -#elif HAVE_INTTYPES_H -#include <inttypes.h> -#endif - -#if defined INT64_MAX || defined int64_t -#define INT64_OR_DOUBLE int64_t -#else -#define INT64_OR_DOUBLE double -#endif - -/* All character handling must be done as unsigned characters. Otherwise there -are problems with top-bit-set characters and functions such as isspace(). -However, we leave the interface to the outside world as char * or short *, -because that should make things easier for callers. This character type is -called pcre_uchar. - -The IN_UCHARS macro multiply its argument with the byte size of the current -pcre_uchar type. Useful for memcpy and such operations, whose require the -byte size of their input/output buffers. - -The MAX_255 macro checks whether its pcre_uchar input is less than 256. - -The TABLE_GET macro is designed for accessing elements of tables whose contain -exactly 256 items. When the character is able to contain more than 256 -items, some check is needed before accessing these tables. -*/ - -#ifdef COMPILE_PCRE8 - -typedef unsigned char pcre_uchar; -#define IN_UCHARS(x) (x) -#define MAX_255(c) 1 -#define TABLE_GET(c, table, default) ((table)[c]) - -#else - -#ifdef COMPILE_PCRE16 -#if USHRT_MAX != 65535 -/* This is a warning message. Change PCRE_UCHAR16 to a 16 bit data type in -pcre.h(.in) and disable (comment out) this message. */ -#error Warning: PCRE_UCHAR16 is not a 16 bit data type. -#endif - -typedef pcre_uint16 pcre_uchar; -#define IN_UCHARS(x) ((x) << 1) -#define MAX_255(c) ((c) <= 255u) -#define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default)) - -#else -#error Unsupported compiling mode -#endif /* COMPILE_PCRE16 */ - -#endif /* COMPILE_PCRE8 */ - -/* This is an unsigned int value that no character can ever have. UTF-8 -characters only go up to 0x7fffffff (though Unicode doesn't go beyond -0x0010ffff). */ - -#define NOTACHAR 0xffffffff - -/* PCRE is able to support several different kinds of newline (CR, LF, CRLF, -"any" and "anycrlf" at present). The following macros are used to package up -testing for newlines. NLBLOCK, PSSTART, and PSEND are defined in the various -modules to indicate in which datablock the parameters exist, and what the -start/end of string field names are. */ - -#define NLTYPE_FIXED 0 /* Newline is a fixed length string */ -#define NLTYPE_ANY 1 /* Newline is any Unicode line ending */ -#define NLTYPE_ANYCRLF 2 /* Newline is CR, LF, or CRLF */ - -/* This macro checks for a newline at the given position */ - -#define IS_NEWLINE(p) \ - ((NLBLOCK->nltype != NLTYPE_FIXED)? \ - ((p) < NLBLOCK->PSEND && \ - PRIV(is_newline)((p), NLBLOCK->nltype, NLBLOCK->PSEND, \ - &(NLBLOCK->nllen), utf)) \ - : \ - ((p) <= NLBLOCK->PSEND - NLBLOCK->nllen && \ - (p)[0] == NLBLOCK->nl[0] && \ - (NLBLOCK->nllen == 1 || (p)[1] == NLBLOCK->nl[1]) \ - ) \ - ) - -/* This macro checks for a newline immediately preceding the given position */ - -#define WAS_NEWLINE(p) \ - ((NLBLOCK->nltype != NLTYPE_FIXED)? \ - ((p) > NLBLOCK->PSSTART && \ - PRIV(was_newline)((p), NLBLOCK->nltype, NLBLOCK->PSSTART, \ - &(NLBLOCK->nllen), utf)) \ - : \ - ((p) >= NLBLOCK->PSSTART + NLBLOCK->nllen && \ - (p)[-NLBLOCK->nllen] == NLBLOCK->nl[0] && \ - (NLBLOCK->nllen == 1 || (p)[-NLBLOCK->nllen+1] == NLBLOCK->nl[1]) \ - ) \ - ) - -/* When PCRE is compiled as a C++ library, the subject pointer can be replaced -with a custom type. This makes it possible, for example, to allow pcre_exec() -to process subject strings that are discontinuous by using a smart pointer -class. It must always be possible to inspect all of the subject string in -pcre_exec() because of the way it backtracks. Two macros are required in the -normal case, for sign-unspecified and unsigned char pointers. The former is -used for the external interface and appears in pcre.h, which is why its name -must begin with PCRE_. */ - -#ifdef CUSTOM_SUBJECT_PTR -#define PCRE_PUCHAR CUSTOM_SUBJECT_PTR -#else -#define PCRE_PUCHAR const pcre_uchar * -#endif - -/* Include the public PCRE header and the definitions of UCP character property -values. */ - -#include "pcre.h" -#include "ucp.h" - -/* When compiling for use with the Virtual Pascal compiler, these functions -need to have their names changed. PCRE must be compiled with the -DVPCOMPAT -option on the command line. */ - -#ifdef VPCOMPAT -#define strlen(s) _strlen(s) -#define strncmp(s1,s2,m) _strncmp(s1,s2,m) -#define memcmp(s,c,n) _memcmp(s,c,n) -#define memcpy(d,s,n) _memcpy(d,s,n) -#define memmove(d,s,n) _memmove(d,s,n) -#define memset(s,c,n) _memset(s,c,n) -#else /* VPCOMPAT */ - -/* To cope with SunOS4 and other systems that lack memmove() but have bcopy(), -define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY -is set. Otherwise, include an emulating function for those systems that have -neither (there some non-Unix environments where this is the case). */ - -#ifndef HAVE_MEMMOVE -#undef memmove /* some systems may have a macro */ -#ifdef HAVE_BCOPY -#define memmove(a, b, c) bcopy(b, a, c) -#else /* HAVE_BCOPY */ -static void * -pcre_memmove(void *d, const void *s, size_t n) -{ -size_t i; -unsigned char *dest = (unsigned char *)d; -const unsigned char *src = (const unsigned char *)s; -if (dest > src) - { - dest += n; - src += n; - for (i = 0; i < n; ++i) *(--dest) = *(--src); - return (void *)dest; - } -else - { - for (i = 0; i < n; ++i) *dest++ = *src++; - return (void *)(dest - n); - } -} -#define memmove(a, b, c) pcre_memmove(a, b, c) -#endif /* not HAVE_BCOPY */ -#endif /* not HAVE_MEMMOVE */ -#endif /* not VPCOMPAT */ - - -/* PCRE keeps offsets in its compiled code as 2-byte quantities (always stored -in big-endian order) by default. These are used, for example, to link from the -start of a subpattern to its alternatives and its end. The use of 2 bytes per -offset limits the size of the compiled regex to around 64K, which is big enough -for almost everybody. However, I received a request for an even bigger limit. -For this reason, and also to make the code easier to maintain, the storing and -loading of offsets from the byte string is now handled by the macros that are -defined here. - -The macros are controlled by the value of LINK_SIZE. This defaults to 2 in -the config.h file, but can be overridden by using -D on the command line. This -is automated on Unix systems via the "configure" command. */ - -#ifdef COMPILE_PCRE8 - -#if LINK_SIZE == 2 - -#define PUT(a,n,d) \ - (a[n] = (d) >> 8), \ - (a[(n)+1] = (d) & 255) - -#define GET(a,n) \ - (((a)[n] << 8) | (a)[(n)+1]) - -#define MAX_PATTERN_SIZE (1 << 16) - - -#elif LINK_SIZE == 3 - -#define PUT(a,n,d) \ - (a[n] = (d) >> 16), \ - (a[(n)+1] = (d) >> 8), \ - (a[(n)+2] = (d) & 255) - -#define GET(a,n) \ - (((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2]) - -#define MAX_PATTERN_SIZE (1 << 24) - - -#elif LINK_SIZE == 4 - -#define PUT(a,n,d) \ - (a[n] = (d) >> 24), \ - (a[(n)+1] = (d) >> 16), \ - (a[(n)+2] = (d) >> 8), \ - (a[(n)+3] = (d) & 255) - -#define GET(a,n) \ - (((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3]) - -/* Keep it positive */ -#define MAX_PATTERN_SIZE (1 << 30) - -#else -#error LINK_SIZE must be either 2, 3, or 4 -#endif - -#else /* COMPILE_PCRE8 */ - -#ifdef COMPILE_PCRE16 - -#if LINK_SIZE == 2 - -#undef LINK_SIZE -#define LINK_SIZE 1 - -#define PUT(a,n,d) \ - (a[n] = (d)) - -#define GET(a,n) \ - (a[n]) - -#define MAX_PATTERN_SIZE (1 << 16) - -#elif LINK_SIZE == 3 || LINK_SIZE == 4 - -#undef LINK_SIZE -#define LINK_SIZE 2 - -#define PUT(a,n,d) \ - (a[n] = (d) >> 16), \ - (a[(n)+1] = (d) & 65535) - -#define GET(a,n) \ - (((a)[n] << 16) | (a)[(n)+1]) - -/* Keep it positive */ -#define MAX_PATTERN_SIZE (1 << 30) - -#else -#error LINK_SIZE must be either 2, 3, or 4 -#endif - -#else -#error Unsupported compiling mode -#endif /* COMPILE_PCRE16 */ - -#endif /* COMPILE_PCRE8 */ - -/* Convenience macro defined in terms of the others */ - -#define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE - - -/* PCRE uses some other 2-byte quantities that do not change when the size of -offsets changes. There are used for repeat counts and for other things such as -capturing parenthesis numbers in back references. */ - -#ifdef COMPILE_PCRE8 - -#define IMM2_SIZE 2 - -#define PUT2(a,n,d) \ - a[n] = (d) >> 8; \ - a[(n)+1] = (d) & 255 - -#define GET2(a,n) \ - (((a)[n] << 8) | (a)[(n)+1]) - -#else /* COMPILE_PCRE8 */ - -#ifdef COMPILE_PCRE16 - -#define IMM2_SIZE 1 - -#define PUT2(a,n,d) \ - a[n] = d - -#define GET2(a,n) \ - a[n] - -#else -#error Unsupported compiling mode -#endif /* COMPILE_PCRE16 */ - -#endif /* COMPILE_PCRE8 */ - -#define PUT2INC(a,n,d) PUT2(a,n,d), a += IMM2_SIZE - -/* The maximum length of a MARK name is currently one data unit; it may be -changed in future to be a fixed number of bytes or to depend on LINK_SIZE. */ - -#define MAX_MARK ((1 << (sizeof(pcre_uchar)*8)) - 1) - -/* When UTF encoding is being used, a character is no longer just a single -character. The macros for character handling generate simple sequences when -used in character-mode, and more complicated ones for UTF characters. -GETCHARLENTEST and other macros are not used when UTF is not supported, -so they are not defined. To make sure they can never even appear when -UTF support is omitted, we don't even define them. */ - -#ifndef SUPPORT_UTF - -/* #define MAX_VALUE_FOR_SINGLE_CHAR */ -/* #define HAS_EXTRALEN(c) */ -/* #define GET_EXTRALEN(c) */ -/* #define NOT_FIRSTCHAR(c) */ -#define GETCHAR(c, eptr) c = *eptr; -#define GETCHARTEST(c, eptr) c = *eptr; -#define GETCHARINC(c, eptr) c = *eptr++; -#define GETCHARINCTEST(c, eptr) c = *eptr++; -#define GETCHARLEN(c, eptr, len) c = *eptr; -/* #define GETCHARLENTEST(c, eptr, len) */ -/* #define BACKCHAR(eptr) */ -/* #define FORWARDCHAR(eptr) */ -/* #define ACROSSCHAR(condition, eptr, action) */ - -#else /* SUPPORT_UTF */ - -#ifdef COMPILE_PCRE8 - -/* These macros were originally written in the form of loops that used data -from the tables whose names start with PRIV(utf8_table). They were rewritten by -a user so as not to use loops, because in some environments this gives a -significant performance advantage, and it seems never to do any harm. */ - -/* Tells the biggest code point which can be encoded as a single character. */ - -#define MAX_VALUE_FOR_SINGLE_CHAR 127 - -/* Tests whether the code point needs extra characters to decode. */ - -#define HAS_EXTRALEN(c) ((c) >= 0xc0) - -/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE. -Otherwise it has an undefined behaviour. */ - -#define GET_EXTRALEN(c) (PRIV(utf8_table4)[(c) & 0x3f]) - -/* Returns TRUE, if the given character is not the first character -of a UTF sequence. */ - -#define NOT_FIRSTCHAR(c) (((c) & 0xc0) == 0x80) - -/* Base macro to pick up the remaining bytes of a UTF-8 character, not -advancing the pointer. */ - -#define GETUTF8(c, eptr) \ - { \ - if ((c & 0x20) == 0) \ - c = ((c & 0x1f) << 6) | (eptr[1] & 0x3f); \ - else if ((c & 0x10) == 0) \ - c = ((c & 0x0f) << 12) | ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \ - else if ((c & 0x08) == 0) \ - c = ((c & 0x07) << 18) | ((eptr[1] & 0x3f) << 12) | \ - ((eptr[2] & 0x3f) << 6) | (eptr[3] & 0x3f); \ - else if ((c & 0x04) == 0) \ - c = ((c & 0x03) << 24) | ((eptr[1] & 0x3f) << 18) | \ - ((eptr[2] & 0x3f) << 12) | ((eptr[3] & 0x3f) << 6) | \ - (eptr[4] & 0x3f); \ - else \ - c = ((c & 0x01) << 30) | ((eptr[1] & 0x3f) << 24) | \ - ((eptr[2] & 0x3f) << 18) | ((eptr[3] & 0x3f) << 12) | \ - ((eptr[4] & 0x3f) << 6) | (eptr[5] & 0x3f); \ - } - -/* Get the next UTF-8 character, not advancing the pointer. This is called when -we know we are in UTF-8 mode. */ - -#define GETCHAR(c, eptr) \ - c = *eptr; \ - if (c >= 0xc0) GETUTF8(c, eptr); - -/* Get the next UTF-8 character, testing for UTF-8 mode, and not advancing the -pointer. */ - -#define GETCHARTEST(c, eptr) \ - c = *eptr; \ - if (utf && c >= 0xc0) GETUTF8(c, eptr); - -/* Base macro to pick up the remaining bytes of a UTF-8 character, advancing -the pointer. */ - -#define GETUTF8INC(c, eptr) \ - { \ - if ((c & 0x20) == 0) \ - c = ((c & 0x1f) << 6) | (*eptr++ & 0x3f); \ - else if ((c & 0x10) == 0) \ - { \ - c = ((c & 0x0f) << 12) | ((*eptr & 0x3f) << 6) | (eptr[1] & 0x3f); \ - eptr += 2; \ - } \ - else if ((c & 0x08) == 0) \ - { \ - c = ((c & 0x07) << 18) | ((*eptr & 0x3f) << 12) | \ - ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \ - eptr += 3; \ - } \ - else if ((c & 0x04) == 0) \ - { \ - c = ((c & 0x03) << 24) | ((*eptr & 0x3f) << 18) | \ - ((eptr[1] & 0x3f) << 12) | ((eptr[2] & 0x3f) << 6) | \ - (eptr[3] & 0x3f); \ - eptr += 4; \ - } \ - else \ - { \ - c = ((c & 0x01) << 30) | ((*eptr & 0x3f) << 24) | \ - ((eptr[1] & 0x3f) << 18) | ((eptr[2] & 0x3f) << 12) | \ - ((eptr[3] & 0x3f) << 6) | (eptr[4] & 0x3f); \ - eptr += 5; \ - } \ - } - -/* Get the next UTF-8 character, advancing the pointer. This is called when we -know we are in UTF-8 mode. */ - -#define GETCHARINC(c, eptr) \ - c = *eptr++; \ - if (c >= 0xc0) GETUTF8INC(c, eptr); - -/* Get the next character, testing for UTF-8 mode, and advancing the pointer. -This is called when we don't know if we are in UTF-8 mode. */ - -#define GETCHARINCTEST(c, eptr) \ - c = *eptr++; \ - if (utf && c >= 0xc0) GETUTF8INC(c, eptr); - -/* Base macro to pick up the remaining bytes of a UTF-8 character, not -advancing the pointer, incrementing the length. */ - -#define GETUTF8LEN(c, eptr, len) \ - { \ - if ((c & 0x20) == 0) \ - { \ - c = ((c & 0x1f) << 6) | (eptr[1] & 0x3f); \ - len++; \ - } \ - else if ((c & 0x10) == 0) \ - { \ - c = ((c & 0x0f) << 12) | ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \ - len += 2; \ - } \ - else if ((c & 0x08) == 0) \ - {\ - c = ((c & 0x07) << 18) | ((eptr[1] & 0x3f) << 12) | \ - ((eptr[2] & 0x3f) << 6) | (eptr[3] & 0x3f); \ - len += 3; \ - } \ - else if ((c & 0x04) == 0) \ - { \ - c = ((c & 0x03) << 24) | ((eptr[1] & 0x3f) << 18) | \ - ((eptr[2] & 0x3f) << 12) | ((eptr[3] & 0x3f) << 6) | \ - (eptr[4] & 0x3f); \ - len += 4; \ - } \ - else \ - {\ - c = ((c & 0x01) << 30) | ((eptr[1] & 0x3f) << 24) | \ - ((eptr[2] & 0x3f) << 18) | ((eptr[3] & 0x3f) << 12) | \ - ((eptr[4] & 0x3f) << 6) | (eptr[5] & 0x3f); \ - len += 5; \ - } \ - } - -/* Get the next UTF-8 character, not advancing the pointer, incrementing length -if there are extra bytes. This is called when we know we are in UTF-8 mode. */ - -#define GETCHARLEN(c, eptr, len) \ - c = *eptr; \ - if (c >= 0xc0) GETUTF8LEN(c, eptr, len); - -/* Get the next UTF-8 character, testing for UTF-8 mode, not advancing the -pointer, incrementing length if there are extra bytes. This is called when we -do not know if we are in UTF-8 mode. */ - -#define GETCHARLENTEST(c, eptr, len) \ - c = *eptr; \ - if (utf && c >= 0xc0) GETUTF8LEN(c, eptr, len); - -/* If the pointer is not at the start of a character, move it back until -it is. This is called only in UTF-8 mode - we don't put a test within the macro -because almost all calls are already within a block of UTF-8 only code. */ - -#define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr-- - -/* Same as above, just in the other direction. */ -#define FORWARDCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr++ - -/* Same as above, but it allows a fully customizable form. */ -#define ACROSSCHAR(condition, eptr, action) \ - while((condition) && ((eptr) & 0xc0) == 0x80) action - -#else /* COMPILE_PCRE8 */ - -#ifdef COMPILE_PCRE16 - -/* Tells the biggest code point which can be encoded as a single character. */ - -#define MAX_VALUE_FOR_SINGLE_CHAR 65535 - -/* Tests whether the code point needs extra characters to decode. */ - -#define HAS_EXTRALEN(c) (((c) & 0xfc00) == 0xd800) - -/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE. -Otherwise it has an undefined behaviour. */ - -#define GET_EXTRALEN(c) 1 - -/* Returns TRUE, if the given character is not the first character -of a UTF sequence. */ - -#define NOT_FIRSTCHAR(c) (((c) & 0xfc00) == 0xdc00) - -/* Base macro to pick up the low surrogate of a UTF-16 character, not -advancing the pointer. */ - -#define GETUTF16(c, eptr) \ - { c = (((c & 0x3ff) << 10) | (eptr[1] & 0x3ff)) + 0x10000; } - -/* Get the next UTF-16 character, not advancing the pointer. This is called when -we know we are in UTF-16 mode. */ - -#define GETCHAR(c, eptr) \ - c = *eptr; \ - if ((c & 0xfc00) == 0xd800) GETUTF16(c, eptr); - -/* Get the next UTF-16 character, testing for UTF-16 mode, and not advancing the -pointer. */ - -#define GETCHARTEST(c, eptr) \ - c = *eptr; \ - if (utf && (c & 0xfc00) == 0xd800) GETUTF16(c, eptr); - -/* Base macro to pick up the low surrogate of a UTF-16 character, advancing -the pointer. */ - -#define GETUTF16INC(c, eptr) \ - { c = (((c & 0x3ff) << 10) | (*eptr++ & 0x3ff)) + 0x10000; } - -/* Get the next UTF-16 character, advancing the pointer. This is called when we -know we are in UTF-16 mode. */ - -#define GETCHARINC(c, eptr) \ - c = *eptr++; \ - if ((c & 0xfc00) == 0xd800) GETUTF16INC(c, eptr); - -/* Get the next character, testing for UTF-16 mode, and advancing the pointer. -This is called when we don't know if we are in UTF-16 mode. */ - -#define GETCHARINCTEST(c, eptr) \ - c = *eptr++; \ - if (utf && (c & 0xfc00) == 0xd800) GETUTF16INC(c, eptr); - -/* Base macro to pick up the low surrogate of a UTF-16 character, not -advancing the pointer, incrementing the length. */ - -#define GETUTF16LEN(c, eptr, len) \ - { c = (((c & 0x3ff) << 10) | (eptr[1] & 0x3ff)) + 0x10000; len++; } - -/* Get the next UTF-16 character, not advancing the pointer, incrementing -length if there is a low surrogate. This is called when we know we are in -UTF-16 mode. */ - -#define GETCHARLEN(c, eptr, len) \ - c = *eptr; \ - if ((c & 0xfc00) == 0xd800) GETUTF16LEN(c, eptr, len); - -/* Get the next UTF-816character, testing for UTF-16 mode, not advancing the -pointer, incrementing length if there is a low surrogate. This is called when -we do not know if we are in UTF-16 mode. */ - -#define GETCHARLENTEST(c, eptr, len) \ - c = *eptr; \ - if (utf && (c & 0xfc00) == 0xd800) GETUTF16LEN(c, eptr, len); - -/* If the pointer is not at the start of a character, move it back until -it is. This is called only in UTF-16 mode - we don't put a test within the -macro because almost all calls are already within a block of UTF-16 only -code. */ - -#define BACKCHAR(eptr) if ((*eptr & 0xfc00) == 0xdc00) eptr-- - -/* Same as above, just in the other direction. */ -#define FORWARDCHAR(eptr) if ((*eptr & 0xfc00) == 0xdc00) eptr++ - -/* Same as above, but it allows a fully customizable form. */ -#define ACROSSCHAR(condition, eptr, action) \ - if ((condition) && ((eptr) & 0xfc00) == 0xdc00) action - -#endif - -#endif /* COMPILE_PCRE8 */ - -#endif /* SUPPORT_UTF */ - - -/* In case there is no definition of offsetof() provided - though any proper -Standard C system should have one. */ - -#ifndef offsetof -#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field)) -#endif - - -/* Private flags containing information about the compiled regex. They used to -live at the top end of the options word, but that got almost full, so now they -are in a 16-bit flags word. From release 8.00, PCRE_NOPARTIAL is unused, as -the restrictions on partial matching have been lifted. It remains for backwards -compatibility. */ - -#ifdef COMPILE_PCRE8 -#define PCRE_MODE 0x0001 /* compiled in 8 bit mode */ -#endif -#ifdef COMPILE_PCRE16 -#define PCRE_MODE 0x0002 /* compiled in 16 bit mode */ -#endif -#define PCRE_FIRSTSET 0x0010 /* first_char is set */ -#define PCRE_FCH_CASELESS 0x0020 /* caseless first char */ -#define PCRE_REQCHSET 0x0040 /* req_byte is set */ -#define PCRE_RCH_CASELESS 0x0080 /* caseless requested char */ -#define PCRE_STARTLINE 0x0100 /* start after \n for multiline */ -#define PCRE_NOPARTIAL 0x0200 /* can't use partial with this regex */ -#define PCRE_JCHANGED 0x0400 /* j option used in regex */ -#define PCRE_HASCRORLF 0x0800 /* explicit \r or \n in pattern */ -#define PCRE_HASTHEN 0x1000 /* pattern contains (*THEN) */ - -/* Flags for the "extra" block produced by pcre_study(). */ - -#define PCRE_STUDY_MAPPED 0x0001 /* a map of starting chars exists */ -#define PCRE_STUDY_MINLEN 0x0002 /* a minimum length field exists */ - -/* Masks for identifying the public options that are permitted at compile -time, run time, or study time, respectively. */ - -#define PCRE_NEWLINE_BITS (PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|PCRE_NEWLINE_ANY| \ - PCRE_NEWLINE_ANYCRLF) - -#define PUBLIC_COMPILE_OPTIONS \ - (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \ - PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8| \ - PCRE_NO_AUTO_CAPTURE|PCRE_NO_UTF8_CHECK|PCRE_AUTO_CALLOUT|PCRE_FIRSTLINE| \ - PCRE_DUPNAMES|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE| \ - PCRE_JAVASCRIPT_COMPAT|PCRE_UCP|PCRE_NO_START_OPTIMIZE) - -#define PUBLIC_EXEC_OPTIONS \ - (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NOTEMPTY_ATSTART| \ - PCRE_NO_UTF8_CHECK|PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT|PCRE_NEWLINE_BITS| \ - PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE|PCRE_NO_START_OPTIMIZE) - -#define PUBLIC_DFA_EXEC_OPTIONS \ - (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NOTEMPTY_ATSTART| \ - PCRE_NO_UTF8_CHECK|PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT|PCRE_DFA_SHORTEST| \ - PCRE_DFA_RESTART|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE| \ - PCRE_NO_START_OPTIMIZE) - -#define PUBLIC_STUDY_OPTIONS \ - (PCRE_STUDY_JIT_COMPILE|PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE| \ - PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE) - -/* Magic number to provide a small check against being handed junk. */ - -#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */ - -/* This variable is used to detect a loaded regular expression -in different endianness. */ - -#define REVERSED_MAGIC_NUMBER 0x45524350UL /* 'ERCP' */ - -/* Negative values for the firstchar and reqchar variables */ - -#define REQ_UNSET (-2) -#define REQ_NONE (-1) - -/* The maximum remaining length of subject we are prepared to search for a -req_byte match. */ - -#define REQ_BYTE_MAX 1000 - -/* Miscellaneous definitions. The #ifndef is to pacify compiler warnings in -environments where these macros are defined elsewhere. Unfortunately, there -is no way to do the same for the typedef. */ - -typedef int BOOL; - -#ifndef FALSE -#define FALSE 0 -#define TRUE 1 -#endif - -/* If PCRE is to support UTF-8 on EBCDIC platforms, we cannot use normal -character constants like '*' because the compiler would emit their EBCDIC code, -which is different from their ASCII/UTF-8 code. Instead we define macros for -the characters so that they always use the ASCII/UTF-8 code when UTF-8 support -is enabled. When UTF-8 support is not enabled, the definitions use character -literals. Both character and string versions of each character are needed, and -there are some longer strings as well. - -This means that, on EBCDIC platforms, the PCRE library can handle either -EBCDIC, or UTF-8, but not both. To support both in the same compiled library -would need different lookups depending on whether PCRE_UTF8 was set or not. -This would make it impossible to use characters in switch/case statements, -which would reduce performance. For a theoretical use (which nobody has asked -for) in a minority area (EBCDIC platforms), this is not sensible. Any -application that did need both could compile two versions of the library, using -macros to give the functions distinct names. */ - -#ifndef SUPPORT_UTF - -/* UTF-8 support is not enabled; use the platform-dependent character literals -so that PCRE works on both ASCII and EBCDIC platforms, in non-UTF-mode only. */ - -#define CHAR_HT '\t' -#define CHAR_VT '\v' -#define CHAR_FF '\f' -#define CHAR_CR '\r' -#define CHAR_NL '\n' -#define CHAR_BS '\b' -#define CHAR_BEL '\a' -#ifdef EBCDIC -#define CHAR_ESC '\047' -#define CHAR_DEL '\007' -#else -#define CHAR_ESC '\033' -#define CHAR_DEL '\177' -#endif - -#define CHAR_SPACE ' ' -#define CHAR_EXCLAMATION_MARK '!' -#define CHAR_QUOTATION_MARK '"' -#define CHAR_NUMBER_SIGN '#' -#define CHAR_DOLLAR_SIGN '$' -#define CHAR_PERCENT_SIGN '%' -#define CHAR_AMPERSAND '&' -#define CHAR_APOSTROPHE '\'' -#define CHAR_LEFT_PARENTHESIS '(' -#define CHAR_RIGHT_PARENTHESIS ')' -#define CHAR_ASTERISK '*' -#define CHAR_PLUS '+' -#define CHAR_COMMA ',' -#define CHAR_MINUS '-' -#define CHAR_DOT '.' -#define CHAR_SLASH '/' -#define CHAR_0 '0' -#define CHAR_1 '1' -#define CHAR_2 '2' -#define CHAR_3 '3' -#define CHAR_4 '4' -#define CHAR_5 '5' -#define CHAR_6 '6' -#define CHAR_7 '7' -#define CHAR_8 '8' -#define CHAR_9 '9' -#define CHAR_COLON ':' -#define CHAR_SEMICOLON ';' -#define CHAR_LESS_THAN_SIGN '<' -#define CHAR_EQUALS_SIGN '=' -#define CHAR_GREATER_THAN_SIGN '>' -#define CHAR_QUESTION_MARK '?' -#define CHAR_COMMERCIAL_AT '@' -#define CHAR_A 'A' -#define CHAR_B 'B' -#define CHAR_C 'C' -#define CHAR_D 'D' -#define CHAR_E 'E' -#define CHAR_F 'F' -#define CHAR_G 'G' -#define CHAR_H 'H' -#define CHAR_I 'I' -#define CHAR_J 'J' -#define CHAR_K 'K' -#define CHAR_L 'L' -#define CHAR_M 'M' -#define CHAR_N 'N' -#define CHAR_O 'O' -#define CHAR_P 'P' -#define CHAR_Q 'Q' -#define CHAR_R 'R' -#define CHAR_S 'S' -#define CHAR_T 'T' -#define CHAR_U 'U' -#define CHAR_V 'V' -#define CHAR_W 'W' -#define CHAR_X 'X' -#define CHAR_Y 'Y' -#define CHAR_Z 'Z' -#define CHAR_LEFT_SQUARE_BRACKET '[' -#define CHAR_BACKSLASH '\\' -#define CHAR_RIGHT_SQUARE_BRACKET ']' -#define CHAR_CIRCUMFLEX_ACCENT '^' -#define CHAR_UNDERSCORE '_' -#define CHAR_GRAVE_ACCENT '`' -#define CHAR_a 'a' -#define CHAR_b 'b' -#define CHAR_c 'c' -#define CHAR_d 'd' -#define CHAR_e 'e' -#define CHAR_f 'f' -#define CHAR_g 'g' -#define CHAR_h 'h' -#define CHAR_i 'i' -#define CHAR_j 'j' -#define CHAR_k 'k' -#define CHAR_l 'l' -#define CHAR_m 'm' -#define CHAR_n 'n' -#define CHAR_o 'o' -#define CHAR_p 'p' -#define CHAR_q 'q' -#define CHAR_r 'r' -#define CHAR_s 's' -#define CHAR_t 't' -#define CHAR_u 'u' -#define CHAR_v 'v' -#define CHAR_w 'w' -#define CHAR_x 'x' -#define CHAR_y 'y' -#define CHAR_z 'z' -#define CHAR_LEFT_CURLY_BRACKET '{' -#define CHAR_VERTICAL_LINE '|' -#define CHAR_RIGHT_CURLY_BRACKET '}' -#define CHAR_TILDE '~' - -#define STR_HT "\t" -#define STR_VT "\v" -#define STR_FF "\f" -#define STR_CR "\r" -#define STR_NL "\n" -#define STR_BS "\b" -#define STR_BEL "\a" -#ifdef EBCDIC -#define STR_ESC "\047" -#define STR_DEL "\007" -#else -#define STR_ESC "\033" -#define STR_DEL "\177" -#endif - -#define STR_SPACE " " -#define STR_EXCLAMATION_MARK "!" -#define STR_QUOTATION_MARK "\"" -#define STR_NUMBER_SIGN "#" -#define STR_DOLLAR_SIGN "$" -#define STR_PERCENT_SIGN "%" -#define STR_AMPERSAND "&" -#define STR_APOSTROPHE "'" -#define STR_LEFT_PARENTHESIS "(" -#define STR_RIGHT_PARENTHESIS ")" -#define STR_ASTERISK "*" -#define STR_PLUS "+" -#define STR_COMMA "," -#define STR_MINUS "-" -#define STR_DOT "." -#define STR_SLASH "/" -#define STR_0 "0" -#define STR_1 "1" -#define STR_2 "2" -#define STR_3 "3" -#define STR_4 "4" -#define STR_5 "5" -#define STR_6 "6" -#define STR_7 "7" -#define STR_8 "8" -#define STR_9 "9" -#define STR_COLON ":" -#define STR_SEMICOLON ";" -#define STR_LESS_THAN_SIGN "<" -#define STR_EQUALS_SIGN "=" -#define STR_GREATER_THAN_SIGN ">" -#define STR_QUESTION_MARK "?" -#define STR_COMMERCIAL_AT "@" -#define STR_A "A" -#define STR_B "B" -#define STR_C "C" -#define STR_D "D" -#define STR_E "E" -#define STR_F "F" -#define STR_G "G" -#define STR_H "H" -#define STR_I "I" -#define STR_J "J" -#define STR_K "K" -#define STR_L "L" -#define STR_M "M" -#define STR_N "N" -#define STR_O "O" -#define STR_P "P" -#define STR_Q "Q" -#define STR_R "R" -#define STR_S "S" -#define STR_T "T" -#define STR_U "U" -#define STR_V "V" -#define STR_W "W" -#define STR_X "X" -#define STR_Y "Y" -#define STR_Z "Z" -#define STR_LEFT_SQUARE_BRACKET "[" -#define STR_BACKSLASH "\\" -#define STR_RIGHT_SQUARE_BRACKET "]" -#define STR_CIRCUMFLEX_ACCENT "^" -#define STR_UNDERSCORE "_" -#define STR_GRAVE_ACCENT "`" -#define STR_a "a" -#define STR_b "b" -#define STR_c "c" -#define STR_d "d" -#define STR_e "e" -#define STR_f "f" -#define STR_g "g" -#define STR_h "h" -#define STR_i "i" -#define STR_j "j" -#define STR_k "k" -#define STR_l "l" -#define STR_m "m" -#define STR_n "n" -#define STR_o "o" -#define STR_p "p" -#define STR_q "q" -#define STR_r "r" -#define STR_s "s" -#define STR_t "t" -#define STR_u "u" -#define STR_v "v" -#define STR_w "w" -#define STR_x "x" -#define STR_y "y" -#define STR_z "z" -#define STR_LEFT_CURLY_BRACKET "{" -#define STR_VERTICAL_LINE "|" -#define STR_RIGHT_CURLY_BRACKET "}" -#define STR_TILDE "~" - -#define STRING_ACCEPT0 "ACCEPT\0" -#define STRING_COMMIT0 "COMMIT\0" -#define STRING_F0 "F\0" -#define STRING_FAIL0 "FAIL\0" -#define STRING_MARK0 "MARK\0" -#define STRING_PRUNE0 "PRUNE\0" -#define STRING_SKIP0 "SKIP\0" -#define STRING_THEN "THEN" - -#define STRING_alpha0 "alpha\0" -#define STRING_lower0 "lower\0" -#define STRING_upper0 "upper\0" -#define STRING_alnum0 "alnum\0" -#define STRING_ascii0 "ascii\0" -#define STRING_blank0 "blank\0" -#define STRING_cntrl0 "cntrl\0" -#define STRING_digit0 "digit\0" -#define STRING_graph0 "graph\0" -#define STRING_print0 "print\0" -#define STRING_punct0 "punct\0" -#define STRING_space0 "space\0" -#define STRING_word0 "word\0" -#define STRING_xdigit "xdigit" - -#define STRING_DEFINE "DEFINE" - -#define STRING_CR_RIGHTPAR "CR)" -#define STRING_LF_RIGHTPAR "LF)" -#define STRING_CRLF_RIGHTPAR "CRLF)" -#define STRING_ANY_RIGHTPAR "ANY)" -#define STRING_ANYCRLF_RIGHTPAR "ANYCRLF)" -#define STRING_BSR_ANYCRLF_RIGHTPAR "BSR_ANYCRLF)" -#define STRING_BSR_UNICODE_RIGHTPAR "BSR_UNICODE)" -#ifdef COMPILE_PCRE8 -#define STRING_UTF_RIGHTPAR "UTF8)" -#endif -#ifdef COMPILE_PCRE16 -#define STRING_UTF_RIGHTPAR "UTF16)" -#endif -#define STRING_UCP_RIGHTPAR "UCP)" -#define STRING_NO_START_OPT_RIGHTPAR "NO_START_OPT)" - -#else /* SUPPORT_UTF */ - -/* UTF-8 support is enabled; always use UTF-8 (=ASCII) character codes. This -works in both modes non-EBCDIC platforms, and on EBCDIC platforms in UTF-8 mode -only. */ - -#define CHAR_HT '\011' -#define CHAR_VT '\013' -#define CHAR_FF '\014' -#define CHAR_CR '\015' -#define CHAR_NL '\012' -#define CHAR_BS '\010' -#define CHAR_BEL '\007' -#define CHAR_ESC '\033' -#define CHAR_DEL '\177' - -#define CHAR_SPACE '\040' -#define CHAR_EXCLAMATION_MARK '\041' -#define CHAR_QUOTATION_MARK '\042' -#define CHAR_NUMBER_SIGN '\043' -#define CHAR_DOLLAR_SIGN '\044' -#define CHAR_PERCENT_SIGN '\045' -#define CHAR_AMPERSAND '\046' -#define CHAR_APOSTROPHE '\047' -#define CHAR_LEFT_PARENTHESIS '\050' -#define CHAR_RIGHT_PARENTHESIS '\051' -#define CHAR_ASTERISK '\052' -#define CHAR_PLUS '\053' -#define CHAR_COMMA '\054' -#define CHAR_MINUS '\055' -#define CHAR_DOT '\056' -#define CHAR_SLASH '\057' -#define CHAR_0 '\060' -#define CHAR_1 '\061' -#define CHAR_2 '\062' -#define CHAR_3 '\063' -#define CHAR_4 '\064' -#define CHAR_5 '\065' -#define CHAR_6 '\066' -#define CHAR_7 '\067' -#define CHAR_8 '\070' -#define CHAR_9 '\071' -#define CHAR_COLON '\072' -#define CHAR_SEMICOLON '\073' -#define CHAR_LESS_THAN_SIGN '\074' -#define CHAR_EQUALS_SIGN '\075' -#define CHAR_GREATER_THAN_SIGN '\076' -#define CHAR_QUESTION_MARK '\077' -#define CHAR_COMMERCIAL_AT '\100' -#define CHAR_A '\101' -#define CHAR_B '\102' -#define CHAR_C '\103' -#define CHAR_D '\104' -#define CHAR_E '\105' -#define CHAR_F '\106' -#define CHAR_G '\107' -#define CHAR_H '\110' -#define CHAR_I '\111' -#define CHAR_J '\112' -#define CHAR_K '\113' -#define CHAR_L '\114' -#define CHAR_M '\115' -#define CHAR_N '\116' -#define CHAR_O '\117' -#define CHAR_P '\120' -#define CHAR_Q '\121' -#define CHAR_R '\122' -#define CHAR_S '\123' -#define CHAR_T '\124' -#define CHAR_U '\125' -#define CHAR_V '\126' -#define CHAR_W '\127' -#define CHAR_X '\130' -#define CHAR_Y '\131' -#define CHAR_Z '\132' -#define CHAR_LEFT_SQUARE_BRACKET '\133' -#define CHAR_BACKSLASH '\134' -#define CHAR_RIGHT_SQUARE_BRACKET '\135' -#define CHAR_CIRCUMFLEX_ACCENT '\136' -#define CHAR_UNDERSCORE '\137' -#define CHAR_GRAVE_ACCENT '\140' -#define CHAR_a '\141' -#define CHAR_b '\142' -#define CHAR_c '\143' -#define CHAR_d '\144' -#define CHAR_e '\145' -#define CHAR_f '\146' -#define CHAR_g '\147' -#define CHAR_h '\150' -#define CHAR_i '\151' -#define CHAR_j '\152' -#define CHAR_k '\153' -#define CHAR_l '\154' -#define CHAR_m '\155' -#define CHAR_n '\156' -#define CHAR_o '\157' -#define CHAR_p '\160' -#define CHAR_q '\161' -#define CHAR_r '\162' -#define CHAR_s '\163' -#define CHAR_t '\164' -#define CHAR_u '\165' -#define CHAR_v '\166' -#define CHAR_w '\167' -#define CHAR_x '\170' -#define CHAR_y '\171' -#define CHAR_z '\172' -#define CHAR_LEFT_CURLY_BRACKET '\173' -#define CHAR_VERTICAL_LINE '\174' -#define CHAR_RIGHT_CURLY_BRACKET '\175' -#define CHAR_TILDE '\176' - -#define STR_HT "\011" -#define STR_VT "\013" -#define STR_FF "\014" -#define STR_CR "\015" -#define STR_NL "\012" -#define STR_BS "\010" -#define STR_BEL "\007" -#define STR_ESC "\033" -#define STR_DEL "\177" - -#define STR_SPACE "\040" -#define STR_EXCLAMATION_MARK "\041" -#define STR_QUOTATION_MARK "\042" -#define STR_NUMBER_SIGN "\043" -#define STR_DOLLAR_SIGN "\044" -#define STR_PERCENT_SIGN "\045" -#define STR_AMPERSAND "\046" -#define STR_APOSTROPHE "\047" -#define STR_LEFT_PARENTHESIS "\050" -#define STR_RIGHT_PARENTHESIS "\051" -#define STR_ASTERISK "\052" -#define STR_PLUS "\053" -#define STR_COMMA "\054" -#define STR_MINUS "\055" -#define STR_DOT "\056" -#define STR_SLASH "\057" -#define STR_0 "\060" -#define STR_1 "\061" -#define STR_2 "\062" -#define STR_3 "\063" -#define STR_4 "\064" -#define STR_5 "\065" -#define STR_6 "\066" -#define STR_7 "\067" -#define STR_8 "\070" -#define STR_9 "\071" -#define STR_COLON "\072" -#define STR_SEMICOLON "\073" -#define STR_LESS_THAN_SIGN "\074" -#define STR_EQUALS_SIGN "\075" -#define STR_GREATER_THAN_SIGN "\076" -#define STR_QUESTION_MARK "\077" -#define STR_COMMERCIAL_AT "\100" -#define STR_A "\101" -#define STR_B "\102" -#define STR_C "\103" -#define STR_D "\104" -#define STR_E "\105" -#define STR_F "\106" -#define STR_G "\107" -#define STR_H "\110" -#define STR_I "\111" -#define STR_J "\112" -#define STR_K "\113" -#define STR_L "\114" -#define STR_M "\115" -#define STR_N "\116" -#define STR_O "\117" -#define STR_P "\120" -#define STR_Q "\121" -#define STR_R "\122" -#define STR_S "\123" -#define STR_T "\124" -#define STR_U "\125" -#define STR_V "\126" -#define STR_W "\127" -#define STR_X "\130" -#define STR_Y "\131" -#define STR_Z "\132" -#define STR_LEFT_SQUARE_BRACKET "\133" -#define STR_BACKSLASH "\134" -#define STR_RIGHT_SQUARE_BRACKET "\135" -#define STR_CIRCUMFLEX_ACCENT "\136" -#define STR_UNDERSCORE "\137" -#define STR_GRAVE_ACCENT "\140" -#define STR_a "\141" -#define STR_b "\142" -#define STR_c "\143" -#define STR_d "\144" -#define STR_e "\145" -#define STR_f "\146" -#define STR_g "\147" -#define STR_h "\150" -#define STR_i "\151" -#define STR_j "\152" -#define STR_k "\153" -#define STR_l "\154" -#define STR_m "\155" -#define STR_n "\156" -#define STR_o "\157" -#define STR_p "\160" -#define STR_q "\161" -#define STR_r "\162" -#define STR_s "\163" -#define STR_t "\164" -#define STR_u "\165" -#define STR_v "\166" -#define STR_w "\167" -#define STR_x "\170" -#define STR_y "\171" -#define STR_z "\172" -#define STR_LEFT_CURLY_BRACKET "\173" -#define STR_VERTICAL_LINE "\174" -#define STR_RIGHT_CURLY_BRACKET "\175" -#define STR_TILDE "\176" - -#define STRING_ACCEPT0 STR_A STR_C STR_C STR_E STR_P STR_T "\0" -#define STRING_COMMIT0 STR_C STR_O STR_M STR_M STR_I STR_T "\0" -#define STRING_F0 STR_F "\0" -#define STRING_FAIL0 STR_F STR_A STR_I STR_L "\0" -#define STRING_MARK0 STR_M STR_A STR_R STR_K "\0" -#define STRING_PRUNE0 STR_P STR_R STR_U STR_N STR_E "\0" -#define STRING_SKIP0 STR_S STR_K STR_I STR_P "\0" -#define STRING_THEN STR_T STR_H STR_E STR_N - -#define STRING_alpha0 STR_a STR_l STR_p STR_h STR_a "\0" -#define STRING_lower0 STR_l STR_o STR_w STR_e STR_r "\0" -#define STRING_upper0 STR_u STR_p STR_p STR_e STR_r "\0" -#define STRING_alnum0 STR_a STR_l STR_n STR_u STR_m "\0" -#define STRING_ascii0 STR_a STR_s STR_c STR_i STR_i "\0" -#define STRING_blank0 STR_b STR_l STR_a STR_n STR_k "\0" -#define STRING_cntrl0 STR_c STR_n STR_t STR_r STR_l "\0" -#define STRING_digit0 STR_d STR_i STR_g STR_i STR_t "\0" -#define STRING_graph0 STR_g STR_r STR_a STR_p STR_h "\0" -#define STRING_print0 STR_p STR_r STR_i STR_n STR_t "\0" -#define STRING_punct0 STR_p STR_u STR_n STR_c STR_t "\0" -#define STRING_space0 STR_s STR_p STR_a STR_c STR_e "\0" -#define STRING_word0 STR_w STR_o STR_r STR_d "\0" -#define STRING_xdigit STR_x STR_d STR_i STR_g STR_i STR_t - -#define STRING_DEFINE STR_D STR_E STR_F STR_I STR_N STR_E - -#define STRING_CR_RIGHTPAR STR_C STR_R STR_RIGHT_PARENTHESIS -#define STRING_LF_RIGHTPAR STR_L STR_F STR_RIGHT_PARENTHESIS -#define STRING_CRLF_RIGHTPAR STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS -#define STRING_ANY_RIGHTPAR STR_A STR_N STR_Y STR_RIGHT_PARENTHESIS -#define STRING_ANYCRLF_RIGHTPAR STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS -#define STRING_BSR_ANYCRLF_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS -#define STRING_BSR_UNICODE_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_U STR_N STR_I STR_C STR_O STR_D STR_E STR_RIGHT_PARENTHESIS -#ifdef COMPILE_PCRE8 -#define STRING_UTF_RIGHTPAR STR_U STR_T STR_F STR_8 STR_RIGHT_PARENTHESIS -#endif -#ifdef COMPILE_PCRE16 -#define STRING_UTF_RIGHTPAR STR_U STR_T STR_F STR_1 STR_6 STR_RIGHT_PARENTHESIS -#endif -#define STRING_UCP_RIGHTPAR STR_U STR_C STR_P STR_RIGHT_PARENTHESIS -#define STRING_NO_START_OPT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_S STR_T STR_A STR_R STR_T STR_UNDERSCORE STR_O STR_P STR_T STR_RIGHT_PARENTHESIS - -#endif /* SUPPORT_UTF */ - -/* Escape items that are just an encoding of a particular data value. */ - -#ifndef ESC_e -#define ESC_e CHAR_ESC -#endif - -#ifndef ESC_f -#define ESC_f CHAR_FF -#endif - -#ifndef ESC_n -#define ESC_n CHAR_NL -#endif - -#ifndef ESC_r -#define ESC_r CHAR_CR -#endif - -/* We can't officially use ESC_t because it is a POSIX reserved identifier -(presumably because of all the others like size_t). */ - -#ifndef ESC_tee -#define ESC_tee CHAR_HT -#endif - -/* Codes for different types of Unicode property */ - -#define PT_ANY 0 /* Any property - matches all chars */ -#define PT_LAMP 1 /* L& - the union of Lu, Ll, Lt */ -#define PT_GC 2 /* Specified general characteristic (e.g. L) */ -#define PT_PC 3 /* Specified particular characteristic (e.g. Lu) */ -#define PT_SC 4 /* Script (e.g. Han) */ -#define PT_ALNUM 5 /* Alphanumeric - the union of L and N */ -#define PT_SPACE 6 /* Perl space - Z plus 9,10,12,13 */ -#define PT_PXSPACE 7 /* POSIX space - Z plus 9,10,11,12,13 */ -#define PT_WORD 8 /* Word - L plus N plus underscore */ - -/* Flag bits and data types for the extended class (OP_XCLASS) for classes that -contain characters with values greater than 255. */ - -#define XCL_NOT 0x01 /* Flag: this is a negative class */ -#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */ - -#define XCL_END 0 /* Marks end of individual items */ -#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */ -#define XCL_RANGE 2 /* A range (two multibyte chars) follows */ -#define XCL_PROP 3 /* Unicode property (2-byte property code follows) */ -#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */ - -/* These are escaped items that aren't just an encoding of a particular data -value such as \n. They must have non-zero values, as check_escape() returns -their negation. Also, they must appear in the same order as in the opcode -definitions below, up to ESC_z. There's a dummy for OP_ALLANY because it -corresponds to "." in DOTALL mode rather than an escape sequence. It is also -used for [^] in JavaScript compatibility mode, and for \C in non-utf mode. In -non-DOTALL mode, "." behaves like \N. - -The special values ESC_DU, ESC_du, etc. are used instead of ESC_D, ESC_d, etc. -when PCRE_UCP is set, when replacement of \d etc by \p sequences is required. -They must be contiguous, and remain in order so that the replacements can be -looked up from a table. - -The final escape must be ESC_REF as subsequent values are used for -backreferences (\1, \2, \3, etc). There are two tests in the code for an escape -greater than ESC_b and less than ESC_Z to detect the types that may be -repeated. These are the types that consume characters. If any new escapes are -put in between that don't consume a character, that code will have to change. -*/ - -enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, - ESC_W, ESC_w, ESC_N, ESC_dum, ESC_C, ESC_P, ESC_p, ESC_R, ESC_H, - ESC_h, ESC_V, ESC_v, ESC_X, ESC_Z, ESC_z, - ESC_E, ESC_Q, ESC_g, ESC_k, - ESC_DU, ESC_du, ESC_SU, ESC_su, ESC_WU, ESC_wu, - ESC_REF }; - -/* Opcode table: Starting from 1 (i.e. after OP_END), the values up to -OP_EOD must correspond in order to the list of escapes immediately above. - -*** NOTE NOTE NOTE *** Whenever this list is updated, the two macro definitions -that follow must also be updated to match. There are also tables called -"coptable" and "poptable" in pcre_dfa_exec.c that must be updated. */ - -enum { - OP_END, /* 0 End of pattern */ - - /* Values corresponding to backslashed metacharacters */ - - OP_SOD, /* 1 Start of data: \A */ - OP_SOM, /* 2 Start of match (subject + offset): \G */ - OP_SET_SOM, /* 3 Set start of match (\K) */ - OP_NOT_WORD_BOUNDARY, /* 4 \B */ - OP_WORD_BOUNDARY, /* 5 \b */ - OP_NOT_DIGIT, /* 6 \D */ - OP_DIGIT, /* 7 \d */ - OP_NOT_WHITESPACE, /* 8 \S */ - OP_WHITESPACE, /* 9 \s */ - OP_NOT_WORDCHAR, /* 10 \W */ - OP_WORDCHAR, /* 11 \w */ - - OP_ANY, /* 12 Match any character except newline */ - OP_ALLANY, /* 13 Match any character */ - OP_ANYBYTE, /* 14 Match any byte (\C); different to OP_ANY for UTF-8 */ - OP_NOTPROP, /* 15 \P (not Unicode property) */ - OP_PROP, /* 16 \p (Unicode property) */ - OP_ANYNL, /* 17 \R (any newline sequence) */ - OP_NOT_HSPACE, /* 18 \H (not horizontal whitespace) */ - OP_HSPACE, /* 19 \h (horizontal whitespace) */ - OP_NOT_VSPACE, /* 20 \V (not vertical whitespace) */ - OP_VSPACE, /* 21 \v (vertical whitespace) */ - OP_EXTUNI, /* 22 \X (extended Unicode sequence */ - OP_EODN, /* 23 End of data or \n at end of data: \Z. */ - OP_EOD, /* 24 End of data: \z */ - - OP_CIRC, /* 25 Start of line - not multiline */ - OP_CIRCM, /* 26 Start of line - multiline */ - OP_DOLL, /* 27 End of line - not multiline */ - OP_DOLLM, /* 28 End of line - multiline */ - OP_CHAR, /* 29 Match one character, casefully */ - OP_CHARI, /* 30 Match one character, caselessly */ - OP_NOT, /* 31 Match one character, not the given one, casefully */ - OP_NOTI, /* 32 Match one character, not the given one, caselessly */ - - /* The following sets of 13 opcodes must always be kept in step because - the offset from the first one is used to generate the others. */ - - /**** Single characters, caseful, must precede the caseless ones ****/ - - OP_STAR, /* 33 The maximizing and minimizing versions of */ - OP_MINSTAR, /* 34 these six opcodes must come in pairs, with */ - OP_PLUS, /* 35 the minimizing one second. */ - OP_MINPLUS, /* 36 */ - OP_QUERY, /* 37 */ - OP_MINQUERY, /* 38 */ - - OP_UPTO, /* 39 From 0 to n matches of one character, caseful*/ - OP_MINUPTO, /* 40 */ - OP_EXACT, /* 41 Exactly n matches */ - - OP_POSSTAR, /* 42 Possessified star, caseful */ - OP_POSPLUS, /* 43 Possessified plus, caseful */ - OP_POSQUERY, /* 44 Posesssified query, caseful */ - OP_POSUPTO, /* 45 Possessified upto, caseful */ - - /**** Single characters, caseless, must follow the caseful ones */ - - OP_STARI, /* 46 */ - OP_MINSTARI, /* 47 */ - OP_PLUSI, /* 48 */ - OP_MINPLUSI, /* 49 */ - OP_QUERYI, /* 50 */ - OP_MINQUERYI, /* 51 */ - - OP_UPTOI, /* 52 From 0 to n matches of one character, caseless */ - OP_MINUPTOI, /* 53 */ - OP_EXACTI, /* 54 */ - - OP_POSSTARI, /* 55 Possessified star, caseless */ - OP_POSPLUSI, /* 56 Possessified plus, caseless */ - OP_POSQUERYI, /* 57 Posesssified query, caseless */ - OP_POSUPTOI, /* 58 Possessified upto, caseless */ - - /**** The negated ones must follow the non-negated ones, and match them ****/ - /**** Negated single character, caseful; must precede the caseless ones ****/ - - OP_NOTSTAR, /* 59 The maximizing and minimizing versions of */ - OP_NOTMINSTAR, /* 60 these six opcodes must come in pairs, with */ - OP_NOTPLUS, /* 61 the minimizing one second. They must be in */ - OP_NOTMINPLUS, /* 62 exactly the same order as those above. */ - OP_NOTQUERY, /* 63 */ - OP_NOTMINQUERY, /* 64 */ - - OP_NOTUPTO, /* 65 From 0 to n matches, caseful */ - OP_NOTMINUPTO, /* 66 */ - OP_NOTEXACT, /* 67 Exactly n matches */ - - OP_NOTPOSSTAR, /* 68 Possessified versions, caseful */ - OP_NOTPOSPLUS, /* 69 */ - OP_NOTPOSQUERY, /* 70 */ - OP_NOTPOSUPTO, /* 71 */ - - /**** Negated single character, caseless; must follow the caseful ones ****/ - - OP_NOTSTARI, /* 72 */ - OP_NOTMINSTARI, /* 73 */ - OP_NOTPLUSI, /* 74 */ - OP_NOTMINPLUSI, /* 75 */ - OP_NOTQUERYI, /* 76 */ - OP_NOTMINQUERYI, /* 77 */ - - OP_NOTUPTOI, /* 78 From 0 to n matches, caseless */ - OP_NOTMINUPTOI, /* 79 */ - OP_NOTEXACTI, /* 80 Exactly n matches */ - - OP_NOTPOSSTARI, /* 81 Possessified versions, caseless */ - OP_NOTPOSPLUSI, /* 82 */ - OP_NOTPOSQUERYI, /* 83 */ - OP_NOTPOSUPTOI, /* 84 */ - - /**** Character types ****/ - - OP_TYPESTAR, /* 85 The maximizing and minimizing versions of */ - OP_TYPEMINSTAR, /* 86 these six opcodes must come in pairs, with */ - OP_TYPEPLUS, /* 87 the minimizing one second. These codes must */ - OP_TYPEMINPLUS, /* 88 be in exactly the same order as those above. */ - OP_TYPEQUERY, /* 89 */ - OP_TYPEMINQUERY, /* 90 */ - - OP_TYPEUPTO, /* 91 From 0 to n matches */ - OP_TYPEMINUPTO, /* 92 */ - OP_TYPEEXACT, /* 93 Exactly n matches */ - - OP_TYPEPOSSTAR, /* 94 Possessified versions */ - OP_TYPEPOSPLUS, /* 95 */ - OP_TYPEPOSQUERY, /* 96 */ - OP_TYPEPOSUPTO, /* 97 */ - - /* These are used for character classes and back references; only the - first six are the same as the sets above. */ - - OP_CRSTAR, /* 98 The maximizing and minimizing versions of */ - OP_CRMINSTAR, /* 99 all these opcodes must come in pairs, with */ - OP_CRPLUS, /* 100 the minimizing one second. These codes must */ - OP_CRMINPLUS, /* 101 be in exactly the same order as those above. */ - OP_CRQUERY, /* 102 */ - OP_CRMINQUERY, /* 103 */ - - OP_CRRANGE, /* 104 These are different to the three sets above. */ - OP_CRMINRANGE, /* 105 */ - - /* End of quantifier opcodes */ - - OP_CLASS, /* 106 Match a character class, chars < 256 only */ - OP_NCLASS, /* 107 Same, but the bitmap was created from a negative - class - the difference is relevant only when a - character > 255 is encountered. */ - OP_XCLASS, /* 108 Extended class for handling > 255 chars within the - class. This does both positive and negative. */ - OP_REF, /* 109 Match a back reference, casefully */ - OP_REFI, /* 110 Match a back reference, caselessly */ - OP_RECURSE, /* 111 Match a numbered subpattern (possibly recursive) */ - OP_CALLOUT, /* 112 Call out to external function if provided */ - - OP_ALT, /* 113 Start of alternation */ - OP_KET, /* 114 End of group that doesn't have an unbounded repeat */ - OP_KETRMAX, /* 115 These two must remain together and in this */ - OP_KETRMIN, /* 116 order. They are for groups the repeat for ever. */ - OP_KETRPOS, /* 117 Possessive unlimited repeat. */ - - /* The assertions must come before BRA, CBRA, ONCE, and COND, and the four - asserts must remain in order. */ - - OP_REVERSE, /* 118 Move pointer back - used in lookbehind assertions */ - OP_ASSERT, /* 119 Positive lookahead */ - OP_ASSERT_NOT, /* 120 Negative lookahead */ - OP_ASSERTBACK, /* 121 Positive lookbehind */ - OP_ASSERTBACK_NOT, /* 122 Negative lookbehind */ - - /* ONCE, ONCE_NC, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come immediately - after the assertions, with ONCE first, as there's a test for >= ONCE for a - subpattern that isn't an assertion. The POS versions must immediately follow - the non-POS versions in each case. */ - - OP_ONCE, /* 123 Atomic group, contains captures */ - OP_ONCE_NC, /* 124 Atomic group containing no captures */ - OP_BRA, /* 125 Start of non-capturing bracket */ - OP_BRAPOS, /* 126 Ditto, with unlimited, possessive repeat */ - OP_CBRA, /* 127 Start of capturing bracket */ - OP_CBRAPOS, /* 128 Ditto, with unlimited, possessive repeat */ - OP_COND, /* 129 Conditional group */ - - /* These five must follow the previous five, in the same order. There's a - check for >= SBRA to distinguish the two sets. */ - - OP_SBRA, /* 130 Start of non-capturing bracket, check empty */ - OP_SBRAPOS, /* 131 Ditto, with unlimited, possessive repeat */ - OP_SCBRA, /* 132 Start of capturing bracket, check empty */ - OP_SCBRAPOS, /* 133 Ditto, with unlimited, possessive repeat */ - OP_SCOND, /* 134 Conditional group, check empty */ - - /* The next two pairs must (respectively) be kept together. */ - - OP_CREF, /* 135 Used to hold a capture number as condition */ - OP_NCREF, /* 136 Same, but generated by a name reference*/ - OP_RREF, /* 137 Used to hold a recursion number as condition */ - OP_NRREF, /* 138 Same, but generated by a name reference*/ - OP_DEF, /* 139 The DEFINE condition */ - - OP_BRAZERO, /* 140 These two must remain together and in this */ - OP_BRAMINZERO, /* 141 order. */ - OP_BRAPOSZERO, /* 142 */ - - /* These are backtracking control verbs */ - - OP_MARK, /* 143 always has an argument */ - OP_PRUNE, /* 144 */ - OP_PRUNE_ARG, /* 145 same, but with argument */ - OP_SKIP, /* 146 */ - OP_SKIP_ARG, /* 147 same, but with argument */ - OP_THEN, /* 148 */ - OP_THEN_ARG, /* 149 same, but with argument */ - OP_COMMIT, /* 150 */ - - /* These are forced failure and success verbs */ - - OP_FAIL, /* 151 */ - OP_ACCEPT, /* 152 */ - OP_ASSERT_ACCEPT, /* 153 Used inside assertions */ - OP_CLOSE, /* 154 Used before OP_ACCEPT to close open captures */ - - /* This is used to skip a subpattern with a {0} quantifier */ - - OP_SKIPZERO, /* 155 */ - - /* This is not an opcode, but is used to check that tables indexed by opcode - are the correct length, in order to catch updating errors - there have been - some in the past. */ - - OP_TABLE_LENGTH -}; - -/* *** NOTE NOTE NOTE *** Whenever the list above is updated, the two macro -definitions that follow must also be updated to match. There are also tables -called "coptable" and "poptable" in pcre_dfa_exec.c that must be updated. */ - - -/* This macro defines textual names for all the opcodes. These are used only -for debugging, and some of them are only partial names. The macro is referenced -only in pcre_printint.c, which fills out the full names in many cases (and in -some cases doesn't actually use these names at all). */ - -#define OP_NAME_LIST \ - "End", "\\A", "\\G", "\\K", "\\B", "\\b", "\\D", "\\d", \ - "\\S", "\\s", "\\W", "\\w", "Any", "AllAny", "Anybyte", \ - "notprop", "prop", "\\R", "\\H", "\\h", "\\V", "\\v", \ - "extuni", "\\Z", "\\z", \ - "^", "^", "$", "$", "char", "chari", "not", "noti", \ - "*", "*?", "+", "+?", "?", "??", \ - "{", "{", "{", \ - "*+","++", "?+", "{", \ - "*", "*?", "+", "+?", "?", "??", \ - "{", "{", "{", \ - "*+","++", "?+", "{", \ - "*", "*?", "+", "+?", "?", "??", \ - "{", "{", "{", \ - "*+","++", "?+", "{", \ - "*", "*?", "+", "+?", "?", "??", \ - "{", "{", "{", \ - "*+","++", "?+", "{", \ - "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ - "*+","++", "?+", "{", \ - "*", "*?", "+", "+?", "?", "??", "{", "{", \ - "class", "nclass", "xclass", "Ref", "Refi", \ - "Recurse", "Callout", \ - "Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \ - "Reverse", "Assert", "Assert not", "AssertB", "AssertB not", \ - "Once", "Once_NC", \ - "Bra", "BraPos", "CBra", "CBraPos", \ - "Cond", \ - "SBra", "SBraPos", "SCBra", "SCBraPos", \ - "SCond", \ - "Cond ref", "Cond nref", "Cond rec", "Cond nrec", "Cond def", \ - "Brazero", "Braminzero", "Braposzero", \ - "*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \ - "*THEN", "*THEN", "*COMMIT", "*FAIL", \ - "*ACCEPT", "*ASSERT_ACCEPT", \ - "Close", "Skip zero" - - -/* This macro defines the length of fixed length operations in the compiled -regex. The lengths are used when searching for specific things, and also in the -debugging printing of a compiled regex. We use a macro so that it can be -defined close to the definitions of the opcodes themselves. - -As things have been extended, some of these are no longer fixed lenths, but are -minima instead. For example, the length of a single-character repeat may vary -in UTF-8 mode. The code that uses this table must know about such things. */ - -#define OP_LENGTHS \ - 1, /* End */ \ - 1, 1, 1, 1, 1, /* \A, \G, \K, \B, \b */ \ - 1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */ \ - 1, 1, 1, /* Any, AllAny, Anybyte */ \ - 3, 3, /* \P, \p */ \ - 1, 1, 1, 1, 1, /* \R, \H, \h, \V, \v */ \ - 1, /* \X */ \ - 1, 1, 1, 1, 1, 1, /* \Z, \z, ^, ^M, $, $M */ \ - 2, /* Char - the minimum length */ \ - 2, /* Chari - the minimum length */ \ - 2, /* not */ \ - 2, /* noti */ \ - /* Positive single-char repeats ** These are */ \ - 2, 2, 2, 2, 2, 2, /* *, *?, +, +?, ?, ?? ** minima in */ \ - 2+IMM2_SIZE, 2+IMM2_SIZE, /* upto, minupto ** mode */ \ - 2+IMM2_SIZE, /* exact */ \ - 2, 2, 2, 2+IMM2_SIZE, /* *+, ++, ?+, upto+ */ \ - 2, 2, 2, 2, 2, 2, /* *I, *?I, +I, +?I, ?I, ??I ** UTF-8 */ \ - 2+IMM2_SIZE, 2+IMM2_SIZE, /* upto I, minupto I */ \ - 2+IMM2_SIZE, /* exact I */ \ - 2, 2, 2, 2+IMM2_SIZE, /* *+I, ++I, ?+I, upto+I */ \ - /* Negative single-char repeats - only for chars < 256 */ \ - 2, 2, 2, 2, 2, 2, /* NOT *, *?, +, +?, ?, ?? */ \ - 2+IMM2_SIZE, 2+IMM2_SIZE, /* NOT upto, minupto */ \ - 2+IMM2_SIZE, /* NOT exact */ \ - 2, 2, 2, 2+IMM2_SIZE, /* Possessive NOT *, +, ?, upto */ \ - 2, 2, 2, 2, 2, 2, /* NOT *I, *?I, +I, +?I, ?I, ??I */ \ - 2+IMM2_SIZE, 2+IMM2_SIZE, /* NOT upto I, minupto I */ \ - 2+IMM2_SIZE, /* NOT exact I */ \ - 2, 2, 2, 2+IMM2_SIZE, /* Possessive NOT *I, +I, ?I, upto I */ \ - /* Positive type repeats */ \ - 2, 2, 2, 2, 2, 2, /* Type *, *?, +, +?, ?, ?? */ \ - 2+IMM2_SIZE, 2+IMM2_SIZE, /* Type upto, minupto */ \ - 2+IMM2_SIZE, /* Type exact */ \ - 2, 2, 2, 2+IMM2_SIZE, /* Possessive *+, ++, ?+, upto+ */ \ - /* Character class & ref repeats */ \ - 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ \ - 1+2*IMM2_SIZE, 1+2*IMM2_SIZE, /* CRRANGE, CRMINRANGE */ \ - 1+(32/sizeof(pcre_uchar)), /* CLASS */ \ - 1+(32/sizeof(pcre_uchar)), /* NCLASS */ \ - 0, /* XCLASS - variable length */ \ - 1+IMM2_SIZE, /* REF */ \ - 1+IMM2_SIZE, /* REFI */ \ - 1+LINK_SIZE, /* RECURSE */ \ - 2+2*LINK_SIZE, /* CALLOUT */ \ - 1+LINK_SIZE, /* Alt */ \ - 1+LINK_SIZE, /* Ket */ \ - 1+LINK_SIZE, /* KetRmax */ \ - 1+LINK_SIZE, /* KetRmin */ \ - 1+LINK_SIZE, /* KetRpos */ \ - 1+LINK_SIZE, /* Reverse */ \ - 1+LINK_SIZE, /* Assert */ \ - 1+LINK_SIZE, /* Assert not */ \ - 1+LINK_SIZE, /* Assert behind */ \ - 1+LINK_SIZE, /* Assert behind not */ \ - 1+LINK_SIZE, /* ONCE */ \ - 1+LINK_SIZE, /* ONCE_NC */ \ - 1+LINK_SIZE, /* BRA */ \ - 1+LINK_SIZE, /* BRAPOS */ \ - 1+LINK_SIZE+IMM2_SIZE, /* CBRA */ \ - 1+LINK_SIZE+IMM2_SIZE, /* CBRAPOS */ \ - 1+LINK_SIZE, /* COND */ \ - 1+LINK_SIZE, /* SBRA */ \ - 1+LINK_SIZE, /* SBRAPOS */ \ - 1+LINK_SIZE+IMM2_SIZE, /* SCBRA */ \ - 1+LINK_SIZE+IMM2_SIZE, /* SCBRAPOS */ \ - 1+LINK_SIZE, /* SCOND */ \ - 1+IMM2_SIZE, 1+IMM2_SIZE, /* CREF, NCREF */ \ - 1+IMM2_SIZE, 1+IMM2_SIZE, /* RREF, NRREF */ \ - 1, /* DEF */ \ - 1, 1, 1, /* BRAZERO, BRAMINZERO, BRAPOSZERO */ \ - 3, 1, 3, /* MARK, PRUNE, PRUNE_ARG */ \ - 1, 3, /* SKIP, SKIP_ARG */ \ - 1, 3, /* THEN, THEN_ARG */ \ - 1, 1, 1, 1, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */ \ - 1+IMM2_SIZE, 1 /* CLOSE, SKIPZERO */ - -/* A magic value for OP_RREF and OP_NRREF to indicate the "any recursion" -condition. */ - -#define RREF_ANY 0xffff - -/* Compile time error code numbers. They are given names so that they can more -easily be tracked. When a new number is added, the table called eint in -pcreposix.c must be updated. */ - -enum { ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, - ERR10, ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, - ERR20, ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, - ERR30, ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, - ERR40, ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49, - ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59, - ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, - ERR70, ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERRCOUNT }; - -/* JIT compiling modes. The function list is indexed by them. */ -enum { JIT_COMPILE, JIT_PARTIAL_SOFT_COMPILE, JIT_PARTIAL_HARD_COMPILE, - JIT_NUMBER_OF_COMPILE_MODES }; - -/* The real format of the start of the pcre block; the index of names and the -code vector run on as long as necessary after the end. We store an explicit -offset to the name table so that if a regex is compiled on one host, saved, and -then run on another where the size of pointers is different, all might still -be well. For the case of compiled-on-4 and run-on-8, we include an extra -pointer that is always NULL. For future-proofing, a few dummy fields were -originally included - even though you can never get this planning right - but -there is only one left now. - -NOTE NOTE NOTE: -Because people can now save and re-use compiled patterns, any additions to this -structure should be made at the end, and something earlier (e.g. a new -flag in the options or one of the dummy fields) should indicate that the new -fields are present. Currently PCRE always sets the dummy fields to zero. -NOTE NOTE NOTE -*/ - -#ifdef COMPILE_PCRE8 -#define REAL_PCRE real_pcre -#else -#define REAL_PCRE real_pcre16 -#endif - -typedef struct REAL_PCRE { - pcre_uint32 magic_number; - pcre_uint32 size; /* Total that was malloced */ - pcre_uint32 options; /* Public options */ - pcre_uint16 flags; /* Private flags */ - pcre_uint16 max_lookbehind; /* Longest lookbehind (characters) */ - pcre_uint16 top_bracket; /* Highest numbered group */ - pcre_uint16 top_backref; /* Highest numbered back reference */ - pcre_uint16 first_char; /* Starting character */ - pcre_uint16 req_char; /* This character must be seen */ - pcre_uint16 name_table_offset; /* Offset to name table that follows */ - pcre_uint16 name_entry_size; /* Size of any name items */ - pcre_uint16 name_count; /* Number of name items */ - pcre_uint16 ref_count; /* Reference count */ - const pcre_uint8 *tables; /* Pointer to tables or NULL for std */ - const pcre_uint8 *nullpad; /* NULL padding */ -} REAL_PCRE; - -/* The format of the block used to store data from pcre_study(). The same -remark (see NOTE above) about extending this structure applies. */ - -typedef struct pcre_study_data { - pcre_uint32 size; /* Total that was malloced */ - pcre_uint32 flags; /* Private flags */ - pcre_uint8 start_bits[32]; /* Starting char bits */ - pcre_uint32 minlength; /* Minimum subject length */ -} pcre_study_data; - -/* Structure for building a chain of open capturing subpatterns during -compiling, so that instructions to close them can be compiled when (*ACCEPT) is -encountered. This is also used to identify subpatterns that contain recursive -back references to themselves, so that they can be made atomic. */ - -typedef struct open_capitem { - struct open_capitem *next; /* Chain link */ - pcre_uint16 number; /* Capture number */ - pcre_uint16 flag; /* Set TRUE if recursive back ref */ -} open_capitem; - -/* Structure for passing "static" information around between the functions -doing the compiling, so that they are thread-safe. */ - -typedef struct compile_data { - const pcre_uint8 *lcc; /* Points to lower casing table */ - const pcre_uint8 *fcc; /* Points to case-flipping table */ - const pcre_uint8 *cbits; /* Points to character type table */ - const pcre_uint8 *ctypes; /* Points to table of type maps */ - const pcre_uchar *start_workspace;/* The start of working space */ - const pcre_uchar *start_code; /* The start of the compiled code */ - const pcre_uchar *start_pattern; /* The start of the pattern */ - const pcre_uchar *end_pattern; /* The end of the pattern */ - open_capitem *open_caps; /* Chain of open capture items */ - pcre_uchar *hwm; /* High watermark of workspace */ - pcre_uchar *name_table; /* The name/number table */ - int names_found; /* Number of entries so far */ - int name_entry_size; /* Size of each entry */ - int workspace_size; /* Size of workspace */ - int bracount; /* Count of capturing parens as we compile */ - int final_bracount; /* Saved value after first pass */ - int max_lookbehind; /* Maximum lookbehind (characters) */ - int top_backref; /* Maximum back reference */ - unsigned int backref_map; /* Bitmap of low back refs */ - int assert_depth; /* Depth of nested assertions */ - int external_options; /* External (initial) options */ - int external_flags; /* External flag bits to be set */ - int req_varyopt; /* "After variable item" flag for reqbyte */ - BOOL had_accept; /* (*ACCEPT) encountered */ - BOOL check_lookbehind; /* Lookbehinds need later checking */ - int nltype; /* Newline type */ - int nllen; /* Newline string length */ - pcre_uchar nl[4]; /* Newline string when fixed length */ -} compile_data; - -/* Structure for maintaining a chain of pointers to the currently incomplete -branches, for testing for left recursion while compiling. */ - -typedef struct branch_chain { - struct branch_chain *outer; - pcre_uchar *current_branch; -} branch_chain; - -/* Structure for items in a linked list that represents an explicit recursive -call within the pattern; used by pcre_exec(). */ - -typedef struct recursion_info { - struct recursion_info *prevrec; /* Previous recursion record (or NULL) */ - int group_num; /* Number of group that was called */ - int *offset_save; /* Pointer to start of saved offsets */ - int saved_max; /* Number of saved offsets */ - PCRE_PUCHAR subject_position; /* Position at start of recursion */ -} recursion_info; - -/* A similar structure for pcre_dfa_exec(). */ - -typedef struct dfa_recursion_info { - struct dfa_recursion_info *prevrec; - int group_num; - PCRE_PUCHAR subject_position; -} dfa_recursion_info; - -/* Structure for building a chain of data for holding the values of the subject -pointer at the start of each subpattern, so as to detect when an empty string -has been matched by a subpattern - to break infinite loops; used by -pcre_exec(). */ - -typedef struct eptrblock { - struct eptrblock *epb_prev; - PCRE_PUCHAR epb_saved_eptr; -} eptrblock; - - -/* Structure for passing "static" information around between the functions -doing traditional NFA matching, so that they are thread-safe. */ - -typedef struct match_data { - unsigned long int match_call_count; /* As it says */ - unsigned long int match_limit; /* As it says */ - unsigned long int match_limit_recursion; /* As it says */ - int *offset_vector; /* Offset vector */ - int offset_end; /* One past the end */ - int offset_max; /* The maximum usable for return data */ - int nltype; /* Newline type */ - int nllen; /* Newline string length */ - int name_count; /* Number of names in name table */ - int name_entry_size; /* Size of entry in names table */ - pcre_uchar *name_table; /* Table of names */ - pcre_uchar nl[4]; /* Newline string when fixed */ - const pcre_uint8 *lcc; /* Points to lower casing table */ - const pcre_uint8 *fcc; /* Points to case-flipping table */ - const pcre_uint8 *ctypes; /* Points to table of type maps */ - BOOL offset_overflow; /* Set if too many extractions */ - BOOL notbol; /* NOTBOL flag */ - BOOL noteol; /* NOTEOL flag */ - BOOL utf; /* UTF-8 / UTF-16 flag */ - BOOL jscript_compat; /* JAVASCRIPT_COMPAT flag */ - BOOL use_ucp; /* PCRE_UCP flag */ - BOOL endonly; /* Dollar not before final \n */ - BOOL notempty; /* Empty string match not wanted */ - BOOL notempty_atstart; /* Empty string match at start not wanted */ - BOOL hitend; /* Hit the end of the subject at some point */ - BOOL bsr_anycrlf; /* \R is just any CRLF, not full Unicode */ - BOOL hasthen; /* Pattern contains (*THEN) */ - BOOL ignore_skip_arg; /* For re-run when SKIP name not found */ - const pcre_uchar *start_code; /* For use when recursing */ - PCRE_PUCHAR start_subject; /* Start of the subject string */ - PCRE_PUCHAR end_subject; /* End of the subject string */ - PCRE_PUCHAR start_match_ptr; /* Start of matched string */ - PCRE_PUCHAR end_match_ptr; /* Subject position at end match */ - PCRE_PUCHAR start_used_ptr; /* Earliest consulted character */ - int partial; /* PARTIAL options */ - int end_offset_top; /* Highwater mark at end of match */ - int capture_last; /* Most recent capture number */ - int start_offset; /* The start offset value */ - int match_function_type; /* Set for certain special calls of MATCH() */ - eptrblock *eptrchain; /* Chain of eptrblocks for tail recursions */ - int eptrn; /* Next free eptrblock */ - recursion_info *recursive; /* Linked list of recursion data */ - void *callout_data; /* To pass back to callouts */ - const pcre_uchar *mark; /* Mark pointer to pass back on success */ - const pcre_uchar *nomatch_mark;/* Mark pointer to pass back on failure */ - const pcre_uchar *once_target; /* Where to back up to for atomic groups */ -#ifdef NO_RECURSE - void *match_frames_base; /* For remembering malloc'd frames */ -#endif -} match_data; - -/* A similar structure is used for the same purpose by the DFA matching -functions. */ - -typedef struct dfa_match_data { - const pcre_uchar *start_code; /* Start of the compiled pattern */ - const pcre_uchar *start_subject ; /* Start of the subject string */ - const pcre_uchar *end_subject; /* End of subject string */ - const pcre_uchar *start_used_ptr; /* Earliest consulted character */ - const pcre_uint8 *tables; /* Character tables */ - int start_offset; /* The start offset value */ - int moptions; /* Match options */ - int poptions; /* Pattern options */ - int nltype; /* Newline type */ - int nllen; /* Newline string length */ - pcre_uchar nl[4]; /* Newline string when fixed */ - void *callout_data; /* To pass back to callouts */ - dfa_recursion_info *recursive; /* Linked list of recursion data */ -} dfa_match_data; - -/* Bit definitions for entries in the pcre_ctypes table. */ - -#define ctype_space 0x01 -#define ctype_letter 0x02 -#define ctype_digit 0x04 -#define ctype_xdigit 0x08 -#define ctype_word 0x10 /* alphanumeric or '_' */ -#define ctype_meta 0x80 /* regexp meta char or zero (end pattern) */ - -/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set -of bits for a class map. Some classes are built by combining these tables. */ - -#define cbit_space 0 /* [:space:] or \s */ -#define cbit_xdigit 32 /* [:xdigit:] */ -#define cbit_digit 64 /* [:digit:] or \d */ -#define cbit_upper 96 /* [:upper:] */ -#define cbit_lower 128 /* [:lower:] */ -#define cbit_word 160 /* [:word:] or \w */ -#define cbit_graph 192 /* [:graph:] */ -#define cbit_print 224 /* [:print:] */ -#define cbit_punct 256 /* [:punct:] */ -#define cbit_cntrl 288 /* [:cntrl:] */ -#define cbit_length 320 /* Length of the cbits table */ - -/* Offsets of the various tables from the base tables pointer, and -total length. */ - -#define lcc_offset 0 -#define fcc_offset 256 -#define cbits_offset 512 -#define ctypes_offset (cbits_offset + cbit_length) -#define tables_length (ctypes_offset + 256) - -/* Internal function and data prefixes. */ - -#ifdef COMPILE_PCRE8 -#ifndef PUBL -#define PUBL(name) pcre_##name -#endif -#ifndef PRIV -#define PRIV(name) _pcre_##name -#endif -#else /* COMPILE_PCRE8 */ -#ifdef COMPILE_PCRE16 -#ifndef PUBL -#define PUBL(name) pcre16_##name -#endif -#ifndef PRIV -#define PRIV(name) _pcre16_##name -#endif -#else -#error Unsupported compiling mode -#endif /* COMPILE_PCRE16 */ -#endif /* COMPILE_PCRE8 */ - -/* Layout of the UCP type table that translates property names into types and -codes. Each entry used to point directly to a name, but to reduce the number of -relocations in shared libraries, it now has an offset into a single string -instead. */ - -typedef struct { - pcre_uint16 name_offset; - pcre_uint16 type; - pcre_uint16 value; -} ucp_type_table; - - -/* Internal shared data tables. These are tables that are used by more than one -of the exported public functions. They have to be "external" in the C sense, -but are not part of the PCRE public API. The data for these tables is in the -pcre_tables.c module. */ - -#ifdef COMPILE_PCRE8 - -extern const int PRIV(utf8_table1)[]; -extern const int PRIV(utf8_table1_size); -extern const int PRIV(utf8_table2)[]; -extern const int PRIV(utf8_table3)[]; -extern const pcre_uint8 PRIV(utf8_table4)[]; - -#endif /* COMPILE_PCRE8 */ - -extern const char PRIV(utt_names)[]; -extern const ucp_type_table PRIV(utt)[]; -extern const int PRIV(utt_size); - -extern const pcre_uint8 PRIV(default_tables)[]; - -extern const pcre_uint8 PRIV(OP_lengths)[]; - - -/* Internal shared functions. These are functions that are used by more than -one of the exported public functions. They have to be "external" in the C -sense, but are not part of the PCRE public API. */ - -/* String comparison functions. */ -#ifdef COMPILE_PCRE8 - -#define STRCMP_UC_UC(str1, str2) \ - strcmp((char *)(str1), (char *)(str2)) -#define STRCMP_UC_C8(str1, str2) \ - strcmp((char *)(str1), (str2)) -#define STRNCMP_UC_UC(str1, str2, num) \ - strncmp((char *)(str1), (char *)(str2), (num)) -#define STRNCMP_UC_C8(str1, str2, num) \ - strncmp((char *)(str1), (str2), (num)) -#define STRLEN_UC(str) strlen((const char *)str) - -#else - -extern int PRIV(strcmp_uc_uc)(const pcre_uchar *, - const pcre_uchar *); -extern int PRIV(strcmp_uc_c8)(const pcre_uchar *, - const char *); -extern int PRIV(strncmp_uc_uc)(const pcre_uchar *, - const pcre_uchar *, unsigned int num); -extern int PRIV(strncmp_uc_c8)(const pcre_uchar *, - const char *, unsigned int num); -extern unsigned int PRIV(strlen_uc)(const pcre_uchar *str); - -#define STRCMP_UC_UC(str1, str2) \ - PRIV(strcmp_uc_uc)((str1), (str2)) -#define STRCMP_UC_C8(str1, str2) \ - PRIV(strcmp_uc_c8)((str1), (str2)) -#define STRNCMP_UC_UC(str1, str2, num) \ - PRIV(strncmp_uc_uc)((str1), (str2), (num)) -#define STRNCMP_UC_C8(str1, str2, num) \ - PRIV(strncmp_uc_c8)((str1), (str2), (num)) -#define STRLEN_UC(str) PRIV(strlen_uc)(str) - -#endif /* COMPILE_PCRE8 */ - -extern const pcre_uchar *PRIV(find_bracket)(const pcre_uchar *, BOOL, int); -extern BOOL PRIV(is_newline)(PCRE_PUCHAR, int, PCRE_PUCHAR, - int *, BOOL); -extern int PRIV(ord2utf)(pcre_uint32, pcre_uchar *); -extern int PRIV(valid_utf)(PCRE_PUCHAR, int, int *); -extern BOOL PRIV(was_newline)(PCRE_PUCHAR, int, PCRE_PUCHAR, - int *, BOOL); -extern BOOL PRIV(xclass)(int, const pcre_uchar *, BOOL); - -#ifdef SUPPORT_JIT -extern void PRIV(jit_compile)(const REAL_PCRE *, - PUBL(extra) *, int); -extern int PRIV(jit_exec)(const REAL_PCRE *, const PUBL(extra) *, - const pcre_uchar *, int, int, int, int *, int); -extern void PRIV(jit_free)(void *); -extern int PRIV(jit_get_size)(void *); -extern const char* PRIV(jit_get_target)(void); -#endif - -/* Unicode character database (UCD) */ - -extern const int PRIV(ucp_gentype)[]; -#ifdef SUPPORT_JIT -extern const int PRIV(ucp_typerange)[]; -#endif - -#ifdef SUPPORT_UCP -/* UCD access macros */ - -unsigned int _pcre_ucp_othercase(const unsigned int c); - -#define UCD_CHARTYPE(ch) (pcre_uint8)g_unichar_type((gunichar)(ch)) -#define UCD_SCRIPT(ch) (pcre_uint8)g_unichar_get_script((gunichar)(ch)) -#define UCD_CATEGORY(ch) PRIV(ucp_gentype)[UCD_CHARTYPE(ch)] -#define UCD_OTHERCASE(ch) (_pcre_ucp_othercase(ch)) - -#endif /* SUPPORT_UCP */ - -#endif - -/* End of pcre_internal.h */ diff --git a/glib/pcre/pcre_jit_compile.c b/glib/pcre/pcre_jit_compile.c deleted file mode 100644 index d7233832f..000000000 --- a/glib/pcre/pcre_jit_compile.c +++ /dev/null @@ -1,7497 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - - The machine code generator part (this module) was written by Zoltan Herczeg - Copyright (c) 2010-2012 - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - -#include "config.h" - -#include "pcre_internal.h" - -#ifdef SUPPORT_JIT - -/* All-in-one: Since we use the JIT compiler only from here, -we just include it. This way we don't need to touch the build -system files. */ - -#define SLJIT_MALLOC(size) (PUBL(malloc))(size) -#define SLJIT_FREE(ptr) (PUBL(free))(ptr) -#define SLJIT_CONFIG_AUTO 1 -#define SLJIT_CONFIG_STATIC 1 -#define SLJIT_VERBOSE 0 -#define SLJIT_DEBUG 0 - -#include "sljit/sljitLir.c" - -#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED -#error Unsupported architecture -#endif - -/* Allocate memory on the stack. Fast, but limited size. */ -#define LOCAL_SPACE_SIZE 32768 - -#define STACK_GROWTH_RATE 8192 - -/* Enable to check that the allocation could destroy temporaries. */ -#if defined SLJIT_DEBUG && SLJIT_DEBUG -#define DESTROY_REGISTERS 1 -#endif - -/* -Short summary about the backtracking mechanism empolyed by the jit code generator: - -The code generator follows the recursive nature of the PERL compatible regular -expressions. The basic blocks of regular expressions are condition checkers -whose execute different commands depending on the result of the condition check. -The relationship between the operators can be horizontal (concatenation) and -vertical (sub-expression) (See struct backtrack_common for more details). - - 'ab' - 'a' and 'b' regexps are concatenated - 'a+' - 'a' is the sub-expression of the '+' operator - -The condition checkers are boolean (true/false) checkers. Machine code is generated -for the checker itself and for the actions depending on the result of the checker. -The 'true' case is called as the try path (expected path), and the other is called as -the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken -branches on the try path. - - Greedy star operator (*) : - Try path: match happens. - Backtrack path: match failed. - Non-greedy star operator (*?) : - Try path: no need to perform a match. - Backtrack path: match is required. - -The following example shows how the code generated for a capturing bracket -with two alternatives. Let A, B, C, D are arbirary regular expressions, and -we have the following regular expression: - - A(B|C)D - -The generated code will be the following: - - A try path - '(' try path (pushing arguments to the stack) - B try path - ')' try path (pushing arguments to the stack) - D try path - return with successful match - - D backtrack path - ')' backtrack path (If we arrived from "C" jump to the backtrack of "C") - B backtrack path - C expected path - jump to D try path - C backtrack path - A backtrack path - - Notice, that the order of backtrack code paths are the opposite of the fast - code paths. In this way the topmost value on the stack is always belong - to the current backtrack code path. The backtrack path must check - whether there is a next alternative. If so, it needs to jump back to - the try path eventually. Otherwise it needs to clear out its own stack - frame and continue the execution on the backtrack code paths. -*/ - -/* -Saved stack frames: - -Atomic blocks and asserts require reloading the values of local variables -when the backtrack mechanism performed. Because of OP_RECURSE, the locals -are not necessarly known in compile time, thus we need a dynamic restore -mechanism. - -The stack frames are stored in a chain list, and have the following format: -([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ] - -Thus we can restore the locals to a particular point in the stack. -*/ - -typedef struct jit_arguments { - /* Pointers first. */ - struct sljit_stack *stack; - const pcre_uchar *str; - const pcre_uchar *begin; - const pcre_uchar *end; - int *offsets; - pcre_uchar *uchar_ptr; - pcre_uchar *mark_ptr; - /* Everything else after. */ - int offsetcount; - int calllimit; - pcre_uint8 notbol; - pcre_uint8 noteol; - pcre_uint8 notempty; - pcre_uint8 notempty_atstart; -} jit_arguments; - -typedef struct executable_functions { - void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES]; - PUBL(jit_callback) callback; - void *userdata; - sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES]; -} executable_functions; - -typedef struct jump_list { - struct sljit_jump *jump; - struct jump_list *next; -} jump_list; - -enum stub_types { stack_alloc }; - -typedef struct stub_list { - enum stub_types type; - int data; - struct sljit_jump *start; - struct sljit_label *leave; - struct stub_list *next; -} stub_list; - -typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); - -/* The following structure is the key data type for the recursive -code generator. It is allocated by compile_trypath, and contains -the aguments for compile_backtrackpath. Must be the first member -of its descendants. */ -typedef struct backtrack_common { - /* Concatenation stack. */ - struct backtrack_common *prev; - jump_list *nextbacktracks; - /* Internal stack (for component operators). */ - struct backtrack_common *top; - jump_list *topbacktracks; - /* Opcode pointer. */ - pcre_uchar *cc; -} backtrack_common; - -typedef struct assert_backtrack { - backtrack_common common; - jump_list *condfailed; - /* Less than 0 (-1) if a frame is not needed. */ - int framesize; - /* Points to our private memory word on the stack. */ - int localptr; - /* For iterators. */ - struct sljit_label *trypath; -} assert_backtrack; - -typedef struct bracket_backtrack { - backtrack_common common; - /* Where to coninue if an alternative is successfully matched. */ - struct sljit_label *alttrypath; - /* For rmin and rmax iterators. */ - struct sljit_label *recursivetrypath; - /* For greedy ? operator. */ - struct sljit_label *zerotrypath; - /* Contains the branches of a failed condition. */ - union { - /* Both for OP_COND, OP_SCOND. */ - jump_list *condfailed; - assert_backtrack *assert; - /* For OP_ONCE. -1 if not needed. */ - int framesize; - } u; - /* Points to our private memory word on the stack. */ - int localptr; -} bracket_backtrack; - -typedef struct bracketpos_backtrack { - backtrack_common common; - /* Points to our private memory word on the stack. */ - int localptr; - /* Reverting stack is needed. */ - int framesize; - /* Allocated stack size. */ - int stacksize; -} bracketpos_backtrack; - -typedef struct braminzero_backtrack { - backtrack_common common; - struct sljit_label *trypath; -} braminzero_backtrack; - -typedef struct iterator_backtrack { - backtrack_common common; - /* Next iteration. */ - struct sljit_label *trypath; -} iterator_backtrack; - -typedef struct recurse_entry { - struct recurse_entry *next; - /* Contains the function entry. */ - struct sljit_label *entry; - /* Collects the calls until the function is not created. */ - jump_list *calls; - /* Points to the starting opcode. */ - int start; -} recurse_entry; - -typedef struct recurse_backtrack { - backtrack_common common; -} recurse_backtrack; - -typedef struct compiler_common { - struct sljit_compiler *compiler; - pcre_uchar *start; - - /* Opcode local area direct map. */ - int *localptrs; - int cbraptr; - /* OVector starting point. Must be divisible by 2. */ - int ovector_start; - /* Last known position of the requested byte. */ - int req_char_ptr; - /* Head of the last recursion. */ - int recursive_head; - /* First inspected character for partial matching. */ - int start_used_ptr; - /* Starting pointer for partial soft matches. */ - int hit_start; - /* End pointer of the first line. */ - int first_line_end; - /* Points to the marked string. */ - int mark_ptr; - - /* Other */ - const pcre_uint8 *fcc; - sljit_w lcc; - int mode; - int nltype; - int newline; - int bsr_nltype; - int endonly; - BOOL has_set_som; - sljit_w ctypes; - sljit_uw name_table; - sljit_w name_count; - sljit_w name_entry_size; - - /* Labels and jump lists. */ - struct sljit_label *partialmatchlabel; - struct sljit_label *leavelabel; - struct sljit_label *acceptlabel; - stub_list *stubs; - recurse_entry *entries; - recurse_entry *currententry; - jump_list *partialmatch; - jump_list *leave; - jump_list *accept; - jump_list *calllimit; - jump_list *stackalloc; - jump_list *revertframes; - jump_list *wordboundary; - jump_list *anynewline; - jump_list *hspace; - jump_list *vspace; - jump_list *casefulcmp; - jump_list *caselesscmp; - BOOL jscript_compat; -#ifdef SUPPORT_UTF - BOOL utf; -#ifdef SUPPORT_UCP - BOOL use_ucp; -#endif - jump_list *utfreadchar; -#ifdef COMPILE_PCRE8 - jump_list *utfreadtype8; -#endif -#endif /* SUPPORT_UTF */ -#ifdef SUPPORT_UCP - jump_list *getunichartype; - jump_list *getunichartype_2; - jump_list *getunicharscript; -#endif -} compiler_common; - -/* For byte_sequence_compare. */ - -typedef struct compare_context { - int length; - int sourcereg; -#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED - int ucharptr; - union { - sljit_i asint; - sljit_uh asushort; -#ifdef COMPILE_PCRE8 - sljit_ub asbyte; - sljit_ub asuchars[4]; -#else -#ifdef COMPILE_PCRE16 - sljit_uh asuchars[2]; -#endif -#endif - } c; - union { - sljit_i asint; - sljit_uh asushort; -#ifdef COMPILE_PCRE8 - sljit_ub asbyte; - sljit_ub asuchars[4]; -#else -#ifdef COMPILE_PCRE16 - sljit_uh asuchars[2]; -#endif -#endif - } oc; -#endif -} compare_context; - -enum { - frame_end = 0, - frame_setstrbegin = -1, - frame_setmark = -2 -}; - -/* Undefine sljit macros. */ -#undef CMP - -/* Used for accessing the elements of the stack. */ -#define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w)) - -#define TMP1 SLJIT_TEMPORARY_REG1 -#define TMP2 SLJIT_TEMPORARY_REG3 -#define TMP3 SLJIT_TEMPORARY_EREG2 -#define STR_PTR SLJIT_SAVED_REG1 -#define STR_END SLJIT_SAVED_REG2 -#define STACK_TOP SLJIT_TEMPORARY_REG2 -#define STACK_LIMIT SLJIT_SAVED_REG3 -#define ARGUMENTS SLJIT_SAVED_EREG1 -#define CALL_COUNT SLJIT_SAVED_EREG2 -#define RETURN_ADDR SLJIT_TEMPORARY_EREG1 - -/* Locals layout. */ -/* These two locals can be used by the current opcode. */ -#define LOCALS0 (0 * sizeof(sljit_w)) -#define LOCALS1 (1 * sizeof(sljit_w)) -/* Two local variables for possessive quantifiers (char1 cannot use them). */ -#define POSSESSIVE0 (2 * sizeof(sljit_w)) -#define POSSESSIVE1 (3 * sizeof(sljit_w)) -/* Max limit of recursions. */ -#define CALL_LIMIT (4 * sizeof(sljit_w)) -/* The output vector is stored on the stack, and contains pointers -to characters. The vector data is divided into two groups: the first -group contains the start / end character pointers, and the second is -the start pointers when the end of the capturing group has not yet reached. */ -#define OVECTOR_START (common->ovector_start) -#define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w)) -#define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w)) -#define PRIV_DATA(cc) (common->localptrs[(cc) - common->start]) - -#ifdef COMPILE_PCRE8 -#define MOV_UCHAR SLJIT_MOV_UB -#define MOVU_UCHAR SLJIT_MOVU_UB -#else -#ifdef COMPILE_PCRE16 -#define MOV_UCHAR SLJIT_MOV_UH -#define MOVU_UCHAR SLJIT_MOVU_UH -#else -#error Unsupported compiling mode -#endif -#endif - -/* Shortcuts. */ -#define DEFINE_COMPILER \ - struct sljit_compiler *compiler = common->compiler -#define OP1(op, dst, dstw, src, srcw) \ - sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw)) -#define OP2(op, dst, dstw, src1, src1w, src2, src2w) \ - sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w)) -#define LABEL() \ - sljit_emit_label(compiler) -#define JUMP(type) \ - sljit_emit_jump(compiler, (type)) -#define JUMPTO(type, label) \ - sljit_set_label(sljit_emit_jump(compiler, (type)), (label)) -#define JUMPHERE(jump) \ - sljit_set_label((jump), sljit_emit_label(compiler)) -#define CMP(type, src1, src1w, src2, src2w) \ - sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)) -#define CMPTO(type, src1, src1w, src2, src2w, label) \ - sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label)) -#define COND_VALUE(op, dst, dstw, type) \ - sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type)) -#define GET_LOCAL_BASE(dst, dstw, offset) \ - sljit_get_local_base(compiler, (dst), (dstw), (offset)) - -static pcre_uchar* bracketend(pcre_uchar* cc) -{ -SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); -do cc += GET(cc, 1); while (*cc == OP_ALT); -SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS); -cc += 1 + LINK_SIZE; -return cc; -} - -/* Functions whose might need modification for all new supported opcodes: - next_opcode - get_localspace - set_localptrs - get_framesize - init_frame - get_localsize - copy_locals - compile_trypath - compile_backtrackpath -*/ - -static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc) -{ -SLJIT_UNUSED_ARG(common); -switch(*cc) - { - case OP_SOD: - case OP_SOM: - case OP_SET_SOM: - case OP_NOT_WORD_BOUNDARY: - case OP_WORD_BOUNDARY: - case OP_NOT_DIGIT: - case OP_DIGIT: - case OP_NOT_WHITESPACE: - case OP_WHITESPACE: - case OP_NOT_WORDCHAR: - case OP_WORDCHAR: - case OP_ANY: - case OP_ALLANY: - case OP_ANYNL: - case OP_NOT_HSPACE: - case OP_HSPACE: - case OP_NOT_VSPACE: - case OP_VSPACE: - case OP_EXTUNI: - case OP_EODN: - case OP_EOD: - case OP_CIRC: - case OP_CIRCM: - case OP_DOLL: - case OP_DOLLM: - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEQUERY: - case OP_TYPEMINQUERY: - case OP_TYPEPOSSTAR: - case OP_TYPEPOSPLUS: - case OP_TYPEPOSQUERY: - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRPLUS: - case OP_CRMINPLUS: - case OP_CRQUERY: - case OP_CRMINQUERY: - case OP_DEF: - case OP_BRAZERO: - case OP_BRAMINZERO: - case OP_BRAPOSZERO: - case OP_COMMIT: - case OP_FAIL: - case OP_ACCEPT: - case OP_ASSERT_ACCEPT: - case OP_SKIPZERO: - return cc + 1; - - case OP_ANYBYTE: -#ifdef SUPPORT_UTF - if (common->utf) return NULL; -#endif - return cc + 1; - - case OP_CHAR: - case OP_CHARI: - case OP_NOT: - case OP_NOTI: - case OP_STAR: - case OP_MINSTAR: - case OP_PLUS: - case OP_MINPLUS: - case OP_QUERY: - case OP_MINQUERY: - case OP_POSSTAR: - case OP_POSPLUS: - case OP_POSQUERY: - case OP_STARI: - case OP_MINSTARI: - case OP_PLUSI: - case OP_MINPLUSI: - case OP_QUERYI: - case OP_MINQUERYI: - case OP_POSSTARI: - case OP_POSPLUSI: - case OP_POSQUERYI: - case OP_NOTSTAR: - case OP_NOTMINSTAR: - case OP_NOTPLUS: - case OP_NOTMINPLUS: - case OP_NOTQUERY: - case OP_NOTMINQUERY: - case OP_NOTPOSSTAR: - case OP_NOTPOSPLUS: - case OP_NOTPOSQUERY: - case OP_NOTSTARI: - case OP_NOTMINSTARI: - case OP_NOTPLUSI: - case OP_NOTMINPLUSI: - case OP_NOTQUERYI: - case OP_NOTMINQUERYI: - case OP_NOTPOSSTARI: - case OP_NOTPOSPLUSI: - case OP_NOTPOSQUERYI: - cc += 2; -#ifdef SUPPORT_UTF - if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); -#endif - return cc; - - case OP_UPTO: - case OP_MINUPTO: - case OP_EXACT: - case OP_POSUPTO: - case OP_UPTOI: - case OP_MINUPTOI: - case OP_EXACTI: - case OP_POSUPTOI: - case OP_NOTUPTO: - case OP_NOTMINUPTO: - case OP_NOTEXACT: - case OP_NOTPOSUPTO: - case OP_NOTUPTOI: - case OP_NOTMINUPTOI: - case OP_NOTEXACTI: - case OP_NOTPOSUPTOI: - cc += 2 + IMM2_SIZE; -#ifdef SUPPORT_UTF - if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); -#endif - return cc; - - case OP_NOTPROP: - case OP_PROP: - return cc + 1 + 2; - - case OP_TYPEUPTO: - case OP_TYPEMINUPTO: - case OP_TYPEEXACT: - case OP_TYPEPOSUPTO: - case OP_REF: - case OP_REFI: - case OP_CREF: - case OP_NCREF: - case OP_RREF: - case OP_NRREF: - case OP_CLOSE: - cc += 1 + IMM2_SIZE; - return cc; - - case OP_CRRANGE: - case OP_CRMINRANGE: - return cc + 1 + 2 * IMM2_SIZE; - - case OP_CLASS: - case OP_NCLASS: - return cc + 1 + 32 / sizeof(pcre_uchar); - -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - case OP_XCLASS: - return cc + GET(cc, 1); -#endif - - case OP_RECURSE: - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - case OP_REVERSE: - case OP_ONCE: - case OP_ONCE_NC: - case OP_BRA: - case OP_BRAPOS: - case OP_COND: - case OP_SBRA: - case OP_SBRAPOS: - case OP_SCOND: - case OP_ALT: - case OP_KET: - case OP_KETRMAX: - case OP_KETRMIN: - case OP_KETRPOS: - return cc + 1 + LINK_SIZE; - - case OP_CBRA: - case OP_CBRAPOS: - case OP_SCBRA: - case OP_SCBRAPOS: - return cc + 1 + LINK_SIZE + IMM2_SIZE; - - case OP_MARK: - return cc + 1 + 2 + cc[1]; - - default: - return NULL; - } -} - -static int get_localspace(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) -{ -int localspace = 0; -pcre_uchar *alternative; -/* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ -while (cc < ccend) - { - switch(*cc) - { - case OP_SET_SOM: - common->has_set_som = TRUE; - cc += 1; - break; - - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - case OP_ONCE: - case OP_ONCE_NC: - case OP_BRAPOS: - case OP_SBRA: - case OP_SBRAPOS: - case OP_SCOND: - localspace += sizeof(sljit_w); - cc += 1 + LINK_SIZE; - break; - - case OP_CBRAPOS: - case OP_SCBRAPOS: - localspace += sizeof(sljit_w); - cc += 1 + LINK_SIZE + IMM2_SIZE; - break; - - case OP_COND: - /* Might be a hidden SCOND. */ - alternative = cc + GET(cc, 1); - if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) - localspace += sizeof(sljit_w); - cc += 1 + LINK_SIZE; - break; - - case OP_RECURSE: - /* Set its value only once. */ - if (common->recursive_head == 0) - { - common->recursive_head = common->ovector_start; - common->ovector_start += sizeof(sljit_w); - } - cc += 1 + LINK_SIZE; - break; - - case OP_MARK: - if (common->mark_ptr == 0) - { - common->mark_ptr = common->ovector_start; - common->ovector_start += sizeof(sljit_w); - } - cc += 1 + 2 + cc[1]; - break; - - default: - cc = next_opcode(common, cc); - if (cc == NULL) - return -1; - break; - } - } -return localspace; -} - -static void set_localptrs(compiler_common *common, int localptr, pcre_uchar *ccend) -{ -pcre_uchar *cc = common->start; -pcre_uchar *alternative; -while (cc < ccend) - { - switch(*cc) - { - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - case OP_ONCE: - case OP_ONCE_NC: - case OP_BRAPOS: - case OP_SBRA: - case OP_SBRAPOS: - case OP_SCOND: - common->localptrs[cc - common->start] = localptr; - localptr += sizeof(sljit_w); - cc += 1 + LINK_SIZE; - break; - - case OP_CBRAPOS: - case OP_SCBRAPOS: - common->localptrs[cc - common->start] = localptr; - localptr += sizeof(sljit_w); - cc += 1 + LINK_SIZE + IMM2_SIZE; - break; - - case OP_COND: - /* Might be a hidden SCOND. */ - alternative = cc + GET(cc, 1); - if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) - { - common->localptrs[cc - common->start] = localptr; - localptr += sizeof(sljit_w); - } - cc += 1 + LINK_SIZE; - break; - - default: - cc = next_opcode(common, cc); - SLJIT_ASSERT(cc != NULL); - break; - } - } -} - -/* Returns with -1 if no need for frame. */ -static int get_framesize(compiler_common *common, pcre_uchar *cc, BOOL recursive) -{ -pcre_uchar *ccend = bracketend(cc); -int length = 0; -BOOL possessive = FALSE; -BOOL setsom_found = recursive; -BOOL setmark_found = recursive; - -if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS)) - { - length = 3; - possessive = TRUE; - } - -cc = next_opcode(common, cc); -SLJIT_ASSERT(cc != NULL); -while (cc < ccend) - switch(*cc) - { - case OP_SET_SOM: - SLJIT_ASSERT(common->has_set_som); - if (!setsom_found) - { - length += 2; - setsom_found = TRUE; - } - cc += 1; - break; - - case OP_MARK: - SLJIT_ASSERT(common->mark_ptr != 0); - if (!setmark_found) - { - length += 2; - setmark_found = TRUE; - } - cc += 1 + 2 + cc[1]; - break; - - case OP_RECURSE: - if (common->has_set_som && !setsom_found) - { - length += 2; - setsom_found = TRUE; - } - if (common->mark_ptr != 0 && !setmark_found) - { - length += 2; - setmark_found = TRUE; - } - cc += 1 + LINK_SIZE; - break; - - case OP_CBRA: - case OP_CBRAPOS: - case OP_SCBRA: - case OP_SCBRAPOS: - length += 3; - cc += 1 + LINK_SIZE + IMM2_SIZE; - break; - - default: - cc = next_opcode(common, cc); - SLJIT_ASSERT(cc != NULL); - break; - } - -/* Possessive quantifiers can use a special case. */ -if (SLJIT_UNLIKELY(possessive) && length == 3) - return -1; - -if (length > 0) - return length + 1; -return -1; -} - -static void init_frame(compiler_common *common, pcre_uchar *cc, int stackpos, int stacktop, BOOL recursive) -{ -DEFINE_COMPILER; -pcre_uchar *ccend = bracketend(cc); -BOOL setsom_found = recursive; -BOOL setmark_found = recursive; -int offset; - -/* >= 1 + shortest item size (2) */ -SLJIT_UNUSED_ARG(stacktop); -SLJIT_ASSERT(stackpos >= stacktop + 2); - -stackpos = STACK(stackpos); -if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)) - cc = next_opcode(common, cc); -SLJIT_ASSERT(cc != NULL); -while (cc < ccend) - switch(*cc) - { - case OP_SET_SOM: - SLJIT_ASSERT(common->has_set_som); - if (!setsom_found) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin); - stackpos += (int)sizeof(sljit_w); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos += (int)sizeof(sljit_w); - setsom_found = TRUE; - } - cc += 1; - break; - - case OP_MARK: - SLJIT_ASSERT(common->mark_ptr != 0); - if (!setmark_found) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmark); - stackpos += (int)sizeof(sljit_w); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos += (int)sizeof(sljit_w); - setmark_found = TRUE; - } - cc += 1 + 2 + cc[1]; - break; - - case OP_RECURSE: - if (common->has_set_som && !setsom_found) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin); - stackpos += (int)sizeof(sljit_w); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos += (int)sizeof(sljit_w); - setsom_found = TRUE; - } - if (common->mark_ptr != 0 && !setmark_found) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmark); - stackpos += (int)sizeof(sljit_w); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos += (int)sizeof(sljit_w); - setmark_found = TRUE; - } - cc += 1 + LINK_SIZE; - break; - - case OP_CBRA: - case OP_CBRAPOS: - case OP_SCBRA: - case OP_SCBRAPOS: - offset = (GET2(cc, 1 + LINK_SIZE)) << 1; - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset)); - stackpos += (int)sizeof(sljit_w); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); - stackpos += (int)sizeof(sljit_w); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0); - stackpos += (int)sizeof(sljit_w); - - cc += 1 + LINK_SIZE + IMM2_SIZE; - break; - - default: - cc = next_opcode(common, cc); - SLJIT_ASSERT(cc != NULL); - break; - } - -OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_end); -SLJIT_ASSERT(stackpos == STACK(stacktop)); -} - -static SLJIT_INLINE int get_localsize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) -{ -int localsize = 2; -pcre_uchar *alternative; -/* Calculate the sum of the local variables. */ -while (cc < ccend) - { - switch(*cc) - { - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - case OP_ONCE: - case OP_ONCE_NC: - case OP_BRAPOS: - case OP_SBRA: - case OP_SBRAPOS: - case OP_SCOND: - localsize++; - cc += 1 + LINK_SIZE; - break; - - case OP_CBRA: - case OP_SCBRA: - localsize++; - cc += 1 + LINK_SIZE + IMM2_SIZE; - break; - - case OP_CBRAPOS: - case OP_SCBRAPOS: - localsize += 2; - cc += 1 + LINK_SIZE + IMM2_SIZE; - break; - - case OP_COND: - /* Might be a hidden SCOND. */ - alternative = cc + GET(cc, 1); - if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) - localsize++; - cc += 1 + LINK_SIZE; - break; - - default: - cc = next_opcode(common, cc); - SLJIT_ASSERT(cc != NULL); - break; - } - } -SLJIT_ASSERT(cc == ccend); -return localsize; -} - -static void copy_locals(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, - BOOL save, int stackptr, int stacktop) -{ -DEFINE_COMPILER; -int srcw[2]; -int count; -BOOL tmp1next = TRUE; -BOOL tmp1empty = TRUE; -BOOL tmp2empty = TRUE; -pcre_uchar *alternative; -enum { - start, - loop, - end -} status; - -status = save ? start : loop; -stackptr = STACK(stackptr - 2); -stacktop = STACK(stacktop - 1); - -if (!save) - { - stackptr += sizeof(sljit_w); - if (stackptr < stacktop) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr); - stackptr += sizeof(sljit_w); - tmp1empty = FALSE; - } - if (stackptr < stacktop) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr); - stackptr += sizeof(sljit_w); - tmp2empty = FALSE; - } - /* The tmp1next must be TRUE in either way. */ - } - -while (status != end) - { - count = 0; - switch(status) - { - case start: - SLJIT_ASSERT(save && common->recursive_head != 0); - count = 1; - srcw[0] = common->recursive_head; - status = loop; - break; - - case loop: - if (cc >= ccend) - { - status = end; - break; - } - - switch(*cc) - { - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - case OP_ONCE: - case OP_ONCE_NC: - case OP_BRAPOS: - case OP_SBRA: - case OP_SBRAPOS: - case OP_SCOND: - count = 1; - srcw[0] = PRIV_DATA(cc); - SLJIT_ASSERT(srcw[0] != 0); - cc += 1 + LINK_SIZE; - break; - - case OP_CBRA: - case OP_SCBRA: - count = 1; - srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); - cc += 1 + LINK_SIZE + IMM2_SIZE; - break; - - case OP_CBRAPOS: - case OP_SCBRAPOS: - count = 2; - srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); - srcw[0] = PRIV_DATA(cc); - SLJIT_ASSERT(srcw[0] != 0); - cc += 1 + LINK_SIZE + IMM2_SIZE; - break; - - case OP_COND: - /* Might be a hidden SCOND. */ - alternative = cc + GET(cc, 1); - if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) - { - count = 1; - srcw[0] = PRIV_DATA(cc); - SLJIT_ASSERT(srcw[0] != 0); - } - cc += 1 + LINK_SIZE; - break; - - default: - cc = next_opcode(common, cc); - SLJIT_ASSERT(cc != NULL); - break; - } - break; - - case end: - SLJIT_ASSERT_STOP(); - break; - } - - while (count > 0) - { - count--; - if (save) - { - if (tmp1next) - { - if (!tmp1empty) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); - stackptr += sizeof(sljit_w); - } - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]); - tmp1empty = FALSE; - tmp1next = FALSE; - } - else - { - if (!tmp2empty) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); - stackptr += sizeof(sljit_w); - } - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]); - tmp2empty = FALSE; - tmp1next = TRUE; - } - } - else - { - if (tmp1next) - { - SLJIT_ASSERT(!tmp1empty); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP1, 0); - tmp1empty = stackptr >= stacktop; - if (!tmp1empty) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr); - stackptr += sizeof(sljit_w); - } - tmp1next = FALSE; - } - else - { - SLJIT_ASSERT(!tmp2empty); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP2, 0); - tmp2empty = stackptr >= stacktop; - if (!tmp2empty) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr); - stackptr += sizeof(sljit_w); - } - tmp1next = TRUE; - } - } - } - } - -if (save) - { - if (tmp1next) - { - if (!tmp1empty) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); - stackptr += sizeof(sljit_w); - } - if (!tmp2empty) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); - stackptr += sizeof(sljit_w); - } - } - else - { - if (!tmp2empty) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); - stackptr += sizeof(sljit_w); - } - if (!tmp1empty) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); - stackptr += sizeof(sljit_w); - } - } - } -SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty))); -} - -static SLJIT_INLINE BOOL ispowerof2(unsigned int value) -{ -return (value & (value - 1)) == 0; -} - -static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label) -{ -while (list) - { - /* sljit_set_label is clever enough to do nothing - if either the jump or the label is NULL */ - sljit_set_label(list->jump, label); - list = list->next; - } -} - -static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump* jump) -{ -jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list)); -if (list_item) - { - list_item->next = *list; - list_item->jump = jump; - *list = list_item; - } -} - -static void add_stub(compiler_common *common, enum stub_types type, int data, struct sljit_jump *start) -{ -DEFINE_COMPILER; -stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list)); - -if (list_item) - { - list_item->type = type; - list_item->data = data; - list_item->start = start; - list_item->leave = LABEL(); - list_item->next = common->stubs; - common->stubs = list_item; - } -} - -static void flush_stubs(compiler_common *common) -{ -DEFINE_COMPILER; -stub_list* list_item = common->stubs; - -while (list_item) - { - JUMPHERE(list_item->start); - switch(list_item->type) - { - case stack_alloc: - add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL)); - break; - } - JUMPTO(SLJIT_JUMP, list_item->leave); - list_item = list_item->next; - } -common->stubs = NULL; -} - -static SLJIT_INLINE void decrease_call_count(compiler_common *common) -{ -DEFINE_COMPILER; - -OP2(SLJIT_SUB | SLJIT_SET_E, CALL_COUNT, 0, CALL_COUNT, 0, SLJIT_IMM, 1); -add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO)); -} - -static SLJIT_INLINE void allocate_stack(compiler_common *common, int size) -{ -/* May destroy all locals and registers except TMP2. */ -DEFINE_COMPILER; - -OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w)); -#ifdef DESTROY_REGISTERS -OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345); -OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); -OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0); -#endif -add_stub(common, stack_alloc, 0, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0)); -} - -static SLJIT_INLINE void free_stack(compiler_common *common, int size) -{ -DEFINE_COMPILER; -OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w)); -} - -static SLJIT_INLINE void reset_ovector(compiler_common *common, int length) -{ -DEFINE_COMPILER; -struct sljit_label *loop; -int i; -/* At this point we can freely use all temporary registers. */ -/* TMP1 returns with begin - 1. */ -OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); -if (length < 8) - { - for (i = 0; i < length; i++) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_TEMPORARY_REG1, 0); - } -else - { - GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, OVECTOR_START - sizeof(sljit_w)); - OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length); - loop = LABEL(); - OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1); - JUMPTO(SLJIT_C_NOT_ZERO, loop); - } -} - -static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket) -{ -DEFINE_COMPILER; -struct sljit_label *loop; -struct sljit_jump *earlyexit; - -/* At this point we can freely use all registers. */ -OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0); - -OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0); -if (common->mark_ptr != 0) - OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); -OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount)); -if (common->mark_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_TEMPORARY_REG3, 0); -OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); -OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin)); -GET_LOCAL_BASE(SLJIT_SAVED_REG1, 0, OVECTOR_START); -/* Unlikely, but possible */ -earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0); -loop = LABEL(); -OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_TEMPORARY_REG1, 0); -OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_w)); -/* Copy the integer value to the output buffer */ -#ifdef COMPILE_PCRE16 -OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1); -#endif -OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_SAVED_REG2, 0); -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); -JUMPTO(SLJIT_C_NOT_ZERO, loop); -JUMPHERE(earlyexit); - -/* Calculate the return value, which is the maximum ovector value. */ -if (topbracket > 1) - { - GET_LOCAL_BASE(SLJIT_TEMPORARY_REG1, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_w)); - OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1); - - /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */ - loop = LABEL(); - OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * (sljit_w)sizeof(sljit_w))); - OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); - CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG3, 0, loop); - OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0); - } -else - OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); -} - -static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *leave) -{ -DEFINE_COMPILER; - -SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2); -SLJIT_ASSERT(common->start_used_ptr != 0 && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0)); - -OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); -OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); -OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsetcount)); -CMPTO(SLJIT_C_LESS, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 2, leave); - -/* Store match begin and end. */ -OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, begin)); -OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsets)); -OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start); -OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, STR_END, 0, SLJIT_SAVED_REG1, 0); -#ifdef COMPILE_PCRE16 -OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1); -#endif -OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(int), SLJIT_SAVED_REG2, 0); - -OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG1, 0); -#ifdef COMPILE_PCRE16 -OP2(SLJIT_ASHR, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1); -#endif -OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), 0, SLJIT_TEMPORARY_REG3, 0); - -JUMPTO(SLJIT_JUMP, leave); -} - -static SLJIT_INLINE void check_start_used_ptr(compiler_common *common) -{ -/* May destroy TMP1. */ -DEFINE_COMPILER; -struct sljit_jump *jump; - -if (common->mode == JIT_PARTIAL_SOFT_COMPILE) - { - /* The value of -1 must be kept for start_used_ptr! */ - OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, 1); - /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting - is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */ - jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); - JUMPHERE(jump); - } -else if (common->mode == JIT_PARTIAL_HARD_COMPILE) - { - jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); - JUMPHERE(jump); - } -} - -static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar* cc) -{ -/* Detects if the character has an othercase. */ -unsigned int c; - -#ifdef SUPPORT_UTF -if (common->utf) - { - GETCHAR(c, cc); - if (c > 127) - { -#ifdef SUPPORT_UCP - return c != UCD_OTHERCASE(c); -#else - return FALSE; -#endif - } -#ifndef COMPILE_PCRE8 - return common->fcc[c] != c; -#endif - } -else -#endif - c = *cc; -return MAX_255(c) ? common->fcc[c] != c : FALSE; -} - -static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c) -{ -/* Returns with the othercase. */ -#ifdef SUPPORT_UTF -if (common->utf && c > 127) - { -#ifdef SUPPORT_UCP - return UCD_OTHERCASE(c); -#else - return c; -#endif - } -#endif -return TABLE_GET(c, common->fcc, c); -} - -static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar* cc) -{ -/* Detects if the character and its othercase has only 1 bit difference. */ -unsigned int c, oc, bit; -#if defined SUPPORT_UTF && defined COMPILE_PCRE8 -int n; -#endif - -#ifdef SUPPORT_UTF -if (common->utf) - { - GETCHAR(c, cc); - if (c <= 127) - oc = common->fcc[c]; - else - { -#ifdef SUPPORT_UCP - oc = UCD_OTHERCASE(c); -#else - oc = c; -#endif - } - } -else - { - c = *cc; - oc = TABLE_GET(c, common->fcc, c); - } -#else -c = *cc; -oc = TABLE_GET(c, common->fcc, c); -#endif - -SLJIT_ASSERT(c != oc); - -bit = c ^ oc; -/* Optimized for English alphabet. */ -if (c <= 127 && bit == 0x20) - return (0 << 8) | 0x20; - -/* Since c != oc, they must have at least 1 bit difference. */ -if (!ispowerof2(bit)) - return 0; - -#ifdef COMPILE_PCRE8 - -#ifdef SUPPORT_UTF -if (common->utf && c > 127) - { - n = GET_EXTRALEN(*cc); - while ((bit & 0x3f) == 0) - { - n--; - bit >>= 6; - } - return (n << 8) | bit; - } -#endif /* SUPPORT_UTF */ -return (0 << 8) | bit; - -#else /* COMPILE_PCRE8 */ - -#ifdef COMPILE_PCRE16 -#ifdef SUPPORT_UTF -if (common->utf && c > 65535) - { - if (bit >= (1 << 10)) - bit >>= 10; - else - return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8)); - } -#endif /* SUPPORT_UTF */ -return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (bit >> 8)); -#endif /* COMPILE_PCRE16 */ - -#endif /* COMPILE_PCRE8 */ -} - -static void check_partial(compiler_common *common, BOOL force) -{ -/* Checks whether a partial matching is occured. Does not modify registers. */ -DEFINE_COMPILER; -struct sljit_jump *jump = NULL; - -SLJIT_ASSERT(!force || common->mode != JIT_COMPILE); - -if (common->mode == JIT_COMPILE) - return; - -if (!force) - jump = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); -else if (common->mode == JIT_PARTIAL_SOFT_COMPILE) - jump = CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1); - -if (common->mode == JIT_PARTIAL_SOFT_COMPILE) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); -else - { - if (common->partialmatchlabel != NULL) - JUMPTO(SLJIT_JUMP, common->partialmatchlabel); - else - add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); - } - -if (jump != NULL) - JUMPHERE(jump); -} - -static struct sljit_jump *check_str_end(compiler_common *common) -{ -/* Does not affect registers. Usually used in a tight spot. */ -DEFINE_COMPILER; -struct sljit_jump *jump; -struct sljit_jump *nohit; -struct sljit_jump *return_value; - -if (common->mode == JIT_COMPILE) - return CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - -jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); -if (common->mode == JIT_PARTIAL_SOFT_COMPILE) - { - nohit = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); - JUMPHERE(nohit); - return_value = JUMP(SLJIT_JUMP); - } -else - { - return_value = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); - if (common->partialmatchlabel != NULL) - JUMPTO(SLJIT_JUMP, common->partialmatchlabel); - else - add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); - } -JUMPHERE(jump); -return return_value; -} - -static void detect_partial_match(compiler_common *common, jump_list **backtracks) -{ -DEFINE_COMPILER; -struct sljit_jump *jump; - -if (common->mode == JIT_COMPILE) - { - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); - return; - } - -/* Partial matching mode. */ -jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); -add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); -if (common->mode == JIT_PARTIAL_SOFT_COMPILE) - { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); - } -else - { - if (common->partialmatchlabel != NULL) - JUMPTO(SLJIT_JUMP, common->partialmatchlabel); - else - add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); - } -JUMPHERE(jump); -} - -static void read_char(compiler_common *common) -{ -/* Reads the character into TMP1, updates STR_PTR. -Does not check STR_END. TMP2 Destroyed. */ -DEFINE_COMPILER; -#ifdef SUPPORT_UTF -struct sljit_jump *jump; -#endif - -OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); -#ifdef SUPPORT_UTF -if (common->utf) - { -#ifdef COMPILE_PCRE8 - jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); -#else -#ifdef COMPILE_PCRE16 - jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); -#endif -#endif /* COMPILE_PCRE8 */ - add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); - JUMPHERE(jump); - } -#endif -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -} - -static void peek_char(compiler_common *common) -{ -/* Reads the character into TMP1, keeps STR_PTR. -Does not check STR_END. TMP2 Destroyed. */ -DEFINE_COMPILER; -#ifdef SUPPORT_UTF -struct sljit_jump *jump; -#endif - -OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); -#ifdef SUPPORT_UTF -if (common->utf) - { -#ifdef COMPILE_PCRE8 - jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); -#else -#ifdef COMPILE_PCRE16 - jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); -#endif -#endif /* COMPILE_PCRE8 */ - add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); - JUMPHERE(jump); - } -#endif -} - -static void read_char8_type(compiler_common *common) -{ -/* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */ -DEFINE_COMPILER; -#if defined SUPPORT_UTF || defined COMPILE_PCRE16 -struct sljit_jump *jump; -#endif - -#ifdef SUPPORT_UTF -if (common->utf) - { - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -#ifdef COMPILE_PCRE8 - /* This can be an extra read in some situations, but hopefully - it is needed in most cases. */ - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); - jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0); - add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL)); - JUMPHERE(jump); -#else -#ifdef COMPILE_PCRE16 - OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); - jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); - JUMPHERE(jump); - /* Skip low surrogate if necessary. */ - OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xfc00); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xd800); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); -#endif -#endif /* COMPILE_PCRE8 */ - return; - } -#endif -OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -#ifdef COMPILE_PCRE16 -/* The ctypes array contains only 256 values. */ -OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); -jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); -#endif -OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); -#ifdef COMPILE_PCRE16 -JUMPHERE(jump); -#endif -} - -static void skip_char_back(compiler_common *common) -{ -/* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */ -DEFINE_COMPILER; -#if defined SUPPORT_UTF && defined COMPILE_PCRE8 -struct sljit_label *label; - -if (common->utf) - { - label = LABEL(); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1)); - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); - CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label); - return; - } -#endif -#if defined SUPPORT_UTF && defined COMPILE_PCRE16 -if (common->utf) - { - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1)); - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - /* Skip low surrogate if necessary. */ - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00); - COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - return; - } -#endif -OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -} - -static void check_newlinechar(compiler_common *common, int nltype, jump_list **backtracks, BOOL jumpiftrue) -{ -/* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */ -DEFINE_COMPILER; - -if (nltype == NLTYPE_ANY) - { - add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); - } -else if (nltype == NLTYPE_ANYCRLF) - { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); - COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); - add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); - } -else - { - SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256); - add_jump(compiler, backtracks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); - } -} - -#ifdef SUPPORT_UTF - -#ifdef COMPILE_PCRE8 -static void do_utfreadchar(compiler_common *common) -{ -/* Fast decoding a UTF-8 character. TMP1 contains the first byte -of the character (>= 0xc0). Return char value in TMP1, length - 1 in TMP2. */ -DEFINE_COMPILER; -struct sljit_jump *jump; - -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); -/* Searching for the first zero. */ -OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); -jump = JUMP(SLJIT_C_NOT_ZERO); -/* Two byte sequence. */ -OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f); -OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); -OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); -OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -JUMPHERE(jump); - -OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10); -jump = JUMP(SLJIT_C_NOT_ZERO); -/* Three byte sequence. */ -OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); -OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f); -OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12); -OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); -OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); -OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); -OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2)); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); -OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); -OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2)); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -JUMPHERE(jump); - -/* Four byte sequence. */ -OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); -OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07); -OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18); -OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); -OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12); -OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); -OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2)); -OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); -OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); -OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); -OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(3)); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3)); -OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); -OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3)); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} - -static void do_utfreadtype8(compiler_common *common) -{ -/* Fast decoding a UTF-8 character type. TMP2 contains the first byte -of the character (>= 0xc0). Return value in TMP1. */ -DEFINE_COMPILER; -struct sljit_jump *jump; -struct sljit_jump *compare; - -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); - -OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20); -jump = JUMP(SLJIT_C_NOT_ZERO); -/* Two byte sequence. */ -OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f); -OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); -OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); -OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0); -compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); -OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); - -JUMPHERE(compare); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -JUMPHERE(jump); - -/* We only have types for characters less than 256. */ -OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(utf8_table4) - 0xc0); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} - -#else /* COMPILE_PCRE8 */ - -#ifdef COMPILE_PCRE16 -static void do_utfreadchar(compiler_common *common) -{ -/* Fast decoding a UTF-16 character. TMP1 contains the first 16 bit char -of the character (>= 0xd800). Return char value in TMP1, length - 1 in TMP2. */ -DEFINE_COMPILER; -struct sljit_jump *jump; - -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); -jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00); -/* Do nothing, only return. */ -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); - -JUMPHERE(jump); -/* Combine two 16 bit characters. */ -OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff); -OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10); -OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3ff); -OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); -OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} -#endif /* COMPILE_PCRE16 */ - -#endif /* COMPILE_PCRE8 */ - -#endif /* SUPPORT_UTF */ - -#ifdef SUPPORT_UCP - -static sljit_w SLJIT_CALL getunichartype(sljit_w c) -{ - return (sljit_w)(unsigned int)UCD_CHARTYPE((unsigned int)c); -} - -static sljit_w SLJIT_CALL getunicharscript(sljit_w c) -{ - return (sljit_w)(unsigned int)UCD_SCRIPT((unsigned int)c); -} - -static void do_getunichartype(compiler_common *common) -{ -/* Character comes in TMP1. Returns chartype in TMP1 */ -DEFINE_COMPILER; - -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); -/* Save registers */ -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); -sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(getunichartype)); -/* Restore registers */ -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} - -static void do_getunichartype_2(compiler_common *common) -{ -/* Character comes in TMP1. Returns chartype in TMP1 */ -DEFINE_COMPILER; - -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); -/* Save registers */ -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STACK_TOP, 0); -sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(getunichartype)); -/* Restore registers */ -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} - -static void do_getunicharscript(compiler_common *common) -{ -/* Character comes in TMP1. Returns chartype in TMP1 */ -DEFINE_COMPILER; - -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); -/* Save registers */ -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); -sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(getunicharscript)); -/* Restore registers */ -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} -#endif - -static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, BOOL firstline) -{ -DEFINE_COMPILER; -struct sljit_label *mainloop; -struct sljit_label *newlinelabel = NULL; -struct sljit_jump *start; -struct sljit_jump *end = NULL; -struct sljit_jump *nl = NULL; -#ifdef SUPPORT_UTF -struct sljit_jump *singlechar; -#endif -jump_list *newline = NULL; -BOOL newlinecheck = FALSE; -BOOL readuchar = FALSE; - -if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY || - common->nltype == NLTYPE_ANYCRLF || common->newline > 255)) - newlinecheck = TRUE; - -if (firstline) - { - /* Search for the end of the first line. */ - SLJIT_ASSERT(common->first_line_end != 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_END, 0); - - if (common->nltype == NLTYPE_FIXED && common->newline > 255) - { - mainloop = LABEL(); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop); - CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop); - OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - } - else - { - end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - mainloop = LABEL(); - /* Continual stores does not cause data dependency. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0); - read_char(common); - check_newlinechar(common, common->nltype, &newline, TRUE); - CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, STR_PTR, 0); - set_jumps(newline, LABEL()); - } - - JUMPHERE(end); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); - } - -start = JUMP(SLJIT_JUMP); - -if (newlinecheck) - { - newlinelabel = LABEL(); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff); - COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); -#ifdef COMPILE_PCRE16 - OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); -#endif - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - nl = JUMP(SLJIT_JUMP); - } - -mainloop = LABEL(); - -/* Increasing the STR_PTR here requires one less jump in the most common case. */ -#ifdef SUPPORT_UTF -if (common->utf) readuchar = TRUE; -#endif -if (newlinecheck) readuchar = TRUE; - -if (readuchar) - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - -if (newlinecheck) - CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel); - -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -#if defined SUPPORT_UTF && defined COMPILE_PCRE8 -if (common->utf) - { - singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - JUMPHERE(singlechar); - } -#endif -#if defined SUPPORT_UTF && defined COMPILE_PCRE16 -if (common->utf) - { - singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); - COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - JUMPHERE(singlechar); - } -#endif -JUMPHERE(start); - -if (newlinecheck) - { - JUMPHERE(end); - JUMPHERE(nl); - } - -return mainloop; -} - -static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline) -{ -DEFINE_COMPILER; -struct sljit_label *start; -struct sljit_jump *leave; -struct sljit_jump *found; -pcre_uchar oc, bit; - -if (firstline) - { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); - } - -start = LABEL(); -leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); -OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - -oc = first_char; -if (caseless) - { - oc = TABLE_GET(first_char, common->fcc, first_char); -#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) - if (first_char > 127 && common->utf) - oc = UCD_OTHERCASE(first_char); -#endif - } -if (first_char == oc) - found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, first_char); -else - { - bit = first_char ^ oc; - if (ispowerof2(bit)) - { - OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit); - found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, first_char | bit); - } - else - { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc); - COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); - found = JUMP(SLJIT_C_NOT_ZERO); - } - } - -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -#if defined SUPPORT_UTF && defined COMPILE_PCRE8 -if (common->utf) - { - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - } -#endif -#if defined SUPPORT_UTF && defined COMPILE_PCRE16 -if (common->utf) - { - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); - COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - } -#endif -JUMPTO(SLJIT_JUMP, start); -JUMPHERE(found); -JUMPHERE(leave); - -if (firstline) - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); -} - -static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline) -{ -DEFINE_COMPILER; -struct sljit_label *loop; -struct sljit_jump *lastchar; -struct sljit_jump *firstchar; -struct sljit_jump *leave; -struct sljit_jump *foundcr = NULL; -struct sljit_jump *notfoundnl; -jump_list *newline = NULL; - -if (firstline) - { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); - } - -if (common->nltype == NLTYPE_FIXED && common->newline > 255) - { - lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); - firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0); - - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2)); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER_EQUAL); -#ifdef COMPILE_PCRE16 - OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); -#endif - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); - - loop = LABEL(); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); - CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); - CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); - - JUMPHERE(leave); - JUMPHERE(firstchar); - JUMPHERE(lastchar); - - if (firstline) - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); - return; - } - -OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); -firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0); -skip_char_back(common); - -loop = LABEL(); -read_char(common); -lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); -if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) - foundcr = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); -check_newlinechar(common, common->nltype, &newline, FALSE); -set_jumps(newline, loop); - -if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) - { - leave = JUMP(SLJIT_JUMP); - JUMPHERE(foundcr); - notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); - COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); -#ifdef COMPILE_PCRE16 - OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); -#endif - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - JUMPHERE(notfoundnl); - JUMPHERE(leave); - } -JUMPHERE(lastchar); -JUMPHERE(firstchar); - -if (firstline) - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); -} - -static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline) -{ -DEFINE_COMPILER; -struct sljit_label *start; -struct sljit_jump *leave; -struct sljit_jump *found; -#ifndef COMPILE_PCRE8 -struct sljit_jump *jump; -#endif - -if (firstline) - { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); - } - -start = LABEL(); -leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); -OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); -#ifdef SUPPORT_UTF -if (common->utf) - OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); -#endif -#ifndef COMPILE_PCRE8 -jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 255); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255); -JUMPHERE(jump); -#endif -OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); -OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); -OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), start_bits); -OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); -OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); -found = JUMP(SLJIT_C_NOT_ZERO); - -#ifdef SUPPORT_UTF -if (common->utf) - OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); -#endif -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -#if defined SUPPORT_UTF && defined COMPILE_PCRE8 -if (common->utf) - { - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - } -#endif -#if defined SUPPORT_UTF && defined COMPILE_PCRE16 -if (common->utf) - { - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); - COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - } -#endif -JUMPTO(SLJIT_JUMP, start); -JUMPHERE(found); -JUMPHERE(leave); - -if (firstline) - OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); -} - -static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uchar req_char, BOOL caseless, BOOL has_firstchar) -{ -DEFINE_COMPILER; -struct sljit_label *loop; -struct sljit_jump *toolong; -struct sljit_jump *alreadyfound; -struct sljit_jump *found; -struct sljit_jump *foundoc = NULL; -struct sljit_jump *notfound; -pcre_uchar oc, bit; - -SLJIT_ASSERT(common->req_char_ptr != 0); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr); -OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX); -toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0); -alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0); - -if (has_firstchar) - OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -else - OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0); - -loop = LABEL(); -notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0); - -OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0); -oc = req_char; -if (caseless) - { - oc = TABLE_GET(req_char, common->fcc, req_char); -#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) - if (req_char > 127 && common->utf) - oc = UCD_OTHERCASE(req_char); -#endif - } -if (req_char == oc) - found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char); -else - { - bit = req_char ^ oc; - if (ispowerof2(bit)) - { - OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit); - found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit); - } - else - { - found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char); - foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc); - } - } -OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); -JUMPTO(SLJIT_JUMP, loop); - -JUMPHERE(found); -if (foundoc) - JUMPHERE(foundoc); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, TMP1, 0); -JUMPHERE(alreadyfound); -JUMPHERE(toolong); -return notfound; -} - -static void do_revertframes(compiler_common *common) -{ -DEFINE_COMPILER; -struct sljit_jump *jump; -struct sljit_label *mainloop; - -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); -OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0); -GET_LOCAL_BASE(TMP3, 0, 0); - -/* Drop frames until we reach STACK_TOP. */ -mainloop = LABEL(); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); -jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end); -OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w)); -OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w)); -OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w)); -JUMPTO(SLJIT_JUMP, mainloop); - -JUMPHERE(jump); -jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_end); -/* End of dropping frames. */ -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); - -JUMPHERE(jump); -jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setstrbegin); -/* Set string begin. */ -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w)); -OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w)); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0); -JUMPTO(SLJIT_JUMP, mainloop); - -JUMPHERE(jump); -if (common->mark_ptr != 0) - { - jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setmark); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w)); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); - JUMPTO(SLJIT_JUMP, mainloop); - - JUMPHERE(jump); - } - -/* Unknown command. */ -OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w)); -JUMPTO(SLJIT_JUMP, mainloop); -} - -static void check_wordboundary(compiler_common *common) -{ -DEFINE_COMPILER; -struct sljit_jump *skipread; -#if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF -struct sljit_jump *jump; -#endif - -SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16); - -sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); -/* Get type of the previous char, and put it to LOCALS1. */ -OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0); -skipread = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0); -skip_char_back(common); -check_start_used_ptr(common); -read_char(common); - -/* Testing char type. */ -#ifdef SUPPORT_UCP -if (common->use_ucp) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); - jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); - add_jump(compiler, &common->getunichartype_2, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); - OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); - COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); - JUMPHERE(jump); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0); - } -else -#endif - { -#ifndef COMPILE_PCRE8 - jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); -#elif defined SUPPORT_UTF - /* Here LOCALS1 has already been zeroed. */ - jump = NULL; - if (common->utf) - jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); -#endif /* COMPILE_PCRE8 */ - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes); - OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */); - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0); -#ifndef COMPILE_PCRE8 - JUMPHERE(jump); -#elif defined SUPPORT_UTF - if (jump != NULL) - JUMPHERE(jump); -#endif /* COMPILE_PCRE8 */ - } -JUMPHERE(skipread); - -OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); -skipread = check_str_end(common); -peek_char(common); - -/* Testing char type. This is a code duplication. */ -#ifdef SUPPORT_UCP -if (common->use_ucp) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); - jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); - add_jump(compiler, &common->getunichartype_2, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); - OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); - COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); - JUMPHERE(jump); - } -else -#endif - { -#ifndef COMPILE_PCRE8 - /* TMP2 may be destroyed by peek_char. */ - OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); - jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); -#elif defined SUPPORT_UTF - OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); - jump = NULL; - if (common->utf) - jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); -#endif - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes); - OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */); - OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); -#ifndef COMPILE_PCRE8 - JUMPHERE(jump); -#elif defined SUPPORT_UTF - if (jump != NULL) - JUMPHERE(jump); -#endif /* COMPILE_PCRE8 */ - } -JUMPHERE(skipread); - -OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); -sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); -} - -static void check_anynewline(compiler_common *common) -{ -/* Check whether TMP1 contains a newline character. TMP2 destroyed. */ -DEFINE_COMPILER; - -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); - -OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); -OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); -COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); -#if defined SUPPORT_UTF || defined COMPILE_PCRE16 -#ifdef COMPILE_PCRE8 -if (common->utf) - { -#endif - COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); -#ifdef COMPILE_PCRE8 - } -#endif -#endif /* SUPPORT_UTF || COMPILE_PCRE16 */ -COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} - -static void check_hspace(compiler_common *common) -{ -/* Check whether TMP1 contains a newline character. TMP2 destroyed. */ -DEFINE_COMPILER; - -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); - -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09); -COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); -COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0); -#if defined SUPPORT_UTF || defined COMPILE_PCRE16 -#ifdef COMPILE_PCRE8 -if (common->utf) - { -#endif - COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680); - COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e); - COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000); - COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000); - COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000); - COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000); -#ifdef COMPILE_PCRE8 - } -#endif -#endif /* SUPPORT_UTF || COMPILE_PCRE16 */ -COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); - -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} - -static void check_vspace(compiler_common *common) -{ -/* Check whether TMP1 contains a newline character. TMP2 destroyed. */ -DEFINE_COMPILER; - -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); - -OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); -OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); -COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); -OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); -#if defined SUPPORT_UTF || defined COMPILE_PCRE16 -#ifdef COMPILE_PCRE8 -if (common->utf) - { -#endif - COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); -#ifdef COMPILE_PCRE8 - } -#endif -#endif /* SUPPORT_UTF || COMPILE_PCRE16 */ -COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); - -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} - -#define CHAR1 STR_END -#define CHAR2 STACK_TOP - -static void do_casefulcmp(compiler_common *common) -{ -DEFINE_COMPILER; -struct sljit_jump *jump; -struct sljit_label *label; - -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); -OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); -OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0); -OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); -OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - -label = LABEL(); -OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1)); -OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); -jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0); -OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); -JUMPTO(SLJIT_C_NOT_ZERO, label); - -JUMPHERE(jump); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0); -OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} - -#define LCC_TABLE STACK_LIMIT - -static void do_caselesscmp(compiler_common *common) -{ -DEFINE_COMPILER; -struct sljit_jump *jump; -struct sljit_label *label; - -sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); -OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); - -OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR1, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, CHAR2, 0); -OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc); -OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); -OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - -label = LABEL(); -OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1)); -OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); -#ifndef COMPILE_PCRE8 -jump = CMP(SLJIT_C_GREATER, CHAR1, 0, SLJIT_IMM, 255); -#endif -OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0); -#ifndef COMPILE_PCRE8 -JUMPHERE(jump); -jump = CMP(SLJIT_C_GREATER, CHAR2, 0, SLJIT_IMM, 255); -#endif -OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0); -#ifndef COMPILE_PCRE8 -JUMPHERE(jump); -#endif -jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0); -OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); -JUMPTO(SLJIT_C_NOT_ZERO, label); - -JUMPHERE(jump); -OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0); -OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); -OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); -} - -#undef LCC_TABLE -#undef CHAR1 -#undef CHAR2 - -#if defined SUPPORT_UTF && defined SUPPORT_UCP - -static const pcre_uchar *SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1) -{ -/* This function would be ineffective to do in JIT level. */ -int c1, c2; -const pcre_uchar *src2 = args->uchar_ptr; -const pcre_uchar *end2 = args->end; - -while (src1 < end1) - { - if (src2 >= end2) - return (pcre_uchar*)1; - GETCHARINC(c1, src1); - GETCHARINC(c2, src2); - if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return NULL; - } -return src2; -} - -#endif /* SUPPORT_UTF && SUPPORT_UCP */ - -static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc, - compare_context* context, jump_list **backtracks) -{ -DEFINE_COMPILER; -unsigned int othercasebit = 0; -pcre_uchar *othercasechar = NULL; -#ifdef SUPPORT_UTF -int utflength; -#endif - -if (caseless && char_has_othercase(common, cc)) - { - othercasebit = char_get_othercase_bit(common, cc); - SLJIT_ASSERT(othercasebit); - /* Extracting bit difference info. */ -#ifdef COMPILE_PCRE8 - othercasechar = cc + (othercasebit >> 8); - othercasebit &= 0xff; -#else -#ifdef COMPILE_PCRE16 - othercasechar = cc + (othercasebit >> 9); - if ((othercasebit & 0x100) != 0) - othercasebit = (othercasebit & 0xff) << 8; - else - othercasebit &= 0xff; -#endif -#endif - } - -if (context->sourcereg == -1) - { -#ifdef COMPILE_PCRE8 -#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED - if (context->length >= 4) - OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); - else if (context->length >= 2) - OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); - else -#endif - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); -#else -#ifdef COMPILE_PCRE16 -#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED - if (context->length >= 4) - OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); - else -#endif - OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); -#endif -#endif /* COMPILE_PCRE8 */ - context->sourcereg = TMP2; - } - -#ifdef SUPPORT_UTF -utflength = 1; -if (common->utf && HAS_EXTRALEN(*cc)) - utflength += GET_EXTRALEN(*cc); - -do - { -#endif - - context->length -= IN_UCHARS(1); -#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED - - /* Unaligned read is supported. */ - if (othercasebit != 0 && othercasechar == cc) - { - context->c.asuchars[context->ucharptr] = *cc | othercasebit; - context->oc.asuchars[context->ucharptr] = othercasebit; - } - else - { - context->c.asuchars[context->ucharptr] = *cc; - context->oc.asuchars[context->ucharptr] = 0; - } - context->ucharptr++; - -#ifdef COMPILE_PCRE8 - if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1)) -#else - if (context->ucharptr >= 2 || context->length == 0) -#endif - { - if (context->length >= 4) - OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); -#ifdef COMPILE_PCRE8 - else if (context->length >= 2) - OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); - else if (context->length >= 1) - OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); -#else - else if (context->length >= 2) - OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); -#endif - context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; - - switch(context->ucharptr) - { - case 4 / sizeof(pcre_uchar): - if (context->oc.asint != 0) - OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); - break; - - case 2 / sizeof(pcre_uchar): - if (context->oc.asushort != 0) - OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort)); - break; - -#ifdef COMPILE_PCRE8 - case 1: - if (context->oc.asbyte != 0) - OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte)); - break; -#endif - - default: - SLJIT_ASSERT_STOP(); - break; - } - context->ucharptr = 0; - } - -#else - - /* Unaligned read is unsupported. */ -#ifdef COMPILE_PCRE8 - if (context->length > 0) - OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); -#else - if (context->length > 0) - OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); -#endif - context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; - - if (othercasebit != 0 && othercasechar == cc) - { - OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit)); - } - else - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc)); - -#endif - - cc++; -#ifdef SUPPORT_UTF - utflength--; - } -while (utflength > 0); -#endif - -return cc; -} - -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - -#define SET_TYPE_OFFSET(value) \ - if ((value) != typeoffset) \ - { \ - if ((value) > typeoffset) \ - OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \ - else \ - OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \ - } \ - typeoffset = (value); - -#define SET_CHAR_OFFSET(value) \ - if ((value) != charoffset) \ - { \ - if ((value) > charoffset) \ - OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \ - else \ - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \ - } \ - charoffset = (value); - -static void compile_xclass_trypath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks) -{ -DEFINE_COMPILER; -jump_list *found = NULL; -jump_list **list = (*cc & XCL_NOT) == 0 ? &found : backtracks; -unsigned int c; -int compares; -struct sljit_jump *jump = NULL; -pcre_uchar *ccbegin; -#ifdef SUPPORT_UCP -BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE; -BOOL charsaved = FALSE; -int typereg = TMP1, scriptreg = TMP1; -unsigned int typeoffset; -#endif -int invertcmp, numberofcmps; -unsigned int charoffset; - -/* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */ -detect_partial_match(common, backtracks); -read_char(common); - -if ((*cc++ & XCL_MAP) != 0) - { - OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); -#ifndef COMPILE_PCRE8 - jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); -#elif defined SUPPORT_UTF - if (common->utf) - jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); -#endif - - OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); - OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc); - OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); - add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO)); - -#ifndef COMPILE_PCRE8 - JUMPHERE(jump); -#elif defined SUPPORT_UTF - if (common->utf) - JUMPHERE(jump); -#endif - OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); -#ifdef SUPPORT_UCP - charsaved = TRUE; -#endif - cc += 32 / sizeof(pcre_uchar); - } - -/* Scanning the necessary info. */ -ccbegin = cc; -compares = 0; -while (*cc != XCL_END) - { - compares++; - if (*cc == XCL_SINGLE) - { - cc += 2; -#ifdef SUPPORT_UTF - if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); -#endif -#ifdef SUPPORT_UCP - needschar = TRUE; -#endif - } - else if (*cc == XCL_RANGE) - { - cc += 2; -#ifdef SUPPORT_UTF - if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); -#endif - cc++; -#ifdef SUPPORT_UTF - if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); -#endif -#ifdef SUPPORT_UCP - needschar = TRUE; -#endif - } -#ifdef SUPPORT_UCP - else - { - SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); - cc++; - switch(*cc) - { - case PT_ANY: - break; - - case PT_LAMP: - case PT_GC: - case PT_PC: - case PT_ALNUM: - needstype = TRUE; - break; - - case PT_SC: - needsscript = TRUE; - break; - - case PT_SPACE: - case PT_PXSPACE: - case PT_WORD: - needstype = TRUE; - needschar = TRUE; - break; - - default: - SLJIT_ASSERT_STOP(); - break; - } - cc += 2; - } -#endif - } - -#ifdef SUPPORT_UCP -/* Simple register allocation. TMP1 is preferred if possible. */ -if (needstype || needsscript) - { - if ((needschar || needsscript) && !charsaved) - OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); - - /* Needed to save important temporary registers. */ - SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && - STACK_TOP == SLJIT_TEMPORARY_REG2 && - TMP2 == SLJIT_TEMPORARY_REG3); - - if (needschar) - { - if (needstype) - typereg = RETURN_ADDR; - if (needsscript) - scriptreg = TMP3; - } - else if (needstype && needsscript) - scriptreg = TMP3; - /* In all other cases only one of them was specified, and that can goes to TMP1. */ - - if (needstype) - { - add_jump(compiler, &common->getunichartype, JUMP(SLJIT_FAST_CALL)); - if (typereg != TMP1) - OP1(SLJIT_MOV, typereg, 0, TMP1, 0); - } - - if (needsscript) - { - /* Get the char again */ - if (needstype) - OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); - - add_jump(compiler, &common->getunicharscript, JUMP(SLJIT_FAST_CALL)); - if (scriptreg != TMP1) - OP1(SLJIT_MOV, scriptreg, 0, TMP1, 0); - } - - if (needschar) - OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); - } -#endif - -/* Generating code. */ -cc = ccbegin; -charoffset = 0; -numberofcmps = 0; -#ifdef SUPPORT_UCP -typeoffset = 0; -#endif - -while (*cc != XCL_END) - { - compares--; - invertcmp = (compares == 0 && list != backtracks); - jump = NULL; - - if (*cc == XCL_SINGLE) - { - cc ++; -#ifdef SUPPORT_UTF - if (common->utf) - { - GETCHARINC(c, cc); - } - else -#endif - c = *cc++; - - if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) - { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); - COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); - numberofcmps++; - } - else if (numberofcmps > 0) - { - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); - COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); - numberofcmps = 0; - } - else - { - jump = CMP(SLJIT_C_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset); - numberofcmps = 0; - } - } - else if (*cc == XCL_RANGE) - { - cc ++; -#ifdef SUPPORT_UTF - if (common->utf) - { - GETCHARINC(c, cc); - } - else -#endif - c = *cc++; - SET_CHAR_OFFSET(c); -#ifdef SUPPORT_UTF - if (common->utf) - { - GETCHARINC(c, cc); - } - else -#endif - c = *cc++; - if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) - { - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); - COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); - numberofcmps++; - } - else if (numberofcmps > 0) - { - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); - COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL); - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); - numberofcmps = 0; - } - else - { - jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset); - numberofcmps = 0; - } - } -#ifdef SUPPORT_UCP - else - { - if (*cc == XCL_NOTPROP) - invertcmp ^= 0x1; - cc++; - switch(*cc) - { - case PT_ANY: - if (list != backtracks) - { - if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0)) - continue; - } - else if (cc[-1] == XCL_NOTPROP) - continue; - jump = JUMP(SLJIT_JUMP); - break; - - case PT_LAMP: - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset); - COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset); - COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); - break; - - case PT_GC: - c = PRIV(ucp_typerange)[(int)cc[1] * 2]; - SET_TYPE_OFFSET(c); - jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c); - break; - - case PT_PC: - jump = CMP(SLJIT_C_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset); - break; - - case PT_SC: - jump = CMP(SLJIT_C_EQUAL ^ invertcmp, scriptreg, 0, SLJIT_IMM, (int)cc[1]); - break; - - case PT_SPACE: - case PT_PXSPACE: - if (*cc == PT_SPACE) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); - jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 11 - charoffset); - } - SET_CHAR_OFFSET(9); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 13 - 9); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); - if (*cc == PT_SPACE) - JUMPHERE(jump); - - SET_TYPE_OFFSET(ucp_Zl); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl); - COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL); - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); - break; - - case PT_WORD: - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE - charoffset); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); - /* ... fall through */ - - case PT_ALNUM: - SET_TYPE_OFFSET(ucp_Ll); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); - COND_VALUE((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); - SET_TYPE_OFFSET(ucp_Nd); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd); - COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL); - jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); - break; - } - cc += 2; - } -#endif - - if (jump != NULL) - add_jump(compiler, compares > 0 ? list : backtracks, jump); - } - -if (found != NULL) - set_jumps(found, LABEL()); -} - -#undef SET_TYPE_OFFSET -#undef SET_CHAR_OFFSET - -#endif - -static pcre_uchar *compile_char1_trypath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **backtracks) -{ -DEFINE_COMPILER; -int length; -unsigned int c, oc, bit; -compare_context context; -struct sljit_jump *jump[4]; -#ifdef SUPPORT_UTF -struct sljit_label *label; -#ifdef SUPPORT_UCP -pcre_uchar propdata[5]; -#endif -#endif - -switch(type) - { - case OP_SOD: - OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); - return cc; - - case OP_SOM: - OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); - return cc; - - case OP_NOT_WORD_BOUNDARY: - case OP_WORD_BOUNDARY: - add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); - return cc; - - case OP_NOT_DIGIT: - case OP_DIGIT: - detect_partial_match(common, backtracks); - read_char8_type(common); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); - add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); - return cc; - - case OP_NOT_WHITESPACE: - case OP_WHITESPACE: - detect_partial_match(common, backtracks); - read_char8_type(common); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space); - add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); - return cc; - - case OP_NOT_WORDCHAR: - case OP_WORDCHAR: - detect_partial_match(common, backtracks); - read_char8_type(common); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word); - add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); - return cc; - - case OP_ANY: - detect_partial_match(common, backtracks); - read_char(common); - if (common->nltype == NLTYPE_FIXED && common->newline > 255) - { - jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); - if (common->mode != JIT_PARTIAL_HARD_COMPILE) - jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - else - jump[1] = check_str_end(common); - - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); - if (jump[1] != NULL) - JUMPHERE(jump[1]); - JUMPHERE(jump[0]); - } - else - check_newlinechar(common, common->nltype, backtracks, TRUE); - return cc; - - case OP_ALLANY: - detect_partial_match(common, backtracks); -#ifdef SUPPORT_UTF - if (common->utf) - { - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -#ifdef COMPILE_PCRE8 - jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); -#else /* COMPILE_PCRE8 */ -#ifdef COMPILE_PCRE16 - jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); - OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); - COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); -#endif /* COMPILE_PCRE16 */ -#endif /* COMPILE_PCRE8 */ - JUMPHERE(jump[0]); - return cc; - } -#endif - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - return cc; - - case OP_ANYBYTE: - detect_partial_match(common, backtracks); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - return cc; - -#ifdef SUPPORT_UTF -#ifdef SUPPORT_UCP - case OP_NOTPROP: - case OP_PROP: - propdata[0] = 0; - propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP; - propdata[2] = cc[0]; - propdata[3] = cc[1]; - propdata[4] = XCL_END; - compile_xclass_trypath(common, propdata, backtracks); - return cc + 2; -#endif -#endif - - case OP_ANYNL: - detect_partial_match(common, backtracks); - read_char(common); - jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); - /* We don't need to handle soft partial matching case. */ - if (common->mode != JIT_PARTIAL_HARD_COMPILE) - jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - else - jump[1] = check_str_end(common); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - jump[3] = JUMP(SLJIT_JUMP); - JUMPHERE(jump[0]); - check_newlinechar(common, common->bsr_nltype, backtracks, FALSE); - JUMPHERE(jump[1]); - JUMPHERE(jump[2]); - JUMPHERE(jump[3]); - return cc; - - case OP_NOT_HSPACE: - case OP_HSPACE: - detect_partial_match(common, backtracks); - read_char(common); - add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); - return cc; - - case OP_NOT_VSPACE: - case OP_VSPACE: - detect_partial_match(common, backtracks); - read_char(common); - add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); - return cc; - -#ifdef SUPPORT_UCP - case OP_EXTUNI: - detect_partial_match(common, backtracks); - read_char(common); - add_jump(compiler, &common->getunichartype, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc)); - - label = LABEL(); - jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); - read_char(common); - add_jump(compiler, &common->getunichartype, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc); - CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc, label); - - OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); - JUMPHERE(jump[0]); - if (common->mode == JIT_PARTIAL_HARD_COMPILE) - { - jump[0] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); - /* Since we successfully read a char above, partial matching must occure. */ - check_partial(common, TRUE); - JUMPHERE(jump[0]); - } - return cc; -#endif - - case OP_EODN: - /* Requires rather complex checks. */ - jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - if (common->nltype == NLTYPE_FIXED && common->newline > 255) - { - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - if (common->mode == JIT_COMPILE) - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); - else - { - jump[1] = CMP(SLJIT_C_EQUAL, TMP2, 0, STR_END, 0); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); - COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_NOT_EQUAL); - add_jump(compiler, backtracks, JUMP(SLJIT_C_NOT_EQUAL)); - check_partial(common, TRUE); - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); - JUMPHERE(jump[1]); - } - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); - } - else if (common->nltype == NLTYPE_FIXED) - { - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); - } - else - { - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); - jump[2] = JUMP(SLJIT_C_GREATER); - add_jump(compiler, backtracks, JUMP(SLJIT_C_LESS)); - /* Equal. */ - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); - jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); - - JUMPHERE(jump[1]); - if (common->nltype == NLTYPE_ANYCRLF) - { - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); - } - else - { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0); - read_char(common); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); - add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); - } - JUMPHERE(jump[2]); - JUMPHERE(jump[3]); - } - JUMPHERE(jump[0]); - check_partial(common, FALSE); - return cc; - - case OP_EOD: - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); - check_partial(common, FALSE); - return cc; - - case OP_CIRC: - OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0)); - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); - return cc; - - case OP_CIRCM: - OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); - jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0); - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); - jump[0] = JUMP(SLJIT_JUMP); - JUMPHERE(jump[1]); - - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); - if (common->nltype == NLTYPE_FIXED && common->newline > 255) - { - OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0)); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); - } - else - { - skip_char_back(common); - read_char(common); - check_newlinechar(common, common->nltype, backtracks, FALSE); - } - JUMPHERE(jump[0]); - return cc; - - case OP_DOLL: - OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); - - if (!common->endonly) - compile_char1_trypath(common, OP_EODN, cc, backtracks); - else - { - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); - check_partial(common, FALSE); - } - return cc; - - case OP_DOLLM: - jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); - OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); - check_partial(common, FALSE); - jump[0] = JUMP(SLJIT_JUMP); - JUMPHERE(jump[1]); - - if (common->nltype == NLTYPE_FIXED && common->newline > 255) - { - OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); - if (common->mode == JIT_COMPILE) - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0)); - else - { - jump[1] = CMP(SLJIT_C_LESS_EQUAL, TMP2, 0, STR_END, 0); - /* STR_PTR = STR_END - IN_UCHARS(1) */ - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); - check_partial(common, TRUE); - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); - JUMPHERE(jump[1]); - } - - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); - } - else - { - peek_char(common); - check_newlinechar(common, common->nltype, backtracks, FALSE); - } - JUMPHERE(jump[0]); - return cc; - - case OP_CHAR: - case OP_CHARI: - length = 1; -#ifdef SUPPORT_UTF - if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc); -#endif - if (common->mode == JIT_COMPILE && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)) - { - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); - - context.length = IN_UCHARS(length); - context.sourcereg = -1; -#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED - context.ucharptr = 0; -#endif - return byte_sequence_compare(common, type == OP_CHARI, cc, &context, backtracks); - } - detect_partial_match(common, backtracks); - read_char(common); -#ifdef SUPPORT_UTF - if (common->utf) - { - GETCHAR(c, cc); - } - else -#endif - c = *cc; - if (type == OP_CHAR || !char_has_othercase(common, cc)) - { - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c)); - return cc + length; - } - oc = char_othercase(common, c); - bit = c ^ oc; - if (ispowerof2(bit)) - { - OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); - return cc + length; - } - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c)); - COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); - add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); - return cc + length; - - case OP_NOT: - case OP_NOTI: - detect_partial_match(common, backtracks); - length = 1; -#ifdef SUPPORT_UTF - if (common->utf) - { -#ifdef COMPILE_PCRE8 - c = *cc; - if (c < 128) - { - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); - if (type == OP_NOT || !char_has_othercase(common, cc)) - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); - else - { - /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */ - OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20); - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20)); - } - /* Skip the variable-length character. */ - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); - JUMPHERE(jump[0]); - return cc + 1; - } - else -#endif /* COMPILE_PCRE8 */ - { - GETCHARLEN(c, cc, length); - read_char(common); - } - } - else -#endif /* SUPPORT_UTF */ - { - read_char(common); - c = *cc; - } - - if (type == OP_NOT || !char_has_othercase(common, cc)) - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); - else - { - oc = char_othercase(common, c); - bit = c ^ oc; - if (ispowerof2(bit)) - { - OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); - } - else - { - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc)); - } - } - return cc + length; - - case OP_CLASS: - case OP_NCLASS: - detect_partial_match(common, backtracks); - read_char(common); -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - jump[0] = NULL; -#ifdef COMPILE_PCRE8 - /* This check only affects 8 bit mode. In other modes, we - always need to compare the value with 255. */ - if (common->utf) -#endif /* COMPILE_PCRE8 */ - { - jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); - if (type == OP_CLASS) - { - add_jump(compiler, backtracks, jump[0]); - jump[0] = NULL; - } - } -#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */ - OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); - OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); - OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc); - OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); - OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); - add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - if (jump[0] != NULL) - JUMPHERE(jump[0]); -#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */ - return cc + 32 / sizeof(pcre_uchar); - -#if defined SUPPORT_UTF || defined COMPILE_PCRE16 - case OP_XCLASS: - compile_xclass_trypath(common, cc + LINK_SIZE, backtracks); - return cc + GET(cc, 0) - 1; -#endif - - case OP_REVERSE: - length = GET(cc, 0); - if (length == 0) - return cc + LINK_SIZE; - OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); -#ifdef SUPPORT_UTF - if (common->utf) - { - OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length); - label = LABEL(); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP3, 0)); - skip_char_back(common); - OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); - JUMPTO(SLJIT_C_NOT_ZERO, label); - } - else -#endif - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0)); - } - check_start_used_ptr(common); - return cc + LINK_SIZE; - } -SLJIT_ASSERT_STOP(); -return cc; -} - -static SLJIT_INLINE pcre_uchar *compile_charn_trypath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **backtracks) -{ -/* This function consumes at least one input character. */ -/* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */ -DEFINE_COMPILER; -pcre_uchar *ccbegin = cc; -compare_context context; -int size; - -context.length = 0; -do - { - if (cc >= ccend) - break; - - if (*cc == OP_CHAR) - { - size = 1; -#ifdef SUPPORT_UTF - if (common->utf && HAS_EXTRALEN(cc[1])) - size += GET_EXTRALEN(cc[1]); -#endif - } - else if (*cc == OP_CHARI) - { - size = 1; -#ifdef SUPPORT_UTF - if (common->utf) - { - if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0) - size = 0; - else if (HAS_EXTRALEN(cc[1])) - size += GET_EXTRALEN(cc[1]); - } - else -#endif - if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0) - size = 0; - } - else - size = 0; - - cc += 1 + size; - context.length += IN_UCHARS(size); - } -while (size > 0 && context.length <= 128); - -cc = ccbegin; -if (context.length > 0) - { - /* We have a fixed-length byte sequence. */ - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length); - add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); - - context.sourcereg = -1; -#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED - context.ucharptr = 0; -#endif - do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, backtracks); while (context.length > 0); - return cc; - } - -/* A non-fixed length character will be checked if length == 0. */ -return compile_char1_trypath(common, *cc, cc + 1, backtracks); -} - -static struct sljit_jump *compile_ref_checks(compiler_common *common, pcre_uchar *cc, jump_list **backtracks) -{ -DEFINE_COMPILER; -int offset = GET2(cc, 1) << 1; - -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); -if (!common->jscript_compat) - { - if (backtracks == NULL) - { - /* OVECTOR(1) contains the "string begin - 1" constant. */ - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); - OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); - COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); - return JUMP(SLJIT_C_NOT_ZERO); - } - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); - } -return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); -} - -/* Forward definitions. */ -static void compile_trypath(compiler_common *, pcre_uchar *, pcre_uchar *, backtrack_common *); -static void compile_backtrackpath(compiler_common *, struct backtrack_common *); - -#define PUSH_BACKTRACK(size, ccstart, error) \ - do \ - { \ - backtrack = sljit_alloc_memory(compiler, (size)); \ - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ - return error; \ - memset(backtrack, 0, size); \ - backtrack->prev = parent->top; \ - backtrack->cc = (ccstart); \ - parent->top = backtrack; \ - } \ - while (0) - -#define PUSH_BACKTRACK_NOVALUE(size, ccstart) \ - do \ - { \ - backtrack = sljit_alloc_memory(compiler, (size)); \ - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ - return; \ - memset(backtrack, 0, size); \ - backtrack->prev = parent->top; \ - backtrack->cc = (ccstart); \ - parent->top = backtrack; \ - } \ - while (0) - -#define BACKTRACK_AS(type) ((type *)backtrack) - -static pcre_uchar *compile_ref_trypath(compiler_common *common, pcre_uchar *cc, jump_list **backtracks, BOOL withchecks, BOOL emptyfail) -{ -DEFINE_COMPILER; -int offset = GET2(cc, 1) << 1; -struct sljit_jump *jump = NULL; -struct sljit_jump *partial; -struct sljit_jump *nopartial; - -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); -/* OVECTOR(1) contains the "string begin - 1" constant. */ -if (withchecks && !common->jscript_compat) - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); - -#if defined SUPPORT_UTF && defined SUPPORT_UCP -if (common->utf && *cc == OP_REFI) - { - SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && STACK_TOP == SLJIT_TEMPORARY_REG2 && TMP2 == SLJIT_TEMPORARY_REG3); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); - if (withchecks) - jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0); - - /* Needed to save important temporary registers. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); - OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, uchar_ptr), STR_PTR, 0); - sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp)); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); - if (common->mode == JIT_COMPILE) - add_jump(compiler, backtracks, CMP(SLJIT_C_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1)); - else - { - add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); - nopartial = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); - check_partial(common, FALSE); - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); - JUMPHERE(nopartial); - } - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); - } -else -#endif /* SUPPORT_UTF && SUPPORT_UCP */ - { - OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0); - if (withchecks) - jump = JUMP(SLJIT_C_ZERO); - - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); - partial = CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0); - if (common->mode == JIT_COMPILE) - add_jump(compiler, backtracks, partial); - - add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); - - if (common->mode != JIT_COMPILE) - { - nopartial = JUMP(SLJIT_JUMP); - JUMPHERE(partial); - /* TMP2 -= STR_END - STR_PTR */ - OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0); - OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0); - partial = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0); - OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); - add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); - add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); - JUMPHERE(partial); - check_partial(common, FALSE); - add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); - JUMPHERE(nopartial); - } - } - -if (jump != NULL) - { - if (emptyfail) - add_jump(compiler, backtracks, jump); - else - JUMPHERE(jump); - } -return cc + 1 + IMM2_SIZE; -} - -static SLJIT_INLINE pcre_uchar *compile_ref_iterator_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) -{ -DEFINE_COMPILER; -backtrack_common *backtrack; -pcre_uchar type; -struct sljit_label *label; -struct sljit_jump *zerolength; -struct sljit_jump *jump = NULL; -pcre_uchar *ccbegin = cc; -int min = 0, max = 0; -BOOL minimize; - -PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL); - -type = cc[1 + IMM2_SIZE]; -minimize = (type & 0x1) != 0; -switch(type) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - min = 0; - max = 0; - cc += 1 + IMM2_SIZE + 1; - break; - case OP_CRPLUS: - case OP_CRMINPLUS: - min = 1; - max = 0; - cc += 1 + IMM2_SIZE + 1; - break; - case OP_CRQUERY: - case OP_CRMINQUERY: - min = 0; - max = 1; - cc += 1 + IMM2_SIZE + 1; - break; - case OP_CRRANGE: - case OP_CRMINRANGE: - min = GET2(cc, 1 + IMM2_SIZE + 1); - max = GET2(cc, 1 + IMM2_SIZE + 1 + IMM2_SIZE); - cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE; - break; - default: - SLJIT_ASSERT_STOP(); - break; - } - -if (!minimize) - { - if (min == 0) - { - allocate_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); - /* Temporary release of STR_PTR. */ - OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); - zerolength = compile_ref_checks(common, ccbegin, NULL); - /* Restore if not zero length. */ - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); - } - else - { - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks); - } - - if (min > 1 || max > 1) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); - - label = LABEL(); - compile_ref_trypath(common, ccbegin, &backtrack->topbacktracks, FALSE, FALSE); - - if (min > 1 || max > 1) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); - if (min > 1) - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, label); - if (max > 1) - { - jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max); - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - JUMPTO(SLJIT_JUMP, label); - JUMPHERE(jump); - } - } - - if (max == 0) - { - /* Includes min > 1 case as well. */ - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - JUMPTO(SLJIT_JUMP, label); - } - - JUMPHERE(zerolength); - BACKTRACK_AS(iterator_backtrack)->trypath = LABEL(); - - decrease_call_count(common); - return cc; - } - -allocate_stack(common, 2); -OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); -if (type != OP_CRMINSTAR) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); - -if (min == 0) - { - zerolength = compile_ref_checks(common, ccbegin, NULL); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - jump = JUMP(SLJIT_JUMP); - } -else - zerolength = compile_ref_checks(common, ccbegin, &backtrack->topbacktracks); - -BACKTRACK_AS(iterator_backtrack)->trypath = LABEL(); -if (max > 0) - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max)); - -compile_ref_trypath(common, ccbegin, &backtrack->topbacktracks, TRUE, TRUE); -OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - -if (min > 1) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, BACKTRACK_AS(iterator_backtrack)->trypath); - } -else if (max > 0) - OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); - -if (jump != NULL) - JUMPHERE(jump); -JUMPHERE(zerolength); - -decrease_call_count(common); -return cc; -} - -static SLJIT_INLINE pcre_uchar *compile_recurse_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) -{ -DEFINE_COMPILER; -backtrack_common *backtrack; -recurse_entry *entry = common->entries; -recurse_entry *prev = NULL; -int start = GET(cc, 1); - -PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL); -while (entry != NULL) - { - if (entry->start == start) - break; - prev = entry; - entry = entry->next; - } - -if (entry == NULL) - { - entry = sljit_alloc_memory(compiler, sizeof(recurse_entry)); - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - return NULL; - entry->next = NULL; - entry->entry = NULL; - entry->calls = NULL; - entry->start = start; - - if (prev != NULL) - prev->next = entry; - else - common->entries = entry; - } - -if (common->has_set_som && common->mark_ptr != 0) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); - allocate_stack(common, 2); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); - } -else if (common->has_set_som || common->mark_ptr != 0) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr); - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); - } - -if (entry->entry == NULL) - add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL)); -else - JUMPTO(SLJIT_FAST_CALL, entry->entry); -/* Leave if the match is failed. */ -add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0)); -return cc + 1 + LINK_SIZE; -} - -static pcre_uchar *compile_assert_trypath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional) -{ -DEFINE_COMPILER; -int framesize; -int localptr; -backtrack_common altbacktrack; -pcre_uchar *ccbegin; -pcre_uchar opcode; -pcre_uchar bra = OP_BRA; -jump_list *tmp = NULL; -jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks; -jump_list **found; -/* Saving previous accept variables. */ -struct sljit_label *save_leavelabel = common->leavelabel; -struct sljit_label *save_acceptlabel = common->acceptlabel; -jump_list *save_leave = common->leave; -jump_list *save_accept = common->accept; -struct sljit_jump *jump; -struct sljit_jump *brajump = NULL; - -if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) - { - SLJIT_ASSERT(!conditional); - bra = *cc; - cc++; - } -localptr = PRIV_DATA(cc); -SLJIT_ASSERT(localptr != 0); -framesize = get_framesize(common, cc, FALSE); -backtrack->framesize = framesize; -backtrack->localptr = localptr; -opcode = *cc; -SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT); -found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target; -ccbegin = cc; -cc += GET(cc, 1); - -if (bra == OP_BRAMINZERO) - { - /* This is a braminzero backtrack path. */ - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - free_stack(common, 1); - brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); - } - -if (framesize < 0) - { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0); - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - } -else - { - allocate_stack(common, framesize + 2); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(framesize + 1)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); - init_frame(common, ccbegin, framesize + 1, 2, FALSE); - } - -memset(&altbacktrack, 0, sizeof(backtrack_common)); -common->leavelabel = NULL; -common->leave = NULL; -while (1) - { - common->acceptlabel = NULL; - common->accept = NULL; - altbacktrack.top = NULL; - altbacktrack.topbacktracks = NULL; - - if (*ccbegin == OP_ALT) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - - altbacktrack.cc = ccbegin; - compile_trypath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack); - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - { - common->leavelabel = save_leavelabel; - common->acceptlabel = save_acceptlabel; - common->leave = save_leave; - common->accept = save_accept; - return NULL; - } - common->acceptlabel = LABEL(); - if (common->accept != NULL) - set_jumps(common->accept, common->acceptlabel); - - /* Reset stack. */ - if (framesize < 0) - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - else { - if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional) - { - /* We don't need to keep the STR_PTR, only the previous localptr. */ - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w)); - } - else - { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - } - } - - if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) - { - /* We know that STR_PTR was stored on the top of the stack. */ - if (conditional) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); - else if (bra == OP_BRAZERO) - { - if (framesize < 0) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); - else - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w)); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_w)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); - } - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - } - else if (framesize >= 0) - { - /* For OP_BRA and OP_BRAMINZERO. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w)); - } - } - add_jump(compiler, found, JUMP(SLJIT_JUMP)); - - compile_backtrackpath(common, altbacktrack.top); - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - { - common->leavelabel = save_leavelabel; - common->acceptlabel = save_acceptlabel; - common->leave = save_leave; - common->accept = save_accept; - return NULL; - } - set_jumps(altbacktrack.topbacktracks, LABEL()); - - if (*cc != OP_ALT) - break; - - ccbegin = cc; - cc += GET(cc, 1); - } -/* None of them matched. */ -if (common->leave != NULL) - set_jumps(common->leave, LABEL()); - -if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) - { - /* Assert is failed. */ - if (conditional || bra == OP_BRAZERO) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - - if (framesize < 0) - { - /* The topmost item should be 0. */ - if (bra == OP_BRAZERO) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - else - free_stack(common, 1); - } - else - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - /* The topmost item should be 0. */ - if (bra == OP_BRAZERO) - { - free_stack(common, framesize + 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - } - else - free_stack(common, framesize + 2); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); - } - jump = JUMP(SLJIT_JUMP); - if (bra != OP_BRAZERO) - add_jump(compiler, target, jump); - - /* Assert is successful. */ - set_jumps(tmp, LABEL()); - if (framesize < 0) - { - /* We know that STR_PTR was stored on the top of the stack. */ - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); - /* Keep the STR_PTR on the top of the stack. */ - if (bra == OP_BRAZERO) - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); - else if (bra == OP_BRAMINZERO) - { - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - } - } - else - { - if (bra == OP_BRA) - { - /* We don't need to keep the STR_PTR, only the previous localptr. */ - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w)); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); - } - else - { - /* We don't need to keep the STR_PTR, only the previous localptr. */ - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_w)); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0); - } - } - - if (bra == OP_BRAZERO) - { - backtrack->trypath = LABEL(); - sljit_set_label(jump, backtrack->trypath); - } - else if (bra == OP_BRAMINZERO) - { - JUMPTO(SLJIT_JUMP, backtrack->trypath); - JUMPHERE(brajump); - if (framesize >= 0) - { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w)); - } - set_jumps(backtrack->common.topbacktracks, LABEL()); - } - } -else - { - /* AssertNot is successful. */ - if (framesize < 0) - { - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - if (bra != OP_BRA) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - else - free_stack(common, 1); - } - else - { - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - /* The topmost item should be 0. */ - if (bra != OP_BRA) - { - free_stack(common, framesize + 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - } - else - free_stack(common, framesize + 2); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); - } - - if (bra == OP_BRAZERO) - backtrack->trypath = LABEL(); - else if (bra == OP_BRAMINZERO) - { - JUMPTO(SLJIT_JUMP, backtrack->trypath); - JUMPHERE(brajump); - } - - if (bra != OP_BRA) - { - SLJIT_ASSERT(found == &backtrack->common.topbacktracks); - set_jumps(backtrack->common.topbacktracks, LABEL()); - backtrack->common.topbacktracks = NULL; - } - } - -common->leavelabel = save_leavelabel; -common->acceptlabel = save_acceptlabel; -common->leave = save_leave; -common->accept = save_accept; -return cc + 1 + LINK_SIZE; -} - -static sljit_w SLJIT_CALL do_searchovector(sljit_w refno, sljit_w* locals, pcre_uchar *name_table) -{ -int condition = FALSE; -pcre_uchar *slotA = name_table; -pcre_uchar *slotB; -sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)]; -sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)]; -sljit_w no_capture; -int i; - -locals += refno & 0xff; -refno >>= 8; -no_capture = locals[1]; - -for (i = 0; i < name_count; i++) - { - if (GET2(slotA, 0) == refno) break; - slotA += name_entry_size; - } - -if (i < name_count) - { - /* Found a name for the number - there can be only one; duplicate names - for different numbers are allowed, but not vice versa. First scan down - for duplicates. */ - - slotB = slotA; - while (slotB > name_table) - { - slotB -= name_entry_size; - if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) - { - condition = locals[GET2(slotB, 0) << 1] != no_capture; - if (condition) break; - } - else break; - } - - /* Scan up for duplicates */ - if (!condition) - { - slotB = slotA; - for (i++; i < name_count; i++) - { - slotB += name_entry_size; - if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) - { - condition = locals[GET2(slotB, 0) << 1] != no_capture; - if (condition) break; - } - else break; - } - } - } -return condition; -} - -static sljit_w SLJIT_CALL do_searchgroups(sljit_w recno, sljit_w* locals, pcre_uchar *name_table) -{ -int condition = FALSE; -pcre_uchar *slotA = name_table; -pcre_uchar *slotB; -sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)]; -sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)]; -sljit_w group_num = locals[POSSESSIVE0 / sizeof(sljit_w)]; -int i; - -for (i = 0; i < name_count; i++) - { - if (GET2(slotA, 0) == recno) break; - slotA += name_entry_size; - } - -if (i < name_count) - { - /* Found a name for the number - there can be only one; duplicate - names for different numbers are allowed, but not vice versa. First - scan down for duplicates. */ - - slotB = slotA; - while (slotB > name_table) - { - slotB -= name_entry_size; - if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) - { - condition = GET2(slotB, 0) == group_num; - if (condition) break; - } - else break; - } - - /* Scan up for duplicates */ - if (!condition) - { - slotB = slotA; - for (i++; i < name_count; i++) - { - slotB += name_entry_size; - if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) - { - condition = GET2(slotB, 0) == group_num; - if (condition) break; - } - else break; - } - } - } -return condition; -} - -/* - Handling bracketed expressions is probably the most complex part. - - Stack layout naming characters: - S - Push the current STR_PTR - 0 - Push a 0 (NULL) - A - Push the current STR_PTR. Needed for restoring the STR_PTR - before the next alternative. Not pushed if there are no alternatives. - M - Any values pushed by the current alternative. Can be empty, or anything. - C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack. - L - Push the previous local (pointed by localptr) to the stack - () - opional values stored on the stack - ()* - optonal, can be stored multiple times - - The following list shows the regular expression templates, their PCRE byte codes - and stack layout supported by pcre-sljit. - - (?:) OP_BRA | OP_KET A M - () OP_CBRA | OP_KET C M - (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )* - OP_SBRA | OP_KETRMAX 0 L M S ( L M S )* - (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )* - OP_SBRA | OP_KETRMIN 0 L M S ( L M S )* - ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )* - OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )* - ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )* - OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )* - (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 ) - (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 ) - ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 ) - ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 ) - (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )* - OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )* - (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )* - OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )* - ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )* - OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )* - ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )* - OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )* - - - Stack layout naming characters: - A - Push the alternative index (starting from 0) on the stack. - Not pushed if there is no alternatives. - M - Any values pushed by the current alternative. Can be empty, or anything. - - The next list shows the possible content of a bracket: - (|) OP_*BRA | OP_ALT ... M A - (?()|) OP_*COND | OP_ALT M A - (?>|) OP_ONCE | OP_ALT ... [stack trace] M A - (?>|) OP_ONCE_NC | OP_ALT ... [stack trace] M A - Or nothing, if trace is unnecessary -*/ - -static pcre_uchar *compile_bracket_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) -{ -DEFINE_COMPILER; -backtrack_common *backtrack; -pcre_uchar opcode; -int localptr = 0; -int offset = 0; -int stacksize; -pcre_uchar *ccbegin; -pcre_uchar *trypath; -pcre_uchar bra = OP_BRA; -pcre_uchar ket; -assert_backtrack *assert; -BOOL has_alternatives; -struct sljit_jump *jump; -struct sljit_jump *skip; -struct sljit_label *rmaxlabel = NULL; -struct sljit_jump *braminzerojump = NULL; - -PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL); - -if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) - { - bra = *cc; - cc++; - opcode = *cc; - } - -opcode = *cc; -ccbegin = cc; -trypath = ccbegin + 1 + LINK_SIZE; - -if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF) - { - /* Drop this bracket_backtrack. */ - parent->top = backtrack->prev; - return bracketend(cc); - } - -ket = *(bracketend(cc) - 1 - LINK_SIZE); -SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN); -SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX))); -cc += GET(cc, 1); - -has_alternatives = *cc == OP_ALT; -if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) - { - has_alternatives = (*trypath == OP_RREF) ? FALSE : TRUE; - if (*trypath == OP_NRREF) - { - stacksize = GET2(trypath, 1); - if (common->currententry == NULL || stacksize == RREF_ANY) - has_alternatives = FALSE; - else if (common->currententry->start == 0) - has_alternatives = stacksize != 0; - else - has_alternatives = stacksize != GET2(common->start, common->currententry->start + 1 + LINK_SIZE); - } - } - -if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) - opcode = OP_SCOND; -if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) - opcode = OP_ONCE; - -if (opcode == OP_CBRA || opcode == OP_SCBRA) - { - /* Capturing brackets has a pre-allocated space. */ - offset = GET2(ccbegin, 1 + LINK_SIZE); - localptr = OVECTOR_PRIV(offset); - offset <<= 1; - BACKTRACK_AS(bracket_backtrack)->localptr = localptr; - trypath += IMM2_SIZE; - } -else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND) - { - /* Other brackets simply allocate the next entry. */ - localptr = PRIV_DATA(ccbegin); - SLJIT_ASSERT(localptr != 0); - BACKTRACK_AS(bracket_backtrack)->localptr = localptr; - if (opcode == OP_ONCE) - BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, FALSE); - } - -/* Instructions before the first alternative. */ -stacksize = 0; -if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) - stacksize++; -if (bra == OP_BRAZERO) - stacksize++; - -if (stacksize > 0) - allocate_stack(common, stacksize); - -stacksize = 0; -if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); - stacksize++; - } - -if (bra == OP_BRAZERO) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); - -if (bra == OP_BRAMINZERO) - { - /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */ - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - if (ket != OP_KETRMIN) - { - free_stack(common, 1); - braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); - } - else - { - if (opcode == OP_ONCE || opcode >= OP_SBRA) - { - jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - /* Nothing stored during the first run. */ - skip = JUMP(SLJIT_JUMP); - JUMPHERE(jump); - /* Checking zero-length iteration. */ - if (opcode != OP_ONCE || BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) - { - /* When we come from outside, localptr contains the previous STR_PTR. */ - braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - } - else - { - /* Except when the whole stack frame must be saved. */ - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (BACKTRACK_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_w)); - } - JUMPHERE(skip); - } - else - { - jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - JUMPHERE(jump); - } - } - } - -if (ket == OP_KETRMIN) - BACKTRACK_AS(bracket_backtrack)->recursivetrypath = LABEL(); - -if (ket == OP_KETRMAX) - { - rmaxlabel = LABEL(); - if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA) - BACKTRACK_AS(bracket_backtrack)->alttrypath = rmaxlabel; - } - -/* Handling capturing brackets and alternatives. */ -if (opcode == OP_ONCE) - { - if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) - { - /* Neither capturing brackets nor recursions are not found in the block. */ - if (ket == OP_KETRMIN) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - allocate_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); - OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); - } - else if (ket == OP_KETRMAX || has_alternatives) - { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0); - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - } - else - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0); - } - else - { - if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) - { - allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 2); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize + 1)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); - init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1, 2, FALSE); - } - else - { - allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); - init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize, 1, FALSE); - } - } - } -else if (opcode == OP_CBRA || opcode == OP_SCBRA) - { - /* Saving the previous values. */ - allocate_stack(common, 3); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0); - } -else if (opcode == OP_SBRA || opcode == OP_SCOND) - { - /* Saving the previous value. */ - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); - } -else if (has_alternatives) - { - /* Pushing the starting string pointer. */ - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - } - -/* Generating code for the first alternative. */ -if (opcode == OP_COND || opcode == OP_SCOND) - { - if (*trypath == OP_CREF) - { - SLJIT_ASSERT(has_alternatives); - add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), - CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(trypath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); - trypath += 1 + IMM2_SIZE; - } - else if (*trypath == OP_NCREF) - { - SLJIT_ASSERT(has_alternatives); - stacksize = GET2(trypath, 1); - jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(stacksize << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); - - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); - OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, (stacksize << 8) | (common->ovector_start / sizeof(sljit_w))); - GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0); - OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); - sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector)); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); - add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0)); - - JUMPHERE(jump); - trypath += 1 + IMM2_SIZE; - } - else if (*trypath == OP_RREF || *trypath == OP_NRREF) - { - /* Never has other case. */ - BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL; - - stacksize = GET2(trypath, 1); - if (common->currententry == NULL) - stacksize = 0; - else if (stacksize == RREF_ANY) - stacksize = 1; - else if (common->currententry->start == 0) - stacksize = stacksize == 0; - else - stacksize = stacksize == GET2(common->start, common->currententry->start + 1 + LINK_SIZE); - - if (*trypath == OP_RREF || stacksize || common->currententry == NULL) - { - SLJIT_ASSERT(!has_alternatives); - if (stacksize != 0) - trypath += 1 + IMM2_SIZE; - else - { - if (*cc == OP_ALT) - { - trypath = cc + 1 + LINK_SIZE; - cc += GET(cc, 1); - } - else - trypath = cc; - } - } - else - { - SLJIT_ASSERT(has_alternatives); - - stacksize = GET2(trypath, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE)); - OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize); - GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0); - OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); - sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups)); - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); - add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0)); - trypath += 1 + IMM2_SIZE; - } - } - else - { - SLJIT_ASSERT(has_alternatives && *trypath >= OP_ASSERT && *trypath <= OP_ASSERTBACK_NOT); - /* Similar code as PUSH_BACKTRACK macro. */ - assert = sljit_alloc_memory(compiler, sizeof(assert_backtrack)); - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - return NULL; - memset(assert, 0, sizeof(assert_backtrack)); - assert->common.cc = trypath; - BACKTRACK_AS(bracket_backtrack)->u.assert = assert; - trypath = compile_assert_trypath(common, trypath, assert, TRUE); - } - } - -compile_trypath(common, trypath, cc, backtrack); -if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - return NULL; - -if (opcode == OP_ONCE) - { - if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) - { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - /* TMP2 which is set here used by OP_KETRMAX below. */ - if (ket == OP_KETRMAX) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0); - else if (ket == OP_KETRMIN) - { - /* Move the STR_PTR to the localptr. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0); - } - } - else - { - stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1; - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize) * sizeof(sljit_w)); - if (ket == OP_KETRMAX) - { - /* TMP2 which is set here used by OP_KETRMAX below. */ - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - } - } - } - -stacksize = 0; -if (ket != OP_KET || bra != OP_BRA) - stacksize++; -if (has_alternatives && opcode != OP_ONCE) - stacksize++; - -if (stacksize > 0) - allocate_stack(common, stacksize); - -stacksize = 0; -if (ket != OP_KET) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); - stacksize++; - } -else if (bra != OP_BRA) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); - stacksize++; - } - -if (has_alternatives) - { - if (opcode != OP_ONCE) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); - if (ket != OP_KETRMAX) - BACKTRACK_AS(bracket_backtrack)->alttrypath = LABEL(); - } - -/* Must be after the trypath label. */ -if (offset != 0) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0); - } - -if (ket == OP_KETRMAX) - { - if (opcode == OP_ONCE || opcode >= OP_SBRA) - { - if (has_alternatives) - BACKTRACK_AS(bracket_backtrack)->alttrypath = LABEL(); - /* Checking zero-length iteration. */ - if (opcode != OP_ONCE) - { - CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel); - /* Drop STR_PTR for greedy plus quantifier. */ - if (bra != OP_BRAZERO) - free_stack(common, 1); - } - else - /* TMP2 must contain the starting STR_PTR. */ - CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel); - } - else - JUMPTO(SLJIT_JUMP, rmaxlabel); - BACKTRACK_AS(bracket_backtrack)->recursivetrypath = LABEL(); - } - -if (bra == OP_BRAZERO) - BACKTRACK_AS(bracket_backtrack)->zerotrypath = LABEL(); - -if (bra == OP_BRAMINZERO) - { - /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */ - JUMPTO(SLJIT_JUMP, ((braminzero_backtrack *)parent)->trypath); - if (braminzerojump != NULL) - { - JUMPHERE(braminzerojump); - /* We need to release the end pointer to perform the - backtrack for the zero-length iteration. When - framesize is < 0, OP_ONCE will do the release itself. */ - if (opcode == OP_ONCE && BACKTRACK_AS(bracket_backtrack)->u.framesize >= 0) - { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - } - else if (ket == OP_KETRMIN && opcode != OP_ONCE) - free_stack(common, 1); - } - /* Continue to the normal backtrack. */ - } - -if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO) - decrease_call_count(common); - -/* Skip the other alternatives. */ -while (*cc == OP_ALT) - cc += GET(cc, 1); -cc += 1 + LINK_SIZE; -return cc; -} - -static pcre_uchar *compile_bracketpos_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) -{ -DEFINE_COMPILER; -backtrack_common *backtrack; -pcre_uchar opcode; -int localptr; -int cbraprivptr = 0; -int framesize; -int stacksize; -int offset = 0; -BOOL zero = FALSE; -pcre_uchar *ccbegin = NULL; -int stack; -struct sljit_label *loop = NULL; -struct jump_list *emptymatch = NULL; - -PUSH_BACKTRACK(sizeof(bracketpos_backtrack), cc, NULL); -if (*cc == OP_BRAPOSZERO) - { - zero = TRUE; - cc++; - } - -opcode = *cc; -localptr = PRIV_DATA(cc); -SLJIT_ASSERT(localptr != 0); -BACKTRACK_AS(bracketpos_backtrack)->localptr = localptr; -switch(opcode) - { - case OP_BRAPOS: - case OP_SBRAPOS: - ccbegin = cc + 1 + LINK_SIZE; - break; - - case OP_CBRAPOS: - case OP_SCBRAPOS: - offset = GET2(cc, 1 + LINK_SIZE); - cbraprivptr = OVECTOR_PRIV(offset); - offset <<= 1; - ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE; - break; - - default: - SLJIT_ASSERT_STOP(); - break; - } - -framesize = get_framesize(common, cc, FALSE); -BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize; -if (framesize < 0) - { - stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1; - if (!zero) - stacksize++; - BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; - allocate_stack(common, stacksize); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0); - - if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); - } - else - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - - if (!zero) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 1); - } -else - { - stacksize = framesize + 1; - if (!zero) - stacksize++; - if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS) - stacksize++; - BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; - allocate_stack(common, stacksize); - - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); - stack = 0; - if (!zero) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1); - stack++; - } - if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0); - stack++; - } - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0); - init_frame(common, cc, stacksize - 1, stacksize - framesize, FALSE); - } - -if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); - -loop = LABEL(); -while (*cc != OP_KETRPOS) - { - backtrack->top = NULL; - backtrack->topbacktracks = NULL; - cc += GET(cc, 1); - - compile_trypath(common, ccbegin, cc, backtrack); - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - return NULL; - - if (framesize < 0) - { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - - if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); - } - else - { - if (opcode == OP_SBRAPOS) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - } - - if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) - add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0)); - - if (!zero) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0); - } - else - { - if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) - { - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, stacksize * sizeof(sljit_w)); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); - } - else - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - OP2(SLJIT_ADD, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_w)); - if (opcode == OP_SBRAPOS) - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w)); - OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w), STR_PTR, 0); - } - - if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) - add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0)); - - if (!zero) - { - if (framesize < 0) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0); - else - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - } - } - JUMPTO(SLJIT_JUMP, loop); - flush_stubs(common); - - compile_backtrackpath(common, backtrack->top); - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - return NULL; - set_jumps(backtrack->topbacktracks, LABEL()); - - if (framesize < 0) - { - if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); - else - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - } - else - { - if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) - { - /* Last alternative. */ - if (*cc == OP_KETRPOS) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); - } - else - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w)); - } - } - - if (*cc == OP_KETRPOS) - break; - ccbegin = cc + 1 + LINK_SIZE; - } - -backtrack->topbacktracks = NULL; -if (!zero) - { - if (framesize < 0) - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0)); - else /* TMP2 is set to [localptr] above. */ - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0)); - } - -/* None of them matched. */ -set_jumps(emptymatch, LABEL()); -decrease_call_count(common); -return cc + 1 + LINK_SIZE; -} - -static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, int *arg1, int *arg2, pcre_uchar **end) -{ -int class_len; - -*opcode = *cc; -if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO) - { - cc++; - *type = OP_CHAR; - } -else if (*opcode >= OP_STARI && *opcode <= OP_POSUPTOI) - { - cc++; - *type = OP_CHARI; - *opcode -= OP_STARI - OP_STAR; - } -else if (*opcode >= OP_NOTSTAR && *opcode <= OP_NOTPOSUPTO) - { - cc++; - *type = OP_NOT; - *opcode -= OP_NOTSTAR - OP_STAR; - } -else if (*opcode >= OP_NOTSTARI && *opcode <= OP_NOTPOSUPTOI) - { - cc++; - *type = OP_NOTI; - *opcode -= OP_NOTSTARI - OP_STAR; - } -else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO) - { - cc++; - *opcode -= OP_TYPESTAR - OP_STAR; - *type = 0; - } -else - { - SLJIT_ASSERT(*opcode >= OP_CLASS || *opcode <= OP_XCLASS); - *type = *opcode; - cc++; - class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0); - *opcode = cc[class_len - 1]; - if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY) - { - *opcode -= OP_CRSTAR - OP_STAR; - if (end != NULL) - *end = cc + class_len; - } - else - { - SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE); - *arg1 = GET2(cc, (class_len + IMM2_SIZE)); - *arg2 = GET2(cc, class_len); - - if (*arg2 == 0) - { - SLJIT_ASSERT(*arg1 != 0); - *opcode = (*opcode == OP_CRRANGE) ? OP_UPTO : OP_MINUPTO; - } - if (*arg1 == *arg2) - *opcode = OP_EXACT; - - if (end != NULL) - *end = cc + class_len + 2 * IMM2_SIZE; - } - return cc; - } - -if (*opcode == OP_UPTO || *opcode == OP_MINUPTO || *opcode == OP_EXACT || *opcode == OP_POSUPTO) - { - *arg1 = GET2(cc, 0); - cc += IMM2_SIZE; - } - -if (*type == 0) - { - *type = *cc; - if (end != NULL) - *end = next_opcode(common, cc); - cc++; - return cc; - } - -if (end != NULL) - { - *end = cc + 1; -#ifdef SUPPORT_UTF - if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc); -#endif - } -return cc; -} - -static pcre_uchar *compile_iterator_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) -{ -DEFINE_COMPILER; -backtrack_common *backtrack; -pcre_uchar opcode; -pcre_uchar type; -int arg1 = -1, arg2 = -1; -pcre_uchar* end; -jump_list *nomatch = NULL; -struct sljit_jump *jump = NULL; -struct sljit_label *label; - -PUSH_BACKTRACK(sizeof(iterator_backtrack), cc, NULL); - -cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end); - -switch(opcode) - { - case OP_STAR: - case OP_PLUS: - case OP_UPTO: - case OP_CRRANGE: - if (type == OP_ANYNL || type == OP_EXTUNI) - { - if (opcode == OP_STAR || opcode == OP_UPTO) - { - allocate_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); - } - else - { - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - } - if (opcode == OP_UPTO || opcode == OP_CRRANGE) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); - - label = LABEL(); - compile_char1_trypath(common, type, cc, &backtrack->topbacktracks); - if (opcode == OP_UPTO || opcode == OP_CRRANGE) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - if (opcode == OP_CRRANGE && arg2 > 0) - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2, label); - if (opcode == OP_UPTO || (opcode == OP_CRRANGE && arg1 > 0)) - jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, arg1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); - } - - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - JUMPTO(SLJIT_JUMP, label); - if (jump != NULL) - JUMPHERE(jump); - } - else - { - if (opcode == OP_PLUS) - compile_char1_trypath(common, type, cc, &backtrack->topbacktracks); - allocate_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); - label = LABEL(); - compile_char1_trypath(common, type, cc, &nomatch); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - if (opcode <= OP_PLUS || (opcode == OP_CRRANGE && arg1 == 0)) - { - OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); - JUMPTO(SLJIT_JUMP, label); - } - else - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label); - } - set_jumps(nomatch, LABEL()); - if (opcode == OP_CRRANGE) - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_LESS, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, arg2 + 1)); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - } - BACKTRACK_AS(iterator_backtrack)->trypath = LABEL(); - break; - - case OP_MINSTAR: - case OP_MINPLUS: - if (opcode == OP_MINPLUS) - compile_char1_trypath(common, type, cc, &backtrack->topbacktracks); - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - BACKTRACK_AS(iterator_backtrack)->trypath = LABEL(); - break; - - case OP_MINUPTO: - case OP_CRMINRANGE: - allocate_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); - if (opcode == OP_CRMINRANGE) - add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); - BACKTRACK_AS(iterator_backtrack)->trypath = LABEL(); - break; - - case OP_QUERY: - case OP_MINQUERY: - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - if (opcode == OP_QUERY) - compile_char1_trypath(common, type, cc, &backtrack->topbacktracks); - BACKTRACK_AS(iterator_backtrack)->trypath = LABEL(); - break; - - case OP_EXACT: - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1); - label = LABEL(); - compile_char1_trypath(common, type, cc, &backtrack->topbacktracks); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label); - break; - - case OP_POSSTAR: - case OP_POSPLUS: - case OP_POSUPTO: - if (opcode != OP_POSSTAR) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); - label = LABEL(); - compile_char1_trypath(common, type, cc, &nomatch); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); - if (opcode != OP_POSUPTO) - { - if (opcode == OP_POSPLUS) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2); - JUMPTO(SLJIT_JUMP, label); - } - else - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label); - } - set_jumps(nomatch, LABEL()); - if (opcode == OP_POSPLUS) - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_LESS, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2)); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); - break; - - case OP_POSQUERY: - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); - compile_char1_trypath(common, type, cc, &nomatch); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); - set_jumps(nomatch, LABEL()); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); - break; - - default: - SLJIT_ASSERT_STOP(); - break; - } - -decrease_call_count(common); -return end; -} - -static SLJIT_INLINE pcre_uchar *compile_fail_accept_trypath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) -{ -DEFINE_COMPILER; -backtrack_common *backtrack; - -PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL); - -if (*cc == OP_FAIL) - { - add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); - return cc + 1; - } - -if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL) - { - /* No need to check notempty conditions. */ - if (common->acceptlabel == NULL) - add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP)); - else - JUMPTO(SLJIT_JUMP, common->acceptlabel); - return cc + 1; - } - -if (common->acceptlabel == NULL) - add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0))); -else - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->acceptlabel); -OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); -OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); -add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); -OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); -if (common->acceptlabel == NULL) - add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0)); -else - CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->acceptlabel); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); -if (common->acceptlabel == NULL) - add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0)); -else - CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel); -add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); -return cc + 1; -} - -static SLJIT_INLINE pcre_uchar *compile_close_trypath(compiler_common *common, pcre_uchar *cc) -{ -DEFINE_COMPILER; -int offset = GET2(cc, 1); - -/* Data will be discarded anyway... */ -if (common->currententry != NULL) - return cc + 1 + IMM2_SIZE; - -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR_PRIV(offset)); -offset <<= 1; -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); -return cc + 1 + IMM2_SIZE; -} - -static void compile_trypath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) -{ -DEFINE_COMPILER; -backtrack_common *backtrack; - -while (cc < ccend) - { - switch(*cc) - { - case OP_SOD: - case OP_SOM: - case OP_NOT_WORD_BOUNDARY: - case OP_WORD_BOUNDARY: - case OP_NOT_DIGIT: - case OP_DIGIT: - case OP_NOT_WHITESPACE: - case OP_WHITESPACE: - case OP_NOT_WORDCHAR: - case OP_WORDCHAR: - case OP_ANY: - case OP_ALLANY: - case OP_ANYBYTE: - case OP_NOTPROP: - case OP_PROP: - case OP_ANYNL: - case OP_NOT_HSPACE: - case OP_HSPACE: - case OP_NOT_VSPACE: - case OP_VSPACE: - case OP_EXTUNI: - case OP_EODN: - case OP_EOD: - case OP_CIRC: - case OP_CIRCM: - case OP_DOLL: - case OP_DOLLM: - case OP_NOT: - case OP_NOTI: - case OP_REVERSE: - cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); - break; - - case OP_SET_SOM: - PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); - cc++; - break; - - case OP_CHAR: - case OP_CHARI: - if (common->mode == JIT_COMPILE) - cc = compile_charn_trypath(common, cc, ccend, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); - else - cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); - break; - - case OP_STAR: - case OP_MINSTAR: - case OP_PLUS: - case OP_MINPLUS: - case OP_QUERY: - case OP_MINQUERY: - case OP_UPTO: - case OP_MINUPTO: - case OP_EXACT: - case OP_POSSTAR: - case OP_POSPLUS: - case OP_POSQUERY: - case OP_POSUPTO: - case OP_STARI: - case OP_MINSTARI: - case OP_PLUSI: - case OP_MINPLUSI: - case OP_QUERYI: - case OP_MINQUERYI: - case OP_UPTOI: - case OP_MINUPTOI: - case OP_EXACTI: - case OP_POSSTARI: - case OP_POSPLUSI: - case OP_POSQUERYI: - case OP_POSUPTOI: - case OP_NOTSTAR: - case OP_NOTMINSTAR: - case OP_NOTPLUS: - case OP_NOTMINPLUS: - case OP_NOTQUERY: - case OP_NOTMINQUERY: - case OP_NOTUPTO: - case OP_NOTMINUPTO: - case OP_NOTEXACT: - case OP_NOTPOSSTAR: - case OP_NOTPOSPLUS: - case OP_NOTPOSQUERY: - case OP_NOTPOSUPTO: - case OP_NOTSTARI: - case OP_NOTMINSTARI: - case OP_NOTPLUSI: - case OP_NOTMINPLUSI: - case OP_NOTQUERYI: - case OP_NOTMINQUERYI: - case OP_NOTUPTOI: - case OP_NOTMINUPTOI: - case OP_NOTEXACTI: - case OP_NOTPOSSTARI: - case OP_NOTPOSPLUSI: - case OP_NOTPOSQUERYI: - case OP_NOTPOSUPTOI: - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEQUERY: - case OP_TYPEMINQUERY: - case OP_TYPEUPTO: - case OP_TYPEMINUPTO: - case OP_TYPEEXACT: - case OP_TYPEPOSSTAR: - case OP_TYPEPOSPLUS: - case OP_TYPEPOSQUERY: - case OP_TYPEPOSUPTO: - cc = compile_iterator_trypath(common, cc, parent); - break; - - case OP_CLASS: - case OP_NCLASS: - if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRMINRANGE) - cc = compile_iterator_trypath(common, cc, parent); - else - cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); - break; - -#if defined SUPPORT_UTF || defined COMPILE_PCRE16 - case OP_XCLASS: - if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE) - cc = compile_iterator_trypath(common, cc, parent); - else - cc = compile_char1_trypath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks); - break; -#endif - - case OP_REF: - case OP_REFI: - if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRMINRANGE) - cc = compile_ref_iterator_trypath(common, cc, parent); - else - cc = compile_ref_trypath(common, cc, parent->top != NULL ? &parent->top->nextbacktracks : &parent->topbacktracks, TRUE, FALSE); - break; - - case OP_RECURSE: - cc = compile_recurse_trypath(common, cc, parent); - break; - - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc); - cc = compile_assert_trypath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE); - break; - - case OP_BRAMINZERO: - PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack), cc); - cc = bracketend(cc + 1); - if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN) - { - allocate_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - } - else - { - allocate_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0); - } - BACKTRACK_AS(braminzero_backtrack)->trypath = LABEL(); - if (cc[1] > OP_ASSERTBACK_NOT) - decrease_call_count(common); - break; - - case OP_ONCE: - case OP_ONCE_NC: - case OP_BRA: - case OP_CBRA: - case OP_COND: - case OP_SBRA: - case OP_SCBRA: - case OP_SCOND: - cc = compile_bracket_trypath(common, cc, parent); - break; - - case OP_BRAZERO: - if (cc[1] > OP_ASSERTBACK_NOT) - cc = compile_bracket_trypath(common, cc, parent); - else - { - PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack), cc); - cc = compile_assert_trypath(common, cc, BACKTRACK_AS(assert_backtrack), FALSE); - } - break; - - case OP_BRAPOS: - case OP_CBRAPOS: - case OP_SBRAPOS: - case OP_SCBRAPOS: - case OP_BRAPOSZERO: - cc = compile_bracketpos_trypath(common, cc, parent); - break; - - case OP_MARK: - PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); - SLJIT_ASSERT(common->mark_ptr != 0); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); - allocate_stack(common, 1); - OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)(cc + 2)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); - cc += 1 + 2 + cc[1]; - break; - - case OP_COMMIT: - PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); - cc += 1; - break; - - case OP_FAIL: - case OP_ACCEPT: - case OP_ASSERT_ACCEPT: - cc = compile_fail_accept_trypath(common, cc, parent); - break; - - case OP_CLOSE: - cc = compile_close_trypath(common, cc); - break; - - case OP_SKIPZERO: - cc = bracketend(cc + 1); - break; - - default: - SLJIT_ASSERT_STOP(); - return; - } - if (cc == NULL) - return; - } -SLJIT_ASSERT(cc == ccend); -} - -#undef PUSH_BACKTRACK -#undef PUSH_BACKTRACK_NOVALUE -#undef BACKTRACK_AS - -#define COMPILE_BACKTRACKPATH(current) \ - do \ - { \ - compile_backtrackpath(common, (current)); \ - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ - return; \ - } \ - while (0) - -#define CURRENT_AS(type) ((type *)current) - -static void compile_iterator_backtrackpath(compiler_common *common, struct backtrack_common *current) -{ -DEFINE_COMPILER; -pcre_uchar *cc = current->cc; -pcre_uchar opcode; -pcre_uchar type; -int arg1 = -1, arg2 = -1; -struct sljit_label *label = NULL; -struct sljit_jump *jump = NULL; -jump_list *jumplist = NULL; - -cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, NULL); - -switch(opcode) - { - case OP_STAR: - case OP_PLUS: - case OP_UPTO: - case OP_CRRANGE: - if (type == OP_ANYNL || type == OP_EXTUNI) - { - set_jumps(current->topbacktracks, LABEL()); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - free_stack(common, 1); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath); - } - else - { - if (opcode <= OP_PLUS || opcode == OP_UPTO) - arg2 = 0; - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, arg2 + 1); - OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - skip_char_back(common); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath); - if (opcode == OP_CRRANGE) - set_jumps(current->topbacktracks, LABEL()); - JUMPHERE(jump); - free_stack(common, 2); - if (opcode == OP_PLUS) - set_jumps(current->topbacktracks, LABEL()); - } - break; - - case OP_MINSTAR: - case OP_MINPLUS: - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - compile_char1_trypath(common, type, cc, &jumplist); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath); - set_jumps(jumplist, LABEL()); - free_stack(common, 1); - if (opcode == OP_MINPLUS) - set_jumps(current->topbacktracks, LABEL()); - break; - - case OP_MINUPTO: - case OP_CRMINRANGE: - if (opcode == OP_CRMINRANGE) - { - label = LABEL(); - set_jumps(current->topbacktracks, label); - } - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - compile_char1_trypath(common, type, cc, &jumplist); - - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); - - if (opcode == OP_CRMINRANGE) - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2 + 1, label); - - if (opcode == OP_CRMINRANGE && arg1 == 0) - JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath); - else - CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 2, CURRENT_AS(iterator_backtrack)->trypath); - - set_jumps(jumplist, LABEL()); - free_stack(common, 2); - break; - - case OP_QUERY: - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath); - jump = JUMP(SLJIT_JUMP); - set_jumps(current->topbacktracks, LABEL()); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath); - JUMPHERE(jump); - free_stack(common, 1); - break; - - case OP_MINQUERY: - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); - compile_char1_trypath(common, type, cc, &jumplist); - JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_backtrack)->trypath); - set_jumps(jumplist, LABEL()); - JUMPHERE(jump); - free_stack(common, 1); - break; - - case OP_EXACT: - case OP_POSPLUS: - set_jumps(current->topbacktracks, LABEL()); - break; - - case OP_POSSTAR: - case OP_POSQUERY: - case OP_POSUPTO: - break; - - default: - SLJIT_ASSERT_STOP(); - break; - } -} - -static void compile_ref_iterator_backtrackpath(compiler_common *common, struct backtrack_common *current) -{ -DEFINE_COMPILER; -pcre_uchar *cc = current->cc; -pcre_uchar type; - -type = cc[1 + IMM2_SIZE]; -if ((type & 0x1) == 0) - { - set_jumps(current->topbacktracks, LABEL()); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - free_stack(common, 1); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath); - return; - } - -OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); -CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_backtrack)->trypath); -set_jumps(current->topbacktracks, LABEL()); -free_stack(common, 2); -} - -static void compile_recurse_backtrackpath(compiler_common *common, struct backtrack_common *current) -{ -DEFINE_COMPILER; - -set_jumps(current->topbacktracks, LABEL()); - -if (common->has_set_som && common->mark_ptr != 0) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - free_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0); - } -else if (common->has_set_som || common->mark_ptr != 0) - { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - free_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->has_set_som ? (int)(OVECTOR(0)) : common->mark_ptr, TMP2, 0); - } -} - -static void compile_assert_backtrackpath(compiler_common *common, struct backtrack_common *current) -{ -DEFINE_COMPILER; -pcre_uchar *cc = current->cc; -pcre_uchar bra = OP_BRA; -struct sljit_jump *brajump = NULL; - -SLJIT_ASSERT(*cc != OP_BRAMINZERO); -if (*cc == OP_BRAZERO) - { - bra = *cc; - cc++; - } - -if (bra == OP_BRAZERO) - { - SLJIT_ASSERT(current->topbacktracks == NULL); - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - } - -if (CURRENT_AS(assert_backtrack)->framesize < 0) - { - set_jumps(current->topbacktracks, LABEL()); - - if (bra == OP_BRAZERO) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->trypath); - free_stack(common, 1); - } - return; - } - -if (bra == OP_BRAZERO) - { - if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT) - { - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_backtrack)->trypath); - free_stack(common, 1); - return; - } - free_stack(common, 1); - brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); - } - -if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK) - { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->localptr); - add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_backtrack)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_backtrack)->framesize * sizeof(sljit_w)); - - set_jumps(current->topbacktracks, LABEL()); - } -else - set_jumps(current->topbacktracks, LABEL()); - -if (bra == OP_BRAZERO) - { - /* We know there is enough place on the stack. */ - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); - JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_backtrack)->trypath); - JUMPHERE(brajump); - } -} - -static void compile_bracket_backtrackpath(compiler_common *common, struct backtrack_common *current) -{ -DEFINE_COMPILER; -int opcode; -int offset = 0; -int localptr = CURRENT_AS(bracket_backtrack)->localptr; -int stacksize; -int count; -pcre_uchar *cc = current->cc; -pcre_uchar *ccbegin; -pcre_uchar *ccprev; -jump_list *jumplist = NULL; -jump_list *jumplistitem = NULL; -pcre_uchar bra = OP_BRA; -pcre_uchar ket; -assert_backtrack *assert; -BOOL has_alternatives; -struct sljit_jump *brazero = NULL; -struct sljit_jump *once = NULL; -struct sljit_jump *cond = NULL; -struct sljit_label *rminlabel = NULL; - -if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) - { - bra = *cc; - cc++; - } - -opcode = *cc; -ccbegin = cc; -ket = *(bracketend(ccbegin) - 1 - LINK_SIZE); -cc += GET(cc, 1); -has_alternatives = *cc == OP_ALT; -if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) - has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_backtrack)->u.condfailed != NULL; -if (opcode == OP_CBRA || opcode == OP_SCBRA) - offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1; -if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) - opcode = OP_SCOND; -if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) - opcode = OP_ONCE; - -if (ket == OP_KETRMAX) - { - if (bra == OP_BRAZERO) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - free_stack(common, 1); - brazero = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0); - } - } -else if (ket == OP_KETRMIN) - { - if (bra != OP_BRAMINZERO) - { - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - if (opcode >= OP_SBRA || opcode == OP_ONCE) - { - /* Checking zero-length iteration. */ - if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize < 0) - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, CURRENT_AS(bracket_backtrack)->recursivetrypath); - else - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_backtrack)->u.framesize + 1) * sizeof(sljit_w), CURRENT_AS(bracket_backtrack)->recursivetrypath); - } - if (opcode != OP_ONCE) - free_stack(common, 1); - } - else - JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->recursivetrypath); - } - rminlabel = LABEL(); - } -else if (bra == OP_BRAZERO) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - free_stack(common, 1); - brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); - } - -if (SLJIT_UNLIKELY(opcode == OP_ONCE)) - { - if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) - { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - } - once = JUMP(SLJIT_JUMP); - } -else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) - { - if (has_alternatives) - { - /* Always exactly one alternative. */ - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - free_stack(common, 1); - - jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list)); - if (SLJIT_UNLIKELY(!jumplistitem)) - return; - jumplist = jumplistitem; - jumplistitem->next = NULL; - jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 1); - } - } -else if (*cc == OP_ALT) - { - /* Build a jump list. Get the last successfully matched branch index. */ - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - free_stack(common, 1); - count = 1; - do - { - /* Append as the last item. */ - if (jumplist != NULL) - { - jumplistitem->next = sljit_alloc_memory(compiler, sizeof(jump_list)); - jumplistitem = jumplistitem->next; - } - else - { - jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list)); - jumplist = jumplistitem; - } - - if (SLJIT_UNLIKELY(!jumplistitem)) - return; - - jumplistitem->next = NULL; - jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, count++); - cc += GET(cc, 1); - } - while (*cc == OP_ALT); - - cc = ccbegin + GET(ccbegin, 1); - } - -COMPILE_BACKTRACKPATH(current->top); -if (current->topbacktracks) - set_jumps(current->topbacktracks, LABEL()); - -if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) - { - /* Conditional block always has at most one alternative. */ - if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) - { - SLJIT_ASSERT(has_alternatives); - assert = CURRENT_AS(bracket_backtrack)->u.assert; - if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK)) - { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr); - add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w)); - } - cond = JUMP(SLJIT_JUMP); - set_jumps(CURRENT_AS(bracket_backtrack)->u.assert->condfailed, LABEL()); - } - else if (CURRENT_AS(bracket_backtrack)->u.condfailed != NULL) - { - SLJIT_ASSERT(has_alternatives); - cond = JUMP(SLJIT_JUMP); - set_jumps(CURRENT_AS(bracket_backtrack)->u.condfailed, LABEL()); - } - else - SLJIT_ASSERT(!has_alternatives); - } - -if (has_alternatives) - { - count = 1; - do - { - current->top = NULL; - current->topbacktracks = NULL; - current->nextbacktracks = NULL; - if (*cc == OP_ALT) - { - ccprev = cc + 1 + LINK_SIZE; - cc += GET(cc, 1); - if (opcode != OP_COND && opcode != OP_SCOND) - { - if (localptr != 0 && opcode != OP_ONCE) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - else - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - } - compile_trypath(common, ccprev, cc, current); - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - return; - } - - /* Instructions after the current alternative is succesfully matched. */ - /* There is a similar code in compile_bracket_trypath. */ - if (opcode == OP_ONCE) - { - if (CURRENT_AS(bracket_backtrack)->u.framesize < 0) - { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - /* TMP2 which is set here used by OP_KETRMAX below. */ - if (ket == OP_KETRMAX) - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0); - else if (ket == OP_KETRMIN) - { - /* Move the STR_PTR to the localptr. */ - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0); - } - } - else - { - OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (CURRENT_AS(bracket_backtrack)->u.framesize + 2) * sizeof(sljit_w)); - if (ket == OP_KETRMAX) - { - /* TMP2 which is set here used by OP_KETRMAX below. */ - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - } - } - } - - stacksize = 0; - if (opcode != OP_ONCE) - stacksize++; - if (ket != OP_KET || bra != OP_BRA) - stacksize++; - - if (stacksize > 0) { - if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize >= 0) - allocate_stack(common, stacksize); - else - { - /* We know we have place at least for one item on the top of the stack. */ - SLJIT_ASSERT(stacksize == 1); - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); - } - } - - stacksize = 0; - if (ket != OP_KET || bra != OP_BRA) - { - if (ket != OP_KET) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); - else - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); - stacksize++; - } - - if (opcode != OP_ONCE) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, count++); - - if (offset != 0) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0); - } - - JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alttrypath); - - if (opcode != OP_ONCE) - { - SLJIT_ASSERT(jumplist); - JUMPHERE(jumplist->jump); - jumplist = jumplist->next; - } - - COMPILE_BACKTRACKPATH(current->top); - if (current->topbacktracks) - set_jumps(current->topbacktracks, LABEL()); - SLJIT_ASSERT(!current->nextbacktracks); - } - while (*cc == OP_ALT); - SLJIT_ASSERT(!jumplist); - - if (cond != NULL) - { - SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND); - assert = CURRENT_AS(bracket_backtrack)->u.assert; - if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0) - - { - OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr); - add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w)); - } - JUMPHERE(cond); - } - - /* Free the STR_PTR. */ - if (localptr == 0) - free_stack(common, 1); - } - -if (offset != 0) - { - /* Using both tmp register is better for instruction scheduling. */ - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(2)); - free_stack(common, 3); - } -else if (opcode == OP_SBRA || opcode == OP_SCOND) - { - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(0)); - free_stack(common, 1); - } -else if (opcode == OP_ONCE) - { - cc = ccbegin + GET(ccbegin, 1); - if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) - { - /* Reset head and drop saved frame. */ - stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1; - free_stack(common, CURRENT_AS(bracket_backtrack)->u.framesize + stacksize); - } - else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN)) - { - /* The STR_PTR must be released. */ - free_stack(common, 1); - } - - JUMPHERE(once); - /* Restore previous localptr */ - if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_backtrack)->u.framesize * sizeof(sljit_w)); - else if (ket == OP_KETRMIN) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - /* See the comment below. */ - free_stack(common, 2); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); - } - } - -if (ket == OP_KETRMAX) - { - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - if (bra != OP_BRAZERO) - free_stack(common, 1); - CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_backtrack)->recursivetrypath); - if (bra == OP_BRAZERO) - { - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zerotrypath); - JUMPHERE(brazero); - free_stack(common, 1); - } - } -else if (ket == OP_KETRMIN) - { - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - - /* OP_ONCE removes everything in case of a backtrack, so we don't - need to explicitly release the STR_PTR. The extra release would - affect badly the free_stack(2) above. */ - if (opcode != OP_ONCE) - free_stack(common, 1); - CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rminlabel); - if (opcode == OP_ONCE) - free_stack(common, bra == OP_BRAMINZERO ? 2 : 1); - else if (bra == OP_BRAMINZERO) - free_stack(common, 1); - } -else if (bra == OP_BRAZERO) - { - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->zerotrypath); - JUMPHERE(brazero); - } -} - -static void compile_bracketpos_backtrackpath(compiler_common *common, struct backtrack_common *current) -{ -DEFINE_COMPILER; -int offset; -struct sljit_jump *jump; - -if (CURRENT_AS(bracketpos_backtrack)->framesize < 0) - { - if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS) - { - offset = (GET2(current->cc, 1 + LINK_SIZE)) << 1; - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); - } - set_jumps(current->topbacktracks, LABEL()); - free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize); - return; - } - -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->localptr); -add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - -if (current->topbacktracks) - { - jump = JUMP(SLJIT_JUMP); - set_jumps(current->topbacktracks, LABEL()); - /* Drop the stack frame. */ - free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize); - JUMPHERE(jump); - } -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_backtrack)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_backtrack)->framesize * sizeof(sljit_w)); -} - -static void compile_braminzero_backtrackpath(compiler_common *common, struct backtrack_common *current) -{ -assert_backtrack backtrack; - -current->top = NULL; -current->topbacktracks = NULL; -current->nextbacktracks = NULL; -if (current->cc[1] > OP_ASSERTBACK_NOT) - { - /* Manual call of compile_bracket_trypath and compile_bracket_backtrackpath. */ - compile_bracket_trypath(common, current->cc, current); - compile_bracket_backtrackpath(common, current->top); - } -else - { - memset(&backtrack, 0, sizeof(backtrack)); - backtrack.common.cc = current->cc; - backtrack.trypath = CURRENT_AS(braminzero_backtrack)->trypath; - /* Manual call of compile_assert_trypath. */ - compile_assert_trypath(common, current->cc, &backtrack, FALSE); - } -SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks); -} - -static void compile_backtrackpath(compiler_common *common, struct backtrack_common *current) -{ -DEFINE_COMPILER; - -while (current) - { - if (current->nextbacktracks != NULL) - set_jumps(current->nextbacktracks, LABEL()); - switch(*current->cc) - { - case OP_SET_SOM: - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - free_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP1, 0); - break; - - case OP_STAR: - case OP_MINSTAR: - case OP_PLUS: - case OP_MINPLUS: - case OP_QUERY: - case OP_MINQUERY: - case OP_UPTO: - case OP_MINUPTO: - case OP_EXACT: - case OP_POSSTAR: - case OP_POSPLUS: - case OP_POSQUERY: - case OP_POSUPTO: - case OP_STARI: - case OP_MINSTARI: - case OP_PLUSI: - case OP_MINPLUSI: - case OP_QUERYI: - case OP_MINQUERYI: - case OP_UPTOI: - case OP_MINUPTOI: - case OP_EXACTI: - case OP_POSSTARI: - case OP_POSPLUSI: - case OP_POSQUERYI: - case OP_POSUPTOI: - case OP_NOTSTAR: - case OP_NOTMINSTAR: - case OP_NOTPLUS: - case OP_NOTMINPLUS: - case OP_NOTQUERY: - case OP_NOTMINQUERY: - case OP_NOTUPTO: - case OP_NOTMINUPTO: - case OP_NOTEXACT: - case OP_NOTPOSSTAR: - case OP_NOTPOSPLUS: - case OP_NOTPOSQUERY: - case OP_NOTPOSUPTO: - case OP_NOTSTARI: - case OP_NOTMINSTARI: - case OP_NOTPLUSI: - case OP_NOTMINPLUSI: - case OP_NOTQUERYI: - case OP_NOTMINQUERYI: - case OP_NOTUPTOI: - case OP_NOTMINUPTOI: - case OP_NOTEXACTI: - case OP_NOTPOSSTARI: - case OP_NOTPOSPLUSI: - case OP_NOTPOSQUERYI: - case OP_NOTPOSUPTOI: - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEQUERY: - case OP_TYPEMINQUERY: - case OP_TYPEUPTO: - case OP_TYPEMINUPTO: - case OP_TYPEEXACT: - case OP_TYPEPOSSTAR: - case OP_TYPEPOSPLUS: - case OP_TYPEPOSQUERY: - case OP_TYPEPOSUPTO: - case OP_CLASS: - case OP_NCLASS: -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - case OP_XCLASS: -#endif - compile_iterator_backtrackpath(common, current); - break; - - case OP_REF: - case OP_REFI: - compile_ref_iterator_backtrackpath(common, current); - break; - - case OP_RECURSE: - compile_recurse_backtrackpath(common, current); - break; - - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - compile_assert_backtrackpath(common, current); - break; - - case OP_ONCE: - case OP_ONCE_NC: - case OP_BRA: - case OP_CBRA: - case OP_COND: - case OP_SBRA: - case OP_SCBRA: - case OP_SCOND: - compile_bracket_backtrackpath(common, current); - break; - - case OP_BRAZERO: - if (current->cc[1] > OP_ASSERTBACK_NOT) - compile_bracket_backtrackpath(common, current); - else - compile_assert_backtrackpath(common, current); - break; - - case OP_BRAPOS: - case OP_CBRAPOS: - case OP_SBRAPOS: - case OP_SCBRAPOS: - case OP_BRAPOSZERO: - compile_bracketpos_backtrackpath(common, current); - break; - - case OP_BRAMINZERO: - compile_braminzero_backtrackpath(common, current); - break; - - case OP_MARK: - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - free_stack(common, 1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP1, 0); - break; - - case OP_COMMIT: - OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); - if (common->leavelabel == NULL) - add_jump(compiler, &common->leave, JUMP(SLJIT_JUMP)); - else - JUMPTO(SLJIT_JUMP, common->leavelabel); - break; - - case OP_FAIL: - case OP_ACCEPT: - case OP_ASSERT_ACCEPT: - set_jumps(current->topbacktracks, LABEL()); - break; - - default: - SLJIT_ASSERT_STOP(); - break; - } - current = current->prev; - } -} - -static SLJIT_INLINE void compile_recurse(compiler_common *common) -{ -DEFINE_COMPILER; -pcre_uchar *cc = common->start + common->currententry->start; -pcre_uchar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE); -pcre_uchar *ccend = bracketend(cc); -int localsize = get_localsize(common, ccbegin, ccend); -int framesize = get_framesize(common, cc, TRUE); -int alternativesize; -BOOL needsframe; -backtrack_common altbacktrack; -struct sljit_label *save_leavelabel = common->leavelabel; -jump_list *save_leave = common->leave; -struct sljit_jump *jump; - -SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS); -needsframe = framesize >= 0; -if (!needsframe) - framesize = 0; -alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0; - -SLJIT_ASSERT(common->currententry->entry == NULL && common->recursive_head != 0); -common->currententry->entry = LABEL(); -set_jumps(common->currententry->calls, common->currententry->entry); - -sljit_emit_fast_enter(compiler, TMP2, 0); -allocate_stack(common, localsize + framesize + alternativesize); -OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(localsize + framesize + alternativesize - 1), TMP2, 0); -copy_locals(common, ccbegin, ccend, TRUE, localsize + framesize + alternativesize, framesize + alternativesize); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head, STACK_TOP, 0); -if (needsframe) - init_frame(common, cc, framesize + alternativesize - 1, alternativesize, TRUE); - -if (alternativesize > 0) - OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); - -memset(&altbacktrack, 0, sizeof(backtrack_common)); -common->leavelabel = NULL; -common->acceptlabel = NULL; -common->leave = NULL; -common->accept = NULL; -altbacktrack.cc = ccbegin; -cc += GET(cc, 1); -while (1) - { - altbacktrack.top = NULL; - altbacktrack.topbacktracks = NULL; - - if (altbacktrack.cc != ccbegin) - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); - - compile_trypath(common, altbacktrack.cc, cc, &altbacktrack); - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - { - common->leavelabel = save_leavelabel; - common->leave = save_leave; - return; - } - - add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP)); - - compile_backtrackpath(common, altbacktrack.top); - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - { - common->leavelabel = save_leavelabel; - common->leave = save_leave; - return; - } - set_jumps(altbacktrack.topbacktracks, LABEL()); - - if (*cc != OP_ALT) - break; - - altbacktrack.cc = cc + 1 + LINK_SIZE; - cc += GET(cc, 1); - } -/* None of them matched. */ -if (common->leave != NULL) - set_jumps(common->leave, LABEL()); - -OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0); -jump = JUMP(SLJIT_JUMP); - -set_jumps(common->accept, LABEL()); -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head); -if (needsframe) - { - OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w)); - add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w)); - } -OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1); - -JUMPHERE(jump); -copy_locals(common, ccbegin, ccend, FALSE, localsize + framesize + alternativesize, framesize + alternativesize); -free_stack(common, localsize + framesize + alternativesize); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_w)); -OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->recursive_head, TMP2, 0); -sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0); - -common->leavelabel = save_leavelabel; -common->leave = save_leave; -} - -#undef COMPILE_BACKTRACKPATH -#undef CURRENT_AS - -void -PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra, int mode) -{ -struct sljit_compiler *compiler; -backtrack_common rootbacktrack; -compiler_common common_data; -compiler_common *common = &common_data; -const pcre_uint8 *tables = re->tables; -pcre_study_data *study; -int localsize; -pcre_uchar *ccend; -executable_functions *functions; -void *executable_func; -sljit_uw executable_size; -struct sljit_label *mainloop = NULL; -struct sljit_label *empty_match_found; -struct sljit_label *empty_match_backtrack; -struct sljit_jump *jump; -struct sljit_jump *reqbyte_notfound = NULL; -struct sljit_jump *empty_match; - -SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0); -study = extra->study_data; - -if (!tables) - tables = PRIV(default_tables); - -memset(&rootbacktrack, 0, sizeof(backtrack_common)); -memset(common, 0, sizeof(compiler_common)); -rootbacktrack.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size; - -common->start = rootbacktrack.cc; -common->fcc = tables + fcc_offset; -common->lcc = (sljit_w)(tables + lcc_offset); -common->mode = mode; -common->nltype = NLTYPE_FIXED; -switch(re->options & PCRE_NEWLINE_BITS) - { - case 0: - /* Compile-time default */ - switch (NEWLINE) - { - case -1: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break; - case -2: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break; - default: common->newline = NEWLINE; break; - } - break; - case PCRE_NEWLINE_CR: common->newline = CHAR_CR; break; - case PCRE_NEWLINE_LF: common->newline = CHAR_NL; break; - case PCRE_NEWLINE_CR+ - PCRE_NEWLINE_LF: common->newline = (CHAR_CR << 8) | CHAR_NL; break; - case PCRE_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break; - case PCRE_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break; - default: return; - } -if ((re->options & PCRE_BSR_ANYCRLF) != 0) - common->bsr_nltype = NLTYPE_ANYCRLF; -else if ((re->options & PCRE_BSR_UNICODE) != 0) - common->bsr_nltype = NLTYPE_ANY; -else - { -#ifdef BSR_ANYCRLF - common->bsr_nltype = NLTYPE_ANYCRLF; -#else - common->bsr_nltype = NLTYPE_ANY; -#endif - } -common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; -common->ctypes = (sljit_w)(tables + ctypes_offset); -common->name_table = (sljit_w)((pcre_uchar *)re + re->name_table_offset); -common->name_count = re->name_count; -common->name_entry_size = re->name_entry_size; -common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0; -#ifdef SUPPORT_UTF -/* PCRE_UTF16 has the same value as PCRE_UTF8. */ -common->utf = (re->options & PCRE_UTF8) != 0; -#ifdef SUPPORT_UCP -common->use_ucp = (re->options & PCRE_UCP) != 0; -#endif -#endif /* SUPPORT_UTF */ -ccend = bracketend(rootbacktrack.cc); - -/* Calculate the local space size on the stack. */ -common->ovector_start = CALL_LIMIT + sizeof(sljit_w); - -SLJIT_ASSERT(*rootbacktrack.cc == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET); -localsize = get_localspace(common, rootbacktrack.cc, ccend); -if (localsize < 0) - return; - -/* Checking flags and updating ovector_start. */ -if (mode == JIT_COMPILE && (re->flags & PCRE_REQCHSET) != 0 && (re->options & PCRE_NO_START_OPTIMIZE) == 0) - { - common->req_char_ptr = common->ovector_start; - common->ovector_start += sizeof(sljit_w); - } -if (mode != JIT_COMPILE) - { - common->start_used_ptr = common->ovector_start; - common->ovector_start += sizeof(sljit_w); - if (mode == JIT_PARTIAL_SOFT_COMPILE) - { - common->hit_start = common->ovector_start; - common->ovector_start += sizeof(sljit_w); - } - } -if ((re->options & PCRE_FIRSTLINE) != 0) - { - common->first_line_end = common->ovector_start; - common->ovector_start += sizeof(sljit_w); - } - -/* Aligning ovector to even number of sljit words. */ -if ((common->ovector_start & sizeof(sljit_w)) != 0) - common->ovector_start += sizeof(sljit_w); - -SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0)); -common->cbraptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_w); -localsize += common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w); -if (localsize > SLJIT_MAX_LOCAL_SIZE) - return; -common->localptrs = (int *)SLJIT_MALLOC((ccend - rootbacktrack.cc) * sizeof(int)); -if (!common->localptrs) - return; -memset(common->localptrs, 0, (ccend - rootbacktrack.cc) * sizeof(int)); -set_localptrs(common, common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w), ccend); - -compiler = sljit_create_compiler(); -if (!compiler) - { - SLJIT_FREE(common->localptrs); - return; - } -common->compiler = compiler; - -/* Main pcre_jit_exec entry. */ -sljit_emit_enter(compiler, 1, 5, 5, localsize); - -/* Register init. */ -reset_ovector(common, (re->top_bracket + 1) * 2); -if (common->req_char_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->req_char_ptr, SLJIT_TEMPORARY_REG1, 0); - -OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_SAVED_REG1, 0); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_SAVED_REG1, 0); -OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); -OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end)); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); -OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, calllimit)); -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base)); -OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit)); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0); - -if (mode == JIT_PARTIAL_SOFT_COMPILE) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); - -/* Main part of the matching */ -if ((re->options & PCRE_ANCHORED) == 0) - { - mainloop = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0); - /* Forward search if possible. */ - if ((re->options & PCRE_NO_START_OPTIMIZE) == 0) - { - if ((re->flags & PCRE_FIRSTSET) != 0) - fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0); - else if ((re->flags & PCRE_STARTLINE) != 0) - fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0); - else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0) - fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0); - } - } -if (common->req_char_ptr != 0) - reqbyte_notfound = search_requested_char(common, (pcre_uchar)re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0); - -/* Store the current STR_PTR in OVECTOR(0). */ -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0); -/* Copy the limit of allowed recursions. */ -OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT); -if (common->mark_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0); -/* Copy the beginning of the string. */ -if (mode == JIT_PARTIAL_SOFT_COMPILE) - { - jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); - JUMPHERE(jump); - } -else if (mode == JIT_PARTIAL_HARD_COMPILE) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); - -compile_trypath(common, rootbacktrack.cc, ccend, &rootbacktrack); -if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - { - sljit_free_compiler(compiler); - SLJIT_FREE(common->localptrs); - return; - } - -empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); -empty_match_found = LABEL(); - -common->acceptlabel = LABEL(); -if (common->accept != NULL) - set_jumps(common->accept, common->acceptlabel); - -/* This means we have a match. Update the ovector. */ -copy_ovector(common, re->top_bracket + 1); -common->leavelabel = LABEL(); -if (common->leave != NULL) - set_jumps(common->leave, common->leavelabel); -sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); - -if (mode != JIT_COMPILE) - { - common->partialmatchlabel = LABEL(); - set_jumps(common->partialmatch, common->partialmatchlabel); - return_with_partial_match(common, common->leavelabel); - } - -empty_match_backtrack = LABEL(); -compile_backtrackpath(common, rootbacktrack.top); -if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - { - sljit_free_compiler(compiler); - SLJIT_FREE(common->localptrs); - return; - } - -SLJIT_ASSERT(rootbacktrack.prev == NULL); - -if (mode == JIT_PARTIAL_SOFT_COMPILE) - { - /* Update hit_start only in the first time. */ - jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1); - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, TMP1, 0); - JUMPHERE(jump); - } - -/* Check we have remaining characters. */ -OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); - -if ((re->options & PCRE_ANCHORED) == 0) - { - if ((re->options & PCRE_FIRSTLINE) == 0) - { - if (mode == JIT_COMPILE && study != NULL && study->minlength > 1 && (re->options & PCRE_NO_START_OPTIMIZE) == 0) - { - OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength + 1)); - CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_END, 0, mainloop); - } - else - CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop); - } - else - { - SLJIT_ASSERT(common->first_line_end != 0); - if (mode == JIT_COMPILE && study != NULL && study->minlength > 1 && (re->options & PCRE_NO_START_OPTIMIZE) == 0) - { - OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength + 1)); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0); - COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end); - COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_GREATER_EQUAL); - JUMPTO(SLJIT_C_ZERO, mainloop); - } - else - CMPTO(SLJIT_C_LESS, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, mainloop); - } - } - -/* No more remaining characters. */ -if (reqbyte_notfound != NULL) - JUMPHERE(reqbyte_notfound); - -if (mode == JIT_PARTIAL_SOFT_COMPILE) - CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0, common->partialmatchlabel); - -OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); -JUMPTO(SLJIT_JUMP, common->leavelabel); - -flush_stubs(common); - -JUMPHERE(empty_match); -OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); -OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); -CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_backtrack); -OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); -CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); -CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found); -JUMPTO(SLJIT_JUMP, empty_match_backtrack); - -common->currententry = common->entries; -while (common->currententry != NULL) - { - /* Might add new entries. */ - compile_recurse(common); - if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) - { - sljit_free_compiler(compiler); - SLJIT_FREE(common->localptrs); - return; - } - flush_stubs(common); - common->currententry = common->currententry->next; - } - -/* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */ -/* This is a (really) rare case. */ -set_jumps(common->stackalloc, LABEL()); -/* RETURN_ADDR is not a saved register. */ -sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); -OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0); -OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); -OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0); -OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE); - -sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize)); -jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); -OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); -OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); -OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top)); -OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit)); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); -sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); - -/* Allocation failed. */ -JUMPHERE(jump); -/* We break the return address cache here, but this is a really rare case. */ -OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT); -JUMPTO(SLJIT_JUMP, common->leavelabel); - -/* Call limit reached. */ -set_jumps(common->calllimit, LABEL()); -OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT); -JUMPTO(SLJIT_JUMP, common->leavelabel); - -if (common->revertframes != NULL) - { - set_jumps(common->revertframes, LABEL()); - do_revertframes(common); - } -if (common->wordboundary != NULL) - { - set_jumps(common->wordboundary, LABEL()); - check_wordboundary(common); - } -if (common->anynewline != NULL) - { - set_jumps(common->anynewline, LABEL()); - check_anynewline(common); - } -if (common->hspace != NULL) - { - set_jumps(common->hspace, LABEL()); - check_hspace(common); - } -if (common->vspace != NULL) - { - set_jumps(common->vspace, LABEL()); - check_vspace(common); - } -if (common->casefulcmp != NULL) - { - set_jumps(common->casefulcmp, LABEL()); - do_casefulcmp(common); - } -if (common->caselesscmp != NULL) - { - set_jumps(common->caselesscmp, LABEL()); - do_caselesscmp(common); - } -#ifdef SUPPORT_UTF -if (common->utfreadchar != NULL) - { - set_jumps(common->utfreadchar, LABEL()); - do_utfreadchar(common); - } -#ifdef COMPILE_PCRE8 -if (common->utfreadtype8 != NULL) - { - set_jumps(common->utfreadtype8, LABEL()); - do_utfreadtype8(common); - } -#endif -#endif /* COMPILE_PCRE8 */ -#ifdef SUPPORT_UCP -if (common->getunichartype != NULL) - { - set_jumps(common->getunichartype, LABEL()); - do_getunichartype(common); - } -if (common->getunichartype_2 != NULL) - { - set_jumps(common->getunichartype_2, LABEL()); - do_getunichartype_2(common); - } -if (common->getunicharscript != NULL) - { - set_jumps(common->getunicharscript, LABEL()); - do_getunicharscript(common); - } -#endif - -SLJIT_FREE(common->localptrs); -executable_func = sljit_generate_code(compiler); -executable_size = sljit_get_generated_code_size(compiler); -sljit_free_compiler(compiler); -if (executable_func == NULL) - return; - -/* Reuse the function descriptor if possible. */ -if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL) - functions = (executable_functions *)extra->executable_jit; -else - { - functions = SLJIT_MALLOC(sizeof(executable_functions)); - if (functions == NULL) - { - /* This case is highly unlikely since we just recently - freed a lot of memory. Although not impossible. */ - sljit_free_code(executable_func); - return; - } - memset(functions, 0, sizeof(executable_functions)); - extra->executable_jit = functions; - extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT; - } - -functions->executable_funcs[mode] = executable_func; -functions->executable_sizes[mode] = executable_size; -} - -static int jit_machine_stack_exec(jit_arguments *arguments, void* executable_func) -{ -union { - void* executable_func; - jit_function call_executable_func; -} convert_executable_func; -pcre_uint8 local_area[LOCAL_SPACE_SIZE]; -struct sljit_stack local_stack; - -local_stack.top = (sljit_w)&local_area; -local_stack.base = local_stack.top; -local_stack.limit = local_stack.base + LOCAL_SPACE_SIZE; -local_stack.max_limit = local_stack.limit; -arguments->stack = &local_stack; -convert_executable_func.executable_func = executable_func; -return convert_executable_func.call_executable_func(arguments); -} - -int -PRIV(jit_exec)(const REAL_PCRE *re, const PUBL(extra) *extra_data, const pcre_uchar *subject, - int length, int start_offset, int options, int *offsets, int offsetcount) -{ -executable_functions *functions = (executable_functions *)extra_data->executable_jit; -union { - void* executable_func; - jit_function call_executable_func; -} convert_executable_func; -jit_arguments arguments; -int maxoffsetcount; -int retval; -int mode = JIT_COMPILE; - -if ((options & PCRE_PARTIAL_HARD) != 0) - mode = JIT_PARTIAL_HARD_COMPILE; -else if ((options & PCRE_PARTIAL_SOFT) != 0) - mode = JIT_PARTIAL_SOFT_COMPILE; - -if (functions->executable_funcs[mode] == NULL) - return PCRE_ERROR_NULL; - -/* Sanity checks should be handled by pcre_exec. */ -arguments.stack = NULL; -arguments.str = subject + start_offset; -arguments.begin = subject; -arguments.end = subject + length; -arguments.mark_ptr = NULL; -/* JIT decreases this value less frequently than the interpreter. */ -arguments.calllimit = ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) ? MATCH_LIMIT : extra_data->match_limit; -arguments.notbol = (options & PCRE_NOTBOL) != 0; -arguments.noteol = (options & PCRE_NOTEOL) != 0; -arguments.notempty = (options & PCRE_NOTEMPTY) != 0; -arguments.notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0; -arguments.offsets = offsets; - -/* pcre_exec() rounds offsetcount to a multiple of 3, and then uses only 2/3 of -the output vector for storing captured strings, with the remainder used as -workspace. We don't need the workspace here. For compatibility, we limit the -number of captured strings in the same way as pcre_exec(), so that the user -gets the same result with and without JIT. */ - -if (offsetcount != 2) - offsetcount = ((offsetcount - (offsetcount % 3)) * 2) / 3; -maxoffsetcount = (re->top_bracket + 1) * 2; -if (offsetcount > maxoffsetcount) - offsetcount = maxoffsetcount; -arguments.offsetcount = offsetcount; - -if (functions->callback) - arguments.stack = (struct sljit_stack *)functions->callback(functions->userdata); -else - arguments.stack = (struct sljit_stack *)functions->userdata; - -if (arguments.stack == NULL) - retval = jit_machine_stack_exec(&arguments, functions->executable_funcs[mode]); -else - { - convert_executable_func.executable_func = functions->executable_funcs[mode]; - retval = convert_executable_func.call_executable_func(&arguments); - } - -if (retval * 2 > offsetcount) - retval = 0; -if ((extra_data->flags & PCRE_EXTRA_MARK) != 0) - *(extra_data->mark) = arguments.mark_ptr; - -return retval; -} - -void -PRIV(jit_free)(void *executable_funcs) -{ -int i; -executable_functions *functions = (executable_functions *)executable_funcs; -for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++) - { - if (functions->executable_funcs[i] != NULL) - sljit_free_code(functions->executable_funcs[i]); - } -SLJIT_FREE(functions); -} - -int -PRIV(jit_get_size)(void *executable_funcs) -{ -int i; -sljit_uw size = 0; -sljit_uw *executable_sizes = ((executable_functions *)executable_funcs)->executable_sizes; -for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++) - size += executable_sizes[i]; -return (int)size; -} - -const char* -PRIV(jit_get_target)(void) -{ -return sljit_get_platform_name(); -} - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DECL pcre_jit_stack * -pcre_jit_stack_alloc(int startsize, int maxsize) -#else -PCRE_EXP_DECL pcre16_jit_stack * -pcre16_jit_stack_alloc(int startsize, int maxsize) -#endif -{ -if (startsize < 1 || maxsize < 1) - return NULL; -if (startsize > maxsize) - startsize = maxsize; -startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); -maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); -return (PUBL(jit_stack)*)sljit_allocate_stack(startsize, maxsize); -} - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DECL void -pcre_jit_stack_free(pcre_jit_stack *stack) -#else -PCRE_EXP_DECL void -pcre16_jit_stack_free(pcre16_jit_stack *stack) -#endif -{ -sljit_free_stack((struct sljit_stack *)stack); -} - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DECL void -pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata) -#else -PCRE_EXP_DECL void -pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata) -#endif -{ -executable_functions *functions; -if (extra != NULL && - (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && - extra->executable_jit != NULL) - { - functions = (executable_functions *)extra->executable_jit; - functions->callback = callback; - functions->userdata = userdata; - } -} - -#else /* SUPPORT_JIT */ - -/* These are dummy functions to avoid linking errors when JIT support is not -being compiled. */ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DECL pcre_jit_stack * -pcre_jit_stack_alloc(int startsize, int maxsize) -#else -PCRE_EXP_DECL pcre16_jit_stack * -pcre16_jit_stack_alloc(int startsize, int maxsize) -#endif -{ -(void)startsize; -(void)maxsize; -return NULL; -} - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DECL void -pcre_jit_stack_free(pcre_jit_stack *stack) -#else -PCRE_EXP_DECL void -pcre16_jit_stack_free(pcre16_jit_stack *stack) -#endif -{ -(void)stack; -} - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DECL void -pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata) -#else -PCRE_EXP_DECL void -pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata) -#endif -{ -(void)extra; -(void)callback; -(void)userdata; -} - -#endif - -/* End of pcre_jit_compile.c */ diff --git a/glib/pcre/pcre_newline.c b/glib/pcre/pcre_newline.c deleted file mode 100644 index ddd7708fa..000000000 --- a/glib/pcre/pcre_newline.c +++ /dev/null @@ -1,182 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains internal functions for testing newlines when more than -one kind of newline is to be recognized. When a newline is found, its length is -returned. In principle, we could implement several newline "types", each -referring to a different set of newline characters. At present, PCRE supports -only NLTYPE_FIXED, which gets handled without these functions, NLTYPE_ANYCRLF, -and NLTYPE_ANY. The full list of Unicode newline characters is taken from -http://unicode.org/unicode/reports/tr18/. */ - - -#include "config.h" - -#include "pcre_internal.h" - - - -/************************************************* -* Check for newline at given position * -*************************************************/ - -/* It is guaranteed that the initial value of ptr is less than the end of the -string that is being processed. - -Arguments: - ptr pointer to possible newline - type the newline type - endptr pointer to the end of the string - lenptr where to return the length - utf TRUE if in utf mode - -Returns: TRUE or FALSE -*/ - -BOOL -PRIV(is_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR endptr, int *lenptr, - BOOL utf) -{ -int c; -(void)utf; -#ifdef SUPPORT_UTF -if (utf) - { - GETCHAR(c, ptr); - } -else -#endif /* SUPPORT_UTF */ - c = *ptr; - -if (type == NLTYPE_ANYCRLF) switch(c) - { - case 0x000a: *lenptr = 1; return TRUE; /* LF */ - case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1; - return TRUE; /* CR */ - default: return FALSE; - } - -/* NLTYPE_ANY */ - -else switch(c) - { - case 0x000a: /* LF */ - case 0x000b: /* VT */ - case 0x000c: *lenptr = 1; return TRUE; /* FF */ - case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1; - return TRUE; /* CR */ -#ifdef COMPILE_PCRE8 - case 0x0085: *lenptr = utf? 2 : 1; return TRUE; /* NEL */ - case 0x2028: /* LS */ - case 0x2029: *lenptr = 3; return TRUE; /* PS */ -#else - case 0x0085: /* NEL */ - case 0x2028: /* LS */ - case 0x2029: *lenptr = 1; return TRUE; /* PS */ -#endif /* COMPILE_PCRE8 */ - default: return FALSE; - } -} - - - -/************************************************* -* Check for newline at previous position * -*************************************************/ - -/* It is guaranteed that the initial value of ptr is greater than the start of -the string that is being processed. - -Arguments: - ptr pointer to possible newline - type the newline type - startptr pointer to the start of the string - lenptr where to return the length - utf TRUE if in utf mode - -Returns: TRUE or FALSE -*/ - -BOOL -PRIV(was_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR startptr, int *lenptr, - BOOL utf) -{ -int c; -(void)utf; -ptr--; -#ifdef SUPPORT_UTF -if (utf) - { - BACKCHAR(ptr); - GETCHAR(c, ptr); - } -else -#endif /* SUPPORT_UTF */ - c = *ptr; - -if (type == NLTYPE_ANYCRLF) switch(c) - { - case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1; - return TRUE; /* LF */ - case 0x000d: *lenptr = 1; return TRUE; /* CR */ - default: return FALSE; - } - -else switch(c) - { - case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1; - return TRUE; /* LF */ - case 0x000b: /* VT */ - case 0x000c: /* FF */ - case 0x000d: *lenptr = 1; return TRUE; /* CR */ -#ifdef COMPILE_PCRE8 - case 0x0085: *lenptr = utf? 2 : 1; return TRUE; /* NEL */ - case 0x2028: /* LS */ - case 0x2029: *lenptr = 3; return TRUE; /* PS */ -#else - case 0x0085: /* NEL */ - case 0x2028: /* LS */ - case 0x2029: *lenptr = 1; return TRUE; /* PS */ -#endif /* COMPILE_PCRE8 */ - default: return FALSE; - } -} - -/* End of pcre_newline.c */ diff --git a/glib/pcre/pcre_ord2utf8.c b/glib/pcre/pcre_ord2utf8.c deleted file mode 100644 index 71fd587e0..000000000 --- a/glib/pcre/pcre_ord2utf8.c +++ /dev/null @@ -1,95 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This file contains a private PCRE function that converts an ordinal -character value into a UTF8 string. */ - -#include "config.h" - -#include "pcre_internal.h" - - -/************************************************* -* Convert character value to UTF-8 * -*************************************************/ - -/* This function takes an integer value in the range 0 - 0x10ffff -and encodes it as a UTF-8 character in 1 to 6 pcre_uchars. - -Arguments: - cvalue the character value - buffer pointer to buffer for result - at least 6 pcre_uchars long - -Returns: number of characters placed in the buffer -*/ - -int -PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer) -{ -#ifdef SUPPORT_UTF - -int i, j; - -/* Checking invalid cvalue character, encoded as invalid UTF-16 character. -Should never happen in practice. */ -if ((cvalue & 0xf800) == 0xd800 || cvalue >= 0x110000) - cvalue = 0xfffe; - -for (i = 0; i < PRIV(utf8_table1_size); i++) - if ((int)cvalue <= PRIV(utf8_table1)[i]) break; -buffer += i; -for (j = i; j > 0; j--) - { - *buffer-- = 0x80 | (cvalue & 0x3f); - cvalue >>= 6; - } -*buffer = PRIV(utf8_table2)[i] | cvalue; -return i + 1; - -#else - -(void)(cvalue); /* Keep compiler happy; this function won't ever be */ -(void)(buffer); /* called when SUPPORT_UTF is not defined. */ -return 0; - -#endif -} - -/* End of pcre_ord2utf8.c */ diff --git a/glib/pcre/pcre_string_utils.c b/glib/pcre/pcre_string_utils.c deleted file mode 100644 index 38cc2f958..000000000 --- a/glib/pcre/pcre_string_utils.c +++ /dev/null @@ -1,166 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains an internal function that is used to match an extended -class. It is used by both pcre_exec() and pcre_def_exec(). */ - - -#include "config.h" - -#include "pcre_internal.h" - -#ifndef COMPILE_PCRE8 - -/************************************************* -* Compare string utilities * -*************************************************/ - -/* The following two functions compares two strings. Basically an strcmp -for non 8 bit characters. - -Arguments: - str1 first string - str2 second string - -Returns: 0 if both string are equal (like strcmp), 1 otherwise -*/ - -int -PRIV(strcmp_uc_uc)(const pcre_uchar *str1, const pcre_uchar *str2) -{ -pcre_uchar c1; -pcre_uchar c2; - -while (*str1 != '\0' || *str2 != '\0') - { - c1 = *str1++; - c2 = *str2++; - if (c1 != c2) - return ((c1 > c2) << 1) - 1; - } -/* Both length and characters must be equal. */ -return 0; -} - -int -PRIV(strcmp_uc_c8)(const pcre_uchar *str1, const char *str2) -{ -const pcre_uint8 *ustr2 = (pcre_uint8 *)str2; -pcre_uchar c1; -pcre_uchar c2; - -while (*str1 != '\0' || *ustr2 != '\0') - { - c1 = *str1++; - c2 = (pcre_uchar)*ustr2++; - if (c1 != c2) - return ((c1 > c2) << 1) - 1; - } -/* Both length and characters must be equal. */ -return 0; -} - -/* The following two functions compares two, fixed length -strings. Basically an strncmp for non 8 bit characters. - -Arguments: - str1 first string - str2 second string - num size of the string - -Returns: 0 if both string are equal (like strcmp), 1 otherwise -*/ - -int -PRIV(strncmp_uc_uc)(const pcre_uchar *str1, const pcre_uchar *str2, unsigned int num) -{ -pcre_uchar c1; -pcre_uchar c2; - -while (num-- > 0) - { - c1 = *str1++; - c2 = *str2++; - if (c1 != c2) - return ((c1 > c2) << 1) - 1; - } -/* Both length and characters must be equal. */ -return 0; -} - -int -PRIV(strncmp_uc_c8)(const pcre_uchar *str1, const char *str2, unsigned int num) -{ -const pcre_uint8 *ustr2 = (pcre_uint8 *)str2; -pcre_uchar c1; -pcre_uchar c2; - -while (num-- > 0) - { - c1 = *str1++; - c2 = (pcre_uchar)*ustr2++; - if (c1 != c2) - return ((c1 > c2) << 1) - 1; - } -/* Both length and characters must be equal. */ -return 0; -} - -/* The following function returns with the length of -a zero terminated string. Basically an strlen for non 8 bit characters. - -Arguments: - str string - -Returns: length of the string -*/ - -unsigned int -PRIV(strlen_uc)(const pcre_uchar *str) -{ -unsigned int len = 0; -while (*str++ != 0) - len++; -return len; -} - -#endif /* COMPILE_PCRE8 */ - -/* End of pcre_string_utils.c */ diff --git a/glib/pcre/pcre_study.c b/glib/pcre/pcre_study.c deleted file mode 100644 index ee0930718..000000000 --- a/glib/pcre/pcre_study.c +++ /dev/null @@ -1,1532 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains the external function pcre_study(), along with local -supporting functions. */ - - -#include "config.h" - -#include "pcre_internal.h" - -#define SET_BIT(c) start_bits[c/8] |= (1 << (c&7)) - -/* Returns from set_start_bits() */ - -enum { SSB_FAIL, SSB_DONE, SSB_CONTINUE, SSB_UNKNOWN }; - - - -/************************************************* -* Find the minimum subject length for a group * -*************************************************/ - -/* Scan a parenthesized group and compute the minimum length of subject that -is needed to match it. This is a lower bound; it does not mean there is a -string of that length that matches. In UTF8 mode, the result is in characters -rather than bytes. - -Arguments: - code pointer to start of group (the bracket) - startcode pointer to start of the whole pattern - options the compiling options - int RECURSE depth - -Returns: the minimum length - -1 if \C in UTF-8 mode or (*ACCEPT) was encountered - -2 internal error (missing capturing bracket) - -3 internal error (opcode not listed) -*/ - -static int -find_minlength(const pcre_uchar *code, const pcre_uchar *startcode, int options, - int recurse_depth) -{ -int length = -1; -/* PCRE_UTF16 has the same value as PCRE_UTF8. */ -BOOL utf = (options & PCRE_UTF8) != 0; -BOOL had_recurse = FALSE; -int branchlength = 0; -pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE; - -if (*code == OP_CBRA || *code == OP_SCBRA || - *code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE; - -/* Scan along the opcodes for this branch. If we get to the end of the -branch, check the length against that of the other branches. */ - -for (;;) - { - int d, min; - pcre_uchar *cs, *ce; - int op = *cc; - - switch (op) - { - case OP_COND: - case OP_SCOND: - - /* If there is only one branch in a condition, the implied branch has zero - length, so we don't add anything. This covers the DEFINE "condition" - automatically. */ - - cs = cc + GET(cc, 1); - if (*cs != OP_ALT) - { - cc = cs + 1 + LINK_SIZE; - break; - } - - /* Otherwise we can fall through and treat it the same as any other - subpattern. */ - - case OP_CBRA: - case OP_SCBRA: - case OP_BRA: - case OP_SBRA: - case OP_CBRAPOS: - case OP_SCBRAPOS: - case OP_BRAPOS: - case OP_SBRAPOS: - case OP_ONCE: - case OP_ONCE_NC: - d = find_minlength(cc, startcode, options, recurse_depth); - if (d < 0) return d; - branchlength += d; - do cc += GET(cc, 1); while (*cc == OP_ALT); - cc += 1 + LINK_SIZE; - break; - - /* ACCEPT makes things far too complicated; we have to give up. */ - - case OP_ACCEPT: - case OP_ASSERT_ACCEPT: - return -1; - - /* Reached end of a branch; if it's a ket it is the end of a nested - call. If it's ALT it is an alternation in a nested call. If it is END it's - the end of the outer call. All can be handled by the same code. If an - ACCEPT was previously encountered, use the length that was in force at that - time, and pass back the shortest ACCEPT length. */ - - case OP_ALT: - case OP_KET: - case OP_KETRMAX: - case OP_KETRMIN: - case OP_KETRPOS: - case OP_END: - if (length < 0 || (!had_recurse && branchlength < length)) - length = branchlength; - if (op != OP_ALT) return length; - cc += 1 + LINK_SIZE; - branchlength = 0; - had_recurse = FALSE; - break; - - /* Skip over assertive subpatterns */ - - case OP_ASSERT: - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - do cc += GET(cc, 1); while (*cc == OP_ALT); - /* Fall through */ - - /* Skip over things that don't match chars */ - - case OP_REVERSE: - case OP_CREF: - case OP_NCREF: - case OP_RREF: - case OP_NRREF: - case OP_DEF: - case OP_CALLOUT: - case OP_SOD: - case OP_SOM: - case OP_EOD: - case OP_EODN: - case OP_CIRC: - case OP_CIRCM: - case OP_DOLL: - case OP_DOLLM: - case OP_NOT_WORD_BOUNDARY: - case OP_WORD_BOUNDARY: - cc += PRIV(OP_lengths)[*cc]; - break; - - /* Skip over a subpattern that has a {0} or {0,x} quantifier */ - - case OP_BRAZERO: - case OP_BRAMINZERO: - case OP_BRAPOSZERO: - case OP_SKIPZERO: - cc += PRIV(OP_lengths)[*cc]; - do cc += GET(cc, 1); while (*cc == OP_ALT); - cc += 1 + LINK_SIZE; - break; - - /* Handle literal characters and + repetitions */ - - case OP_CHAR: - case OP_CHARI: - case OP_NOT: - case OP_NOTI: - case OP_PLUS: - case OP_PLUSI: - case OP_MINPLUS: - case OP_MINPLUSI: - case OP_POSPLUS: - case OP_POSPLUSI: - case OP_NOTPLUS: - case OP_NOTPLUSI: - case OP_NOTMINPLUS: - case OP_NOTMINPLUSI: - case OP_NOTPOSPLUS: - case OP_NOTPOSPLUSI: - branchlength++; - cc += 2; -#ifdef SUPPORT_UTF - if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); -#endif - break; - - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEPOSPLUS: - branchlength++; - cc += (cc[1] == OP_PROP || cc[1] == OP_NOTPROP)? 4 : 2; - break; - - /* Handle exact repetitions. The count is already in characters, but we - need to skip over a multibyte character in UTF8 mode. */ - - case OP_EXACT: - case OP_EXACTI: - case OP_NOTEXACT: - case OP_NOTEXACTI: - branchlength += GET2(cc,1); - cc += 2 + IMM2_SIZE; -#ifdef SUPPORT_UTF - if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); -#endif - break; - - case OP_TYPEEXACT: - branchlength += GET2(cc,1); - cc += 2 + IMM2_SIZE + ((cc[1 + IMM2_SIZE] == OP_PROP - || cc[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0); - break; - - /* Handle single-char non-literal matchers */ - - case OP_PROP: - case OP_NOTPROP: - cc += 2; - /* Fall through */ - - case OP_NOT_DIGIT: - case OP_DIGIT: - case OP_NOT_WHITESPACE: - case OP_WHITESPACE: - case OP_NOT_WORDCHAR: - case OP_WORDCHAR: - case OP_ANY: - case OP_ALLANY: - case OP_EXTUNI: - case OP_HSPACE: - case OP_NOT_HSPACE: - case OP_VSPACE: - case OP_NOT_VSPACE: - branchlength++; - cc++; - break; - - /* "Any newline" might match two characters, but it also might match just - one. */ - - case OP_ANYNL: - branchlength += 1; - cc++; - break; - - /* The single-byte matcher means we can't proceed in UTF-8 mode. (In - non-UTF-8 mode \C will actually be turned into OP_ALLANY, so won't ever - appear, but leave the code, just in case.) */ - - case OP_ANYBYTE: -#ifdef SUPPORT_UTF - if (utf) return -1; -#endif - branchlength++; - cc++; - break; - - /* For repeated character types, we have to test for \p and \P, which have - an extra two bytes of parameters. */ - - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEQUERY: - case OP_TYPEMINQUERY: - case OP_TYPEPOSSTAR: - case OP_TYPEPOSQUERY: - if (cc[1] == OP_PROP || cc[1] == OP_NOTPROP) cc += 2; - cc += PRIV(OP_lengths)[op]; - break; - - case OP_TYPEUPTO: - case OP_TYPEMINUPTO: - case OP_TYPEPOSUPTO: - if (cc[1 + IMM2_SIZE] == OP_PROP - || cc[1 + IMM2_SIZE] == OP_NOTPROP) cc += 2; - cc += PRIV(OP_lengths)[op]; - break; - - /* Check a class for variable quantification */ - -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - case OP_XCLASS: - cc += GET(cc, 1) - PRIV(OP_lengths)[OP_CLASS]; - /* Fall through */ -#endif - - case OP_CLASS: - case OP_NCLASS: - cc += PRIV(OP_lengths)[OP_CLASS]; - - switch (*cc) - { - case OP_CRPLUS: - case OP_CRMINPLUS: - branchlength++; - /* Fall through */ - - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRQUERY: - case OP_CRMINQUERY: - cc++; - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - branchlength += GET2(cc,1); - cc += 1 + 2 * IMM2_SIZE; - break; - - default: - branchlength++; - break; - } - break; - - /* Backreferences and subroutine calls are treated in the same way: we find - the minimum length for the subpattern. A recursion, however, causes an - a flag to be set that causes the length of this branch to be ignored. The - logic is that a recursion can only make sense if there is another - alternation that stops the recursing. That will provide the minimum length - (when no recursion happens). A backreference within the group that it is - referencing behaves in the same way. - - If PCRE_JAVASCRIPT_COMPAT is set, a backreference to an unset bracket - matches an empty string (by default it causes a matching failure), so in - that case we must set the minimum length to zero. */ - - case OP_REF: - case OP_REFI: - if ((options & PCRE_JAVASCRIPT_COMPAT) == 0) - { - ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(cc, 1)); - if (cs == NULL) return -2; - do ce += GET(ce, 1); while (*ce == OP_ALT); - if (cc > cs && cc < ce) - { - d = 0; - had_recurse = TRUE; - } - else - { - d = find_minlength(cs, startcode, options, recurse_depth); - } - } - else d = 0; - cc += 1 + IMM2_SIZE; - - /* Handle repeated back references */ - - switch (*cc) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRQUERY: - case OP_CRMINQUERY: - min = 0; - cc++; - break; - - case OP_CRPLUS: - case OP_CRMINPLUS: - min = 1; - cc++; - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - min = GET2(cc, 1); - cc += 1 + 2 * IMM2_SIZE; - break; - - default: - min = 1; - break; - } - - branchlength += min * d; - break; - - /* We can easily detect direct recursion, but not mutual recursion. This is - caught by a recursion depth count. */ - - case OP_RECURSE: - cs = ce = (pcre_uchar *)startcode + GET(cc, 1); - do ce += GET(ce, 1); while (*ce == OP_ALT); - if ((cc > cs && cc < ce) || recurse_depth > 10) - had_recurse = TRUE; - else - { - branchlength += find_minlength(cs, startcode, options, recurse_depth + 1); - } - cc += 1 + LINK_SIZE; - break; - - /* Anything else does not or need not match a character. We can get the - item's length from the table, but for those that can match zero occurrences - of a character, we must take special action for UTF-8 characters. As it - happens, the "NOT" versions of these opcodes are used at present only for - ASCII characters, so they could be omitted from this list. However, in - future that may change, so we include them here so as not to leave a - gotcha for a future maintainer. */ - - case OP_UPTO: - case OP_UPTOI: - case OP_NOTUPTO: - case OP_NOTUPTOI: - case OP_MINUPTO: - case OP_MINUPTOI: - case OP_NOTMINUPTO: - case OP_NOTMINUPTOI: - case OP_POSUPTO: - case OP_POSUPTOI: - case OP_NOTPOSUPTO: - case OP_NOTPOSUPTOI: - - case OP_STAR: - case OP_STARI: - case OP_NOTSTAR: - case OP_NOTSTARI: - case OP_MINSTAR: - case OP_MINSTARI: - case OP_NOTMINSTAR: - case OP_NOTMINSTARI: - case OP_POSSTAR: - case OP_POSSTARI: - case OP_NOTPOSSTAR: - case OP_NOTPOSSTARI: - - case OP_QUERY: - case OP_QUERYI: - case OP_NOTQUERY: - case OP_NOTQUERYI: - case OP_MINQUERY: - case OP_MINQUERYI: - case OP_NOTMINQUERY: - case OP_NOTMINQUERYI: - case OP_POSQUERY: - case OP_POSQUERYI: - case OP_NOTPOSQUERY: - case OP_NOTPOSQUERYI: - - cc += PRIV(OP_lengths)[op]; -#ifdef SUPPORT_UTF - if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); -#endif - break; - - /* Skip these, but we need to add in the name length. */ - - case OP_MARK: - case OP_PRUNE_ARG: - case OP_SKIP_ARG: - case OP_THEN_ARG: - cc += PRIV(OP_lengths)[op] + cc[1]; - break; - - /* The remaining opcodes are just skipped over. */ - - case OP_CLOSE: - case OP_COMMIT: - case OP_FAIL: - case OP_PRUNE: - case OP_SET_SOM: - case OP_SKIP: - case OP_THEN: - cc += PRIV(OP_lengths)[op]; - break; - - /* This should not occur: we list all opcodes explicitly so that when - new ones get added they are properly considered. */ - - default: - return -3; - } - } -/* Control never gets here */ -} - - - -/************************************************* -* Set a bit and maybe its alternate case * -*************************************************/ - -/* Given a character, set its first byte's bit in the table, and also the -corresponding bit for the other version of a letter if we are caseless. In -UTF-8 mode, for characters greater than 127, we can only do the caseless thing -when Unicode property support is available. - -Arguments: - start_bits points to the bit map - p points to the character - caseless the caseless flag - cd the block with char table pointers - utf TRUE for UTF-8 / UTF-16 mode - -Returns: pointer after the character -*/ - -static const pcre_uchar * -set_table_bit(pcre_uint8 *start_bits, const pcre_uchar *p, BOOL caseless, - compile_data *cd, BOOL utf) -{ -unsigned int c = *p; - -#ifdef COMPILE_PCRE8 -SET_BIT(c); - -#ifdef SUPPORT_UTF -if (utf && c > 127) - { - GETCHARINC(c, p); -#ifdef SUPPORT_UCP - if (caseless) - { - pcre_uchar buff[6]; - c = UCD_OTHERCASE(c); - (void)PRIV(ord2utf)(c, buff); - SET_BIT(buff[0]); - } -#endif - return p; - } -#endif - -/* Not UTF-8 mode, or character is less than 127. */ - -if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]); -return p + 1; -#endif - -#ifdef COMPILE_PCRE16 -if (c > 0xff) - { - c = 0xff; - caseless = FALSE; - } -SET_BIT(c); - -#ifdef SUPPORT_UTF -if (utf && c > 127) - { - GETCHARINC(c, p); -#ifdef SUPPORT_UCP - if (caseless) - { - c = UCD_OTHERCASE(c); - if (c > 0xff) - c = 0xff; - SET_BIT(c); - } -#endif - return p; - } -#endif - -if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]); -return p + 1; -#endif -} - - - -/************************************************* -* Set bits for a positive character type * -*************************************************/ - -/* This function sets starting bits for a character type. In UTF-8 mode, we can -only do a direct setting for bytes less than 128, as otherwise there can be -confusion with bytes in the middle of UTF-8 characters. In a "traditional" -environment, the tables will only recognize ASCII characters anyway, but in at -least one Windows environment, some higher bytes bits were set in the tables. -So we deal with that case by considering the UTF-8 encoding. - -Arguments: - start_bits the starting bitmap - cbit type the type of character wanted - table_limit 32 for non-UTF-8; 16 for UTF-8 - cd the block with char table pointers - -Returns: nothing -*/ - -static void -set_type_bits(pcre_uint8 *start_bits, int cbit_type, int table_limit, - compile_data *cd) -{ -int c; -for (c = 0; c < table_limit; c++) start_bits[c] |= cd->cbits[c+cbit_type]; -#if defined SUPPORT_UTF && defined COMPILE_PCRE8 -if (table_limit == 32) return; -for (c = 128; c < 256; c++) - { - if ((cd->cbits[c/8] & (1 << (c&7))) != 0) - { - pcre_uchar buff[6]; - (void)PRIV(ord2utf)(c, buff); - SET_BIT(buff[0]); - } - } -#endif -} - - -/************************************************* -* Set bits for a negative character type * -*************************************************/ - -/* This function sets starting bits for a negative character type such as \D. -In UTF-8 mode, we can only do a direct setting for bytes less than 128, as -otherwise there can be confusion with bytes in the middle of UTF-8 characters. -Unlike in the positive case, where we can set appropriate starting bits for -specific high-valued UTF-8 characters, in this case we have to set the bits for -all high-valued characters. The lowest is 0xc2, but we overkill by starting at -0xc0 (192) for simplicity. - -Arguments: - start_bits the starting bitmap - cbit type the type of character wanted - table_limit 32 for non-UTF-8; 16 for UTF-8 - cd the block with char table pointers - -Returns: nothing -*/ - -static void -set_nottype_bits(pcre_uint8 *start_bits, int cbit_type, int table_limit, - compile_data *cd) -{ -int c; -for (c = 0; c < table_limit; c++) start_bits[c] |= ~cd->cbits[c+cbit_type]; -#if defined SUPPORT_UTF && defined COMPILE_PCRE8 -if (table_limit != 32) for (c = 24; c < 32; c++) start_bits[c] = 0xff; -#endif -} - - - -/************************************************* -* Create bitmap of starting bytes * -*************************************************/ - -/* This function scans a compiled unanchored expression recursively and -attempts to build a bitmap of the set of possible starting bytes. As time goes -by, we may be able to get more clever at doing this. The SSB_CONTINUE return is -useful for parenthesized groups in patterns such as (a*)b where the group -provides some optional starting bytes but scanning must continue at the outer -level to find at least one mandatory byte. At the outermost level, this -function fails unless the result is SSB_DONE. - -Arguments: - code points to an expression - start_bits points to a 32-byte table, initialized to 0 - utf TRUE if in UTF-8 / UTF-16 mode - cd the block with char table pointers - -Returns: SSB_FAIL => Failed to find any starting bytes - SSB_DONE => Found mandatory starting bytes - SSB_CONTINUE => Found optional starting bytes - SSB_UNKNOWN => Hit an unrecognized opcode -*/ - -static int -set_start_bits(const pcre_uchar *code, pcre_uint8 *start_bits, BOOL utf, - compile_data *cd) -{ -int c; -int yield = SSB_DONE; -#if defined SUPPORT_UTF && defined COMPILE_PCRE8 -int table_limit = utf? 16:32; -#else -int table_limit = 32; -#endif - -#if 0 -/* ========================================================================= */ -/* The following comment and code was inserted in January 1999. In May 2006, -when it was observed to cause compiler warnings about unused values, I took it -out again. If anybody is still using OS/2, they will have to put it back -manually. */ - -/* This next statement and the later reference to dummy are here in order to -trick the optimizer of the IBM C compiler for OS/2 into generating correct -code. Apparently IBM isn't going to fix the problem, and we would rather not -disable optimization (in this module it actually makes a big difference, and -the pcre module can use all the optimization it can get). */ - -volatile int dummy; -/* ========================================================================= */ -#endif - -do - { - BOOL try_next = TRUE; - const pcre_uchar *tcode = code + 1 + LINK_SIZE; - - if (*code == OP_CBRA || *code == OP_SCBRA || - *code == OP_CBRAPOS || *code == OP_SCBRAPOS) tcode += IMM2_SIZE; - - while (try_next) /* Loop for items in this branch */ - { - int rc; - - switch(*tcode) - { - /* If we reach something we don't understand, it means a new opcode has - been created that hasn't been added to this code. Hopefully this problem - will be discovered during testing. */ - - default: - return SSB_UNKNOWN; - - /* Fail for a valid opcode that implies no starting bits. */ - - case OP_ACCEPT: - case OP_ASSERT_ACCEPT: - case OP_ALLANY: - case OP_ANY: - case OP_ANYBYTE: - case OP_CIRC: - case OP_CIRCM: - case OP_CLOSE: - case OP_COMMIT: - case OP_COND: - case OP_CREF: - case OP_DEF: - case OP_DOLL: - case OP_DOLLM: - case OP_END: - case OP_EOD: - case OP_EODN: - case OP_EXTUNI: - case OP_FAIL: - case OP_MARK: - case OP_NCREF: - case OP_NOT: - case OP_NOTEXACT: - case OP_NOTEXACTI: - case OP_NOTI: - case OP_NOTMINPLUS: - case OP_NOTMINPLUSI: - case OP_NOTMINQUERY: - case OP_NOTMINQUERYI: - case OP_NOTMINSTAR: - case OP_NOTMINSTARI: - case OP_NOTMINUPTO: - case OP_NOTMINUPTOI: - case OP_NOTPLUS: - case OP_NOTPLUSI: - case OP_NOTPOSPLUS: - case OP_NOTPOSPLUSI: - case OP_NOTPOSQUERY: - case OP_NOTPOSQUERYI: - case OP_NOTPOSSTAR: - case OP_NOTPOSSTARI: - case OP_NOTPOSUPTO: - case OP_NOTPOSUPTOI: - case OP_NOTPROP: - case OP_NOTQUERY: - case OP_NOTQUERYI: - case OP_NOTSTAR: - case OP_NOTSTARI: - case OP_NOTUPTO: - case OP_NOTUPTOI: - case OP_NOT_HSPACE: - case OP_NOT_VSPACE: - case OP_NRREF: - case OP_PROP: - case OP_PRUNE: - case OP_PRUNE_ARG: - case OP_RECURSE: - case OP_REF: - case OP_REFI: - case OP_REVERSE: - case OP_RREF: - case OP_SCOND: - case OP_SET_SOM: - case OP_SKIP: - case OP_SKIP_ARG: - case OP_SOD: - case OP_SOM: - case OP_THEN: - case OP_THEN_ARG: -#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 - case OP_XCLASS: -#endif - return SSB_FAIL; - - /* We can ignore word boundary tests. */ - - case OP_WORD_BOUNDARY: - case OP_NOT_WORD_BOUNDARY: - tcode++; - break; - - /* If we hit a bracket or a positive lookahead assertion, recurse to set - bits from within the subpattern. If it can't find anything, we have to - give up. If it finds some mandatory character(s), we are done for this - branch. Otherwise, carry on scanning after the subpattern. */ - - case OP_BRA: - case OP_SBRA: - case OP_CBRA: - case OP_SCBRA: - case OP_BRAPOS: - case OP_SBRAPOS: - case OP_CBRAPOS: - case OP_SCBRAPOS: - case OP_ONCE: - case OP_ONCE_NC: - case OP_ASSERT: - rc = set_start_bits(tcode, start_bits, utf, cd); - if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc; - if (rc == SSB_DONE) try_next = FALSE; else - { - do tcode += GET(tcode, 1); while (*tcode == OP_ALT); - tcode += 1 + LINK_SIZE; - } - break; - - /* If we hit ALT or KET, it means we haven't found anything mandatory in - this branch, though we might have found something optional. For ALT, we - continue with the next alternative, but we have to arrange that the final - result from subpattern is SSB_CONTINUE rather than SSB_DONE. For KET, - return SSB_CONTINUE: if this is the top level, that indicates failure, - but after a nested subpattern, it causes scanning to continue. */ - - case OP_ALT: - yield = SSB_CONTINUE; - try_next = FALSE; - break; - - case OP_KET: - case OP_KETRMAX: - case OP_KETRMIN: - case OP_KETRPOS: - return SSB_CONTINUE; - - /* Skip over callout */ - - case OP_CALLOUT: - tcode += 2 + 2*LINK_SIZE; - break; - - /* Skip over lookbehind and negative lookahead assertions */ - - case OP_ASSERT_NOT: - case OP_ASSERTBACK: - case OP_ASSERTBACK_NOT: - do tcode += GET(tcode, 1); while (*tcode == OP_ALT); - tcode += 1 + LINK_SIZE; - break; - - /* BRAZERO does the bracket, but carries on. */ - - case OP_BRAZERO: - case OP_BRAMINZERO: - case OP_BRAPOSZERO: - rc = set_start_bits(++tcode, start_bits, utf, cd); - if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc; -/* ========================================================================= - See the comment at the head of this function concerning the next line, - which was an old fudge for the benefit of OS/2. - dummy = 1; - ========================================================================= */ - do tcode += GET(tcode,1); while (*tcode == OP_ALT); - tcode += 1 + LINK_SIZE; - break; - - /* SKIPZERO skips the bracket. */ - - case OP_SKIPZERO: - tcode++; - do tcode += GET(tcode,1); while (*tcode == OP_ALT); - tcode += 1 + LINK_SIZE; - break; - - /* Single-char * or ? sets the bit and tries the next item */ - - case OP_STAR: - case OP_MINSTAR: - case OP_POSSTAR: - case OP_QUERY: - case OP_MINQUERY: - case OP_POSQUERY: - tcode = set_table_bit(start_bits, tcode + 1, FALSE, cd, utf); - break; - - case OP_STARI: - case OP_MINSTARI: - case OP_POSSTARI: - case OP_QUERYI: - case OP_MINQUERYI: - case OP_POSQUERYI: - tcode = set_table_bit(start_bits, tcode + 1, TRUE, cd, utf); - break; - - /* Single-char upto sets the bit and tries the next */ - - case OP_UPTO: - case OP_MINUPTO: - case OP_POSUPTO: - tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, FALSE, cd, utf); - break; - - case OP_UPTOI: - case OP_MINUPTOI: - case OP_POSUPTOI: - tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, TRUE, cd, utf); - break; - - /* At least one single char sets the bit and stops */ - - case OP_EXACT: - tcode += IMM2_SIZE; - /* Fall through */ - case OP_CHAR: - case OP_PLUS: - case OP_MINPLUS: - case OP_POSPLUS: - (void)set_table_bit(start_bits, tcode + 1, FALSE, cd, utf); - try_next = FALSE; - break; - - case OP_EXACTI: - tcode += IMM2_SIZE; - /* Fall through */ - case OP_CHARI: - case OP_PLUSI: - case OP_MINPLUSI: - case OP_POSPLUSI: - (void)set_table_bit(start_bits, tcode + 1, TRUE, cd, utf); - try_next = FALSE; - break; - - /* Special spacing and line-terminating items. These recognize specific - lists of characters. The difference between VSPACE and ANYNL is that the - latter can match the two-character CRLF sequence, but that is not - relevant for finding the first character, so their code here is - identical. */ - - case OP_HSPACE: - SET_BIT(0x09); - SET_BIT(0x20); -#ifdef SUPPORT_UTF - if (utf) - { -#ifdef COMPILE_PCRE8 - SET_BIT(0xC2); /* For U+00A0 */ - SET_BIT(0xE1); /* For U+1680, U+180E */ - SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */ - SET_BIT(0xE3); /* For U+3000 */ -#endif -#ifdef COMPILE_PCRE16 - SET_BIT(0xA0); - SET_BIT(0xFF); /* For characters > 255 */ -#endif - } - else -#endif /* SUPPORT_UTF */ - { - SET_BIT(0xA0); -#ifdef COMPILE_PCRE16 - SET_BIT(0xFF); /* For characters > 255 */ -#endif - } - try_next = FALSE; - break; - - case OP_ANYNL: - case OP_VSPACE: - SET_BIT(0x0A); - SET_BIT(0x0B); - SET_BIT(0x0C); - SET_BIT(0x0D); -#ifdef SUPPORT_UTF - if (utf) - { -#ifdef COMPILE_PCRE8 - SET_BIT(0xC2); /* For U+0085 */ - SET_BIT(0xE2); /* For U+2028, U+2029 */ -#endif -#ifdef COMPILE_PCRE16 - SET_BIT(0x85); - SET_BIT(0xFF); /* For characters > 255 */ -#endif - } - else -#endif /* SUPPORT_UTF */ - { - SET_BIT(0x85); -#ifdef COMPILE_PCRE16 - SET_BIT(0xFF); /* For characters > 255 */ -#endif - } - try_next = FALSE; - break; - - /* Single character types set the bits and stop. Note that if PCRE_UCP - is set, we do not see these op codes because \d etc are converted to - properties. Therefore, these apply in the case when only characters less - than 256 are recognized to match the types. */ - - case OP_NOT_DIGIT: - set_nottype_bits(start_bits, cbit_digit, table_limit, cd); - try_next = FALSE; - break; - - case OP_DIGIT: - set_type_bits(start_bits, cbit_digit, table_limit, cd); - try_next = FALSE; - break; - - /* The cbit_space table has vertical tab as whitespace; we have to - ensure it is set as not whitespace. */ - - case OP_NOT_WHITESPACE: - set_nottype_bits(start_bits, cbit_space, table_limit, cd); - start_bits[1] |= 0x08; - try_next = FALSE; - break; - - /* The cbit_space table has vertical tab as whitespace; we have to - not set it from the table. */ - - case OP_WHITESPACE: - c = start_bits[1]; /* Save in case it was already set */ - set_type_bits(start_bits, cbit_space, table_limit, cd); - start_bits[1] = (start_bits[1] & ~0x08) | c; - try_next = FALSE; - break; - - case OP_NOT_WORDCHAR: - set_nottype_bits(start_bits, cbit_word, table_limit, cd); - try_next = FALSE; - break; - - case OP_WORDCHAR: - set_type_bits(start_bits, cbit_word, table_limit, cd); - try_next = FALSE; - break; - - /* One or more character type fudges the pointer and restarts, knowing - it will hit a single character type and stop there. */ - - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEPOSPLUS: - tcode++; - break; - - case OP_TYPEEXACT: - tcode += 1 + IMM2_SIZE; - break; - - /* Zero or more repeats of character types set the bits and then - try again. */ - - case OP_TYPEUPTO: - case OP_TYPEMINUPTO: - case OP_TYPEPOSUPTO: - tcode += IMM2_SIZE; /* Fall through */ - - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEPOSSTAR: - case OP_TYPEQUERY: - case OP_TYPEMINQUERY: - case OP_TYPEPOSQUERY: - switch(tcode[1]) - { - default: - case OP_ANY: - case OP_ALLANY: - return SSB_FAIL; - - case OP_HSPACE: - SET_BIT(0x09); - SET_BIT(0x20); -#ifdef SUPPORT_UTF - if (utf) - { -#ifdef COMPILE_PCRE8 - SET_BIT(0xC2); /* For U+00A0 */ - SET_BIT(0xE1); /* For U+1680, U+180E */ - SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */ - SET_BIT(0xE3); /* For U+3000 */ -#endif -#ifdef COMPILE_PCRE16 - SET_BIT(0xA0); - SET_BIT(0xFF); /* For characters > 255 */ -#endif - } - else -#endif /* SUPPORT_UTF */ - SET_BIT(0xA0); - break; - - case OP_ANYNL: - case OP_VSPACE: - SET_BIT(0x0A); - SET_BIT(0x0B); - SET_BIT(0x0C); - SET_BIT(0x0D); -#ifdef SUPPORT_UTF - if (utf) - { -#ifdef COMPILE_PCRE8 - SET_BIT(0xC2); /* For U+0085 */ - SET_BIT(0xE2); /* For U+2028, U+2029 */ -#endif -#ifdef COMPILE_PCRE16 - SET_BIT(0x85); - SET_BIT(0xFF); /* For characters > 255 */ -#endif - } - else -#endif /* SUPPORT_UTF */ - SET_BIT(0x85); - break; - - case OP_NOT_DIGIT: - set_nottype_bits(start_bits, cbit_digit, table_limit, cd); - break; - - case OP_DIGIT: - set_type_bits(start_bits, cbit_digit, table_limit, cd); - break; - - /* The cbit_space table has vertical tab as whitespace; we have to - ensure it gets set as not whitespace. */ - - case OP_NOT_WHITESPACE: - set_nottype_bits(start_bits, cbit_space, table_limit, cd); - start_bits[1] |= 0x08; - break; - - /* The cbit_space table has vertical tab as whitespace; we have to - avoid setting it. */ - - case OP_WHITESPACE: - c = start_bits[1]; /* Save in case it was already set */ - set_type_bits(start_bits, cbit_space, table_limit, cd); - start_bits[1] = (start_bits[1] & ~0x08) | c; - break; - - case OP_NOT_WORDCHAR: - set_nottype_bits(start_bits, cbit_word, table_limit, cd); - break; - - case OP_WORDCHAR: - set_type_bits(start_bits, cbit_word, table_limit, cd); - break; - } - - tcode += 2; - break; - - /* Character class where all the information is in a bit map: set the - bits and either carry on or not, according to the repeat count. If it was - a negative class, and we are operating with UTF-8 characters, any byte - with a value >= 0xc4 is a potentially valid starter because it starts a - character with a value > 255. */ - - case OP_NCLASS: -#if defined SUPPORT_UTF && defined COMPILE_PCRE8 - if (utf) - { - start_bits[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */ - memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */ - } -#endif -#ifdef COMPILE_PCRE16 - SET_BIT(0xFF); /* For characters > 255 */ -#endif - /* Fall through */ - - case OP_CLASS: - { - pcre_uint8 *map; - tcode++; - map = (pcre_uint8 *)tcode; - - /* In UTF-8 mode, the bits in a bit map correspond to character - values, not to byte values. However, the bit map we are constructing is - for byte values. So we have to do a conversion for characters whose - value is > 127. In fact, there are only two possible starting bytes for - characters in the range 128 - 255. */ - -#if defined SUPPORT_UTF && defined COMPILE_PCRE8 - if (utf) - { - for (c = 0; c < 16; c++) start_bits[c] |= map[c]; - for (c = 128; c < 256; c++) - { - if ((map[c/8] && (1 << (c&7))) != 0) - { - int d = (c >> 6) | 0xc0; /* Set bit for this starter */ - start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */ - c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */ - } - } - } - else -#endif - { - /* In non-UTF-8 mode, the two bit maps are completely compatible. */ - for (c = 0; c < 32; c++) start_bits[c] |= map[c]; - } - - /* Advance past the bit map, and act on what follows. For a zero - minimum repeat, continue; otherwise stop processing. */ - - tcode += 32 / sizeof(pcre_uchar); - switch (*tcode) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRQUERY: - case OP_CRMINQUERY: - tcode++; - break; - - case OP_CRRANGE: - case OP_CRMINRANGE: - if (GET2(tcode, 1) == 0) tcode += 1 + 2 * IMM2_SIZE; - else try_next = FALSE; - break; - - default: - try_next = FALSE; - break; - } - } - break; /* End of bitmap class handling */ - - } /* End of switch */ - } /* End of try_next loop */ - - code += GET(code, 1); /* Advance to next branch */ - } -while (*code == OP_ALT); -return yield; -} - - - - - -/************************************************* -* Study a compiled expression * -*************************************************/ - -/* This function is handed a compiled expression that it must study to produce -information that will speed up the matching. It returns a pcre[16]_extra block -which then gets handed back to pcre_exec(). - -Arguments: - re points to the compiled expression - options contains option bits - errorptr points to where to place error messages; - set NULL unless error - -Returns: pointer to a pcre[16]_extra block, with study_data filled in and - the appropriate flags set; - NULL on error or if no optimization possible -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN pcre_extra * PCRE_CALL_CONVENTION -pcre_study(const pcre *external_re, int options, const char **errorptr) -#else -PCRE_EXP_DEFN pcre16_extra * PCRE_CALL_CONVENTION -pcre16_study(const pcre16 *external_re, int options, const char **errorptr) -#endif -{ -int min; -BOOL bits_set = FALSE; -pcre_uint8 start_bits[32]; -PUBL(extra) *extra = NULL; -pcre_study_data *study; -const pcre_uint8 *tables; -pcre_uchar *code; -compile_data compile_block; -const REAL_PCRE *re = (const REAL_PCRE *)external_re; - -*errorptr = NULL; - -if (re == NULL || re->magic_number != MAGIC_NUMBER) - { - *errorptr = "argument is not a compiled regular expression"; - return NULL; - } - -if ((re->flags & PCRE_MODE) == 0) - { -#ifdef COMPILE_PCRE8 - *errorptr = "argument is compiled in 16 bit mode"; -#else - *errorptr = "argument is compiled in 8 bit mode"; -#endif - return NULL; - } - -if ((options & ~PUBLIC_STUDY_OPTIONS) != 0) - { - *errorptr = "unknown or incorrect option bit(s) set"; - return NULL; - } - -code = (pcre_uchar *)re + re->name_table_offset + - (re->name_count * re->name_entry_size); - -/* For an anchored pattern, or an unanchored pattern that has a first char, or -a multiline pattern that matches only at "line starts", there is no point in -seeking a list of starting bytes. */ - -if ((re->options & PCRE_ANCHORED) == 0 && - (re->flags & (PCRE_FIRSTSET|PCRE_STARTLINE)) == 0) - { - int rc; - - /* Set the character tables in the block that is passed around */ - - tables = re->tables; - -#ifdef COMPILE_PCRE8 - if (tables == NULL) - (void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES, - (void *)(&tables)); -#else - if (tables == NULL) - (void)pcre16_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES, - (void *)(&tables)); -#endif - - compile_block.lcc = tables + lcc_offset; - compile_block.fcc = tables + fcc_offset; - compile_block.cbits = tables + cbits_offset; - compile_block.ctypes = tables + ctypes_offset; - - /* See if we can find a fixed set of initial characters for the pattern. */ - - memset(start_bits, 0, 32 * sizeof(pcre_uint8)); - rc = set_start_bits(code, start_bits, (re->options & PCRE_UTF8) != 0, - &compile_block); - bits_set = rc == SSB_DONE; - if (rc == SSB_UNKNOWN) - { - *errorptr = "internal error: opcode not recognized"; - return NULL; - } - } - -/* Find the minimum length of subject string. */ - -switch(min = find_minlength(code, code, re->options, 0)) - { - case -2: *errorptr = "internal error: missing capturing bracket"; return NULL; - case -3: *errorptr = "internal error: opcode not recognized"; return NULL; - default: break; - } - -/* If a set of starting bytes has been identified, or if the minimum length is -greater than zero, or if JIT optimization has been requested, get a -pcre[16]_extra block and a pcre_study_data block. The study data is put in the -latter, which is pointed to by the former, which may also get additional data -set later by the calling program. At the moment, the size of pcre_study_data -is fixed. We nevertheless save it in a field for returning via the -pcre_fullinfo() function so that if it becomes variable in the future, -we don't have to change that code. */ - -if (bits_set || min > 0 -#ifdef SUPPORT_JIT - || (options & (PCRE_STUDY_JIT_COMPILE | PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE - | PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE)) != 0 -#endif - ) - { - extra = (PUBL(extra) *)(PUBL(malloc)) - (sizeof(PUBL(extra)) + sizeof(pcre_study_data)); - if (extra == NULL) - { - *errorptr = "failed to get memory"; - return NULL; - } - - study = (pcre_study_data *)((char *)extra + sizeof(PUBL(extra))); - extra->flags = PCRE_EXTRA_STUDY_DATA; - extra->study_data = study; - - study->size = sizeof(pcre_study_data); - study->flags = 0; - - /* Set the start bits always, to avoid unset memory errors if the - study data is written to a file, but set the flag only if any of the bits - are set, to save time looking when none are. */ - - if (bits_set) - { - study->flags |= PCRE_STUDY_MAPPED; - memcpy(study->start_bits, start_bits, sizeof(start_bits)); - } - else memset(study->start_bits, 0, 32 * sizeof(pcre_uint8)); - -#ifdef PCRE_DEBUG - if (bits_set) - { - pcre_uint8 *ptr = start_bits; - int i; - - printf("Start bits:\n"); - for (i = 0; i < 32; i++) - printf("%3d: %02x%s", i * 8, *ptr++, ((i + 1) & 0x7) != 0? " " : "\n"); - } -#endif - - /* Always set the minlength value in the block, because the JIT compiler - makes use of it. However, don't set the bit unless the length is greater than - zero - the interpretive pcre_exec() and pcre_dfa_exec() needn't waste time - checking the zero case. */ - - if (min > 0) - { - study->flags |= PCRE_STUDY_MINLEN; - study->minlength = min; - } - else study->minlength = 0; - - /* If JIT support was compiled and requested, attempt the JIT compilation. - If no starting bytes were found, and the minimum length is zero, and JIT - compilation fails, abandon the extra block and return NULL. */ - -#ifdef SUPPORT_JIT - extra->executable_jit = NULL; - if ((options & PCRE_STUDY_JIT_COMPILE) != 0) - PRIV(jit_compile)(re, extra, JIT_COMPILE); - if ((options & PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE) != 0) - PRIV(jit_compile)(re, extra, JIT_PARTIAL_SOFT_COMPILE); - if ((options & PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE) != 0) - PRIV(jit_compile)(re, extra, JIT_PARTIAL_HARD_COMPILE); - - if (study->flags == 0 && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) == 0) - { -#ifdef COMPILE_PCRE8 - pcre_free_study(extra); -#endif -#ifdef COMPILE_PCRE16 - pcre16_free_study(extra); -#endif - extra = NULL; - } -#endif - } - -return extra; -} - - -/************************************************* -* Free the study data * -*************************************************/ - -/* This function frees the memory that was obtained by pcre_study(). - -Argument: a pointer to the pcre[16]_extra block -Returns: nothing -*/ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN void -pcre_free_study(pcre_extra *extra) -#else -PCRE_EXP_DEFN void -pcre16_free_study(pcre16_extra *extra) -#endif -{ -if (extra == NULL) - return; -#ifdef SUPPORT_JIT -if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && - extra->executable_jit != NULL) - PRIV(jit_free)(extra->executable_jit); -#endif -PUBL(free)(extra); -} - -/* End of pcre_study.c */ diff --git a/glib/pcre/pcre_tables.c b/glib/pcre/pcre_tables.c deleted file mode 100644 index abcc96ef4..000000000 --- a/glib/pcre/pcre_tables.c +++ /dev/null @@ -1,600 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - -#ifndef PCRE_INCLUDED - -/* This module contains some fixed tables that are used by more than one of the -PCRE code modules. The tables are also #included by the pcretest program, which -uses macros to change their names from _pcre_xxx to xxxx, thereby avoiding name -clashes with the library. */ - - -#include "config.h" - -#include "pcre_internal.h" - -#endif /* PCRE_INCLUDED */ - -/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that -the definition is next to the definition of the opcodes in pcre_internal.h. */ - -const pcre_uint8 PRIV(OP_lengths)[] = { OP_LENGTHS }; - - - -/************************************************* -* Tables for UTF-8 support * -*************************************************/ - -/* These are the breakpoints for different numbers of bytes in a UTF-8 -character. */ - -#if (defined SUPPORT_UTF && defined COMPILE_PCRE8) \ - || (defined PCRE_INCLUDED && defined SUPPORT_PCRE16) - -/* These tables are also required by pcretest in 16 bit mode. */ - -const int PRIV(utf8_table1)[] = - { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff}; - -const int PRIV(utf8_table1_size) = sizeof(PRIV(utf8_table1)) / sizeof(int); - -/* These are the indicator bits and the mask for the data bits to set in the -first byte of a character, indexed by the number of additional bytes. */ - -const int PRIV(utf8_table2)[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; -const int PRIV(utf8_table3)[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; - -/* Table of the number of extra bytes, indexed by the first byte masked with -0x3f. The highest number for a valid UTF-8 first byte is in fact 0x3d. */ - -const pcre_uint8 PRIV(utf8_table4)[] = { - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; - -#endif /* (SUPPORT_UTF && COMPILE_PCRE8) || (PCRE_INCLUDED && SUPPORT_PCRE16)*/ - -#ifdef SUPPORT_UTF - -/* Table to translate from particular type value to the general value. */ - -const int PRIV(ucp_gentype)[] = { - ucp_C, ucp_C, ucp_C, ucp_C, ucp_C, /* Cc, Cf, Cn, Co, Cs */ - ucp_L, ucp_L, ucp_L, ucp_L, ucp_L, /* Ll, Lu, Lm, Lo, Lt */ - ucp_M, ucp_M, ucp_M, /* Mc, Me, Mn */ - ucp_N, ucp_N, ucp_N, /* Nd, Nl, No */ - ucp_P, ucp_P, ucp_P, ucp_P, ucp_P, /* Pc, Pd, Pe, Pf, Pi */ - ucp_P, ucp_P, /* Ps, Po */ - ucp_S, ucp_S, ucp_S, ucp_S, /* Sc, Sk, Sm, So */ - ucp_Z, ucp_Z, ucp_Z /* Zl, Zp, Zs */ -}; - -#ifdef SUPPORT_JIT -/* This table reverses PRIV(ucp_gentype). We can save the cost -of a memory load. */ - -const int PRIV(ucp_typerange)[] = { - ucp_Cc, ucp_Cs, - ucp_Ll, ucp_Lu, - ucp_Mc, ucp_Mn, - ucp_Nd, ucp_No, - ucp_Pc, ucp_Ps, - ucp_Sc, ucp_So, - ucp_Zl, ucp_Zs, -}; -#endif /* SUPPORT_JIT */ - -/* The pcre_utt[] table below translates Unicode property names into type and -code values. It is searched by binary chop, so must be in collating sequence of -name. Originally, the table contained pointers to the name strings in the first -field of each entry. However, that leads to a large number of relocations when -a shared library is dynamically loaded. A significant reduction is made by -putting all the names into a single, large string and then using offsets in the -table itself. Maintenance is more error-prone, but frequent changes to this -data are unlikely. - -July 2008: There is now a script called maint/GenerateUtt.py that can be used -to generate this data automatically instead of maintaining it by hand. - -The script was updated in March 2009 to generate a new EBCDIC-compliant -version. Like all other character and string literals that are compared against -the regular expression pattern, we must use STR_ macros instead of literal -strings to make sure that UTF-8 support works on EBCDIC platforms. */ - -#define STRING_Any0 STR_A STR_n STR_y "\0" -#define STRING_Arabic0 STR_A STR_r STR_a STR_b STR_i STR_c "\0" -#define STRING_Armenian0 STR_A STR_r STR_m STR_e STR_n STR_i STR_a STR_n "\0" -#define STRING_Avestan0 STR_A STR_v STR_e STR_s STR_t STR_a STR_n "\0" -#define STRING_Balinese0 STR_B STR_a STR_l STR_i STR_n STR_e STR_s STR_e "\0" -#define STRING_Bamum0 STR_B STR_a STR_m STR_u STR_m "\0" -#define STRING_Batak0 STR_B STR_a STR_t STR_a STR_k "\0" -#define STRING_Bengali0 STR_B STR_e STR_n STR_g STR_a STR_l STR_i "\0" -#define STRING_Bopomofo0 STR_B STR_o STR_p STR_o STR_m STR_o STR_f STR_o "\0" -#define STRING_Brahmi0 STR_B STR_r STR_a STR_h STR_m STR_i "\0" -#define STRING_Braille0 STR_B STR_r STR_a STR_i STR_l STR_l STR_e "\0" -#define STRING_Buginese0 STR_B STR_u STR_g STR_i STR_n STR_e STR_s STR_e "\0" -#define STRING_Buhid0 STR_B STR_u STR_h STR_i STR_d "\0" -#define STRING_C0 STR_C "\0" -#define STRING_Canadian_Aboriginal0 STR_C STR_a STR_n STR_a STR_d STR_i STR_a STR_n STR_UNDERSCORE STR_A STR_b STR_o STR_r STR_i STR_g STR_i STR_n STR_a STR_l "\0" -#define STRING_Carian0 STR_C STR_a STR_r STR_i STR_a STR_n "\0" -#define STRING_Cc0 STR_C STR_c "\0" -#define STRING_Cf0 STR_C STR_f "\0" -#define STRING_Chakma0 STR_C STR_h STR_a STR_k STR_m STR_a "\0" -#define STRING_Cham0 STR_C STR_h STR_a STR_m "\0" -#define STRING_Cherokee0 STR_C STR_h STR_e STR_r STR_o STR_k STR_e STR_e "\0" -#define STRING_Cn0 STR_C STR_n "\0" -#define STRING_Co0 STR_C STR_o "\0" -#define STRING_Common0 STR_C STR_o STR_m STR_m STR_o STR_n "\0" -#define STRING_Coptic0 STR_C STR_o STR_p STR_t STR_i STR_c "\0" -#define STRING_Cs0 STR_C STR_s "\0" -#define STRING_Cuneiform0 STR_C STR_u STR_n STR_e STR_i STR_f STR_o STR_r STR_m "\0" -#define STRING_Cypriot0 STR_C STR_y STR_p STR_r STR_i STR_o STR_t "\0" -#define STRING_Cyrillic0 STR_C STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0" -#define STRING_Deseret0 STR_D STR_e STR_s STR_e STR_r STR_e STR_t "\0" -#define STRING_Devanagari0 STR_D STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0" -#define STRING_Egyptian_Hieroglyphs0 STR_E STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0" -#define STRING_Ethiopic0 STR_E STR_t STR_h STR_i STR_o STR_p STR_i STR_c "\0" -#define STRING_Georgian0 STR_G STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0" -#define STRING_Glagolitic0 STR_G STR_l STR_a STR_g STR_o STR_l STR_i STR_t STR_i STR_c "\0" -#define STRING_Gothic0 STR_G STR_o STR_t STR_h STR_i STR_c "\0" -#define STRING_Greek0 STR_G STR_r STR_e STR_e STR_k "\0" -#define STRING_Gujarati0 STR_G STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0" -#define STRING_Gurmukhi0 STR_G STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0" -#define STRING_Han0 STR_H STR_a STR_n "\0" -#define STRING_Hangul0 STR_H STR_a STR_n STR_g STR_u STR_l "\0" -#define STRING_Hanunoo0 STR_H STR_a STR_n STR_u STR_n STR_o STR_o "\0" -#define STRING_Hebrew0 STR_H STR_e STR_b STR_r STR_e STR_w "\0" -#define STRING_Hiragana0 STR_H STR_i STR_r STR_a STR_g STR_a STR_n STR_a "\0" -#define STRING_Imperial_Aramaic0 STR_I STR_m STR_p STR_e STR_r STR_i STR_a STR_l STR_UNDERSCORE STR_A STR_r STR_a STR_m STR_a STR_i STR_c "\0" -#define STRING_Inherited0 STR_I STR_n STR_h STR_e STR_r STR_i STR_t STR_e STR_d "\0" -#define STRING_Inscriptional_Pahlavi0 STR_I STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_UNDERSCORE STR_P STR_a STR_h STR_l STR_a STR_v STR_i "\0" -#define STRING_Inscriptional_Parthian0 STR_I STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_UNDERSCORE STR_P STR_a STR_r STR_t STR_h STR_i STR_a STR_n "\0" -#define STRING_Javanese0 STR_J STR_a STR_v STR_a STR_n STR_e STR_s STR_e "\0" -#define STRING_Kaithi0 STR_K STR_a STR_i STR_t STR_h STR_i "\0" -#define STRING_Kannada0 STR_K STR_a STR_n STR_n STR_a STR_d STR_a "\0" -#define STRING_Katakana0 STR_K STR_a STR_t STR_a STR_k STR_a STR_n STR_a "\0" -#define STRING_Kayah_Li0 STR_K STR_a STR_y STR_a STR_h STR_UNDERSCORE STR_L STR_i "\0" -#define STRING_Kharoshthi0 STR_K STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0" -#define STRING_Khmer0 STR_K STR_h STR_m STR_e STR_r "\0" -#define STRING_L0 STR_L "\0" -#define STRING_L_AMPERSAND0 STR_L STR_AMPERSAND "\0" -#define STRING_Lao0 STR_L STR_a STR_o "\0" -#define STRING_Latin0 STR_L STR_a STR_t STR_i STR_n "\0" -#define STRING_Lepcha0 STR_L STR_e STR_p STR_c STR_h STR_a "\0" -#define STRING_Limbu0 STR_L STR_i STR_m STR_b STR_u "\0" -#define STRING_Linear_B0 STR_L STR_i STR_n STR_e STR_a STR_r STR_UNDERSCORE STR_B "\0" -#define STRING_Lisu0 STR_L STR_i STR_s STR_u "\0" -#define STRING_Ll0 STR_L STR_l "\0" -#define STRING_Lm0 STR_L STR_m "\0" -#define STRING_Lo0 STR_L STR_o "\0" -#define STRING_Lt0 STR_L STR_t "\0" -#define STRING_Lu0 STR_L STR_u "\0" -#define STRING_Lycian0 STR_L STR_y STR_c STR_i STR_a STR_n "\0" -#define STRING_Lydian0 STR_L STR_y STR_d STR_i STR_a STR_n "\0" -#define STRING_M0 STR_M "\0" -#define STRING_Malayalam0 STR_M STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0" -#define STRING_Mandaic0 STR_M STR_a STR_n STR_d STR_a STR_i STR_c "\0" -#define STRING_Mc0 STR_M STR_c "\0" -#define STRING_Me0 STR_M STR_e "\0" -#define STRING_Meetei_Mayek0 STR_M STR_e STR_e STR_t STR_e STR_i STR_UNDERSCORE STR_M STR_a STR_y STR_e STR_k "\0" -#define STRING_Meroitic_Cursive0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_C STR_u STR_r STR_s STR_i STR_v STR_e "\0" -#define STRING_Meroitic_Hieroglyphs0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0" -#define STRING_Miao0 STR_M STR_i STR_a STR_o "\0" -#define STRING_Mn0 STR_M STR_n "\0" -#define STRING_Mongolian0 STR_M STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0" -#define STRING_Myanmar0 STR_M STR_y STR_a STR_n STR_m STR_a STR_r "\0" -#define STRING_N0 STR_N "\0" -#define STRING_Nd0 STR_N STR_d "\0" -#define STRING_New_Tai_Lue0 STR_N STR_e STR_w STR_UNDERSCORE STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_u STR_e "\0" -#define STRING_Nko0 STR_N STR_k STR_o "\0" -#define STRING_Nl0 STR_N STR_l "\0" -#define STRING_No0 STR_N STR_o "\0" -#define STRING_Ogham0 STR_O STR_g STR_h STR_a STR_m "\0" -#define STRING_Ol_Chiki0 STR_O STR_l STR_UNDERSCORE STR_C STR_h STR_i STR_k STR_i "\0" -#define STRING_Old_Italic0 STR_O STR_l STR_d STR_UNDERSCORE STR_I STR_t STR_a STR_l STR_i STR_c "\0" -#define STRING_Old_Persian0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_s STR_i STR_a STR_n "\0" -#define STRING_Old_South_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_u STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0" -#define STRING_Old_Turkic0 STR_O STR_l STR_d STR_UNDERSCORE STR_T STR_u STR_r STR_k STR_i STR_c "\0" -#define STRING_Oriya0 STR_O STR_r STR_i STR_y STR_a "\0" -#define STRING_Osmanya0 STR_O STR_s STR_m STR_a STR_n STR_y STR_a "\0" -#define STRING_P0 STR_P "\0" -#define STRING_Pc0 STR_P STR_c "\0" -#define STRING_Pd0 STR_P STR_d "\0" -#define STRING_Pe0 STR_P STR_e "\0" -#define STRING_Pf0 STR_P STR_f "\0" -#define STRING_Phags_Pa0 STR_P STR_h STR_a STR_g STR_s STR_UNDERSCORE STR_P STR_a "\0" -#define STRING_Phoenician0 STR_P STR_h STR_o STR_e STR_n STR_i STR_c STR_i STR_a STR_n "\0" -#define STRING_Pi0 STR_P STR_i "\0" -#define STRING_Po0 STR_P STR_o "\0" -#define STRING_Ps0 STR_P STR_s "\0" -#define STRING_Rejang0 STR_R STR_e STR_j STR_a STR_n STR_g "\0" -#define STRING_Runic0 STR_R STR_u STR_n STR_i STR_c "\0" -#define STRING_S0 STR_S "\0" -#define STRING_Samaritan0 STR_S STR_a STR_m STR_a STR_r STR_i STR_t STR_a STR_n "\0" -#define STRING_Saurashtra0 STR_S STR_a STR_u STR_r STR_a STR_s STR_h STR_t STR_r STR_a "\0" -#define STRING_Sc0 STR_S STR_c "\0" -#define STRING_Sharada0 STR_S STR_h STR_a STR_r STR_a STR_d STR_a "\0" -#define STRING_Shavian0 STR_S STR_h STR_a STR_v STR_i STR_a STR_n "\0" -#define STRING_Sinhala0 STR_S STR_i STR_n STR_h STR_a STR_l STR_a "\0" -#define STRING_Sk0 STR_S STR_k "\0" -#define STRING_Sm0 STR_S STR_m "\0" -#define STRING_So0 STR_S STR_o "\0" -#define STRING_Sora_Sompeng0 STR_S STR_o STR_r STR_a STR_UNDERSCORE STR_S STR_o STR_m STR_p STR_e STR_n STR_g "\0" -#define STRING_Sundanese0 STR_S STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0" -#define STRING_Syloti_Nagri0 STR_S STR_y STR_l STR_o STR_t STR_i STR_UNDERSCORE STR_N STR_a STR_g STR_r STR_i "\0" -#define STRING_Syriac0 STR_S STR_y STR_r STR_i STR_a STR_c "\0" -#define STRING_Tagalog0 STR_T STR_a STR_g STR_a STR_l STR_o STR_g "\0" -#define STRING_Tagbanwa0 STR_T STR_a STR_g STR_b STR_a STR_n STR_w STR_a "\0" -#define STRING_Tai_Le0 STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_e "\0" -#define STRING_Tai_Tham0 STR_T STR_a STR_i STR_UNDERSCORE STR_T STR_h STR_a STR_m "\0" -#define STRING_Tai_Viet0 STR_T STR_a STR_i STR_UNDERSCORE STR_V STR_i STR_e STR_t "\0" -#define STRING_Takri0 STR_T STR_a STR_k STR_r STR_i "\0" -#define STRING_Tamil0 STR_T STR_a STR_m STR_i STR_l "\0" -#define STRING_Telugu0 STR_T STR_e STR_l STR_u STR_g STR_u "\0" -#define STRING_Thaana0 STR_T STR_h STR_a STR_a STR_n STR_a "\0" -#define STRING_Thai0 STR_T STR_h STR_a STR_i "\0" -#define STRING_Tibetan0 STR_T STR_i STR_b STR_e STR_t STR_a STR_n "\0" -#define STRING_Tifinagh0 STR_T STR_i STR_f STR_i STR_n STR_a STR_g STR_h "\0" -#define STRING_Ugaritic0 STR_U STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0" -#define STRING_Vai0 STR_V STR_a STR_i "\0" -#define STRING_Xan0 STR_X STR_a STR_n "\0" -#define STRING_Xps0 STR_X STR_p STR_s "\0" -#define STRING_Xsp0 STR_X STR_s STR_p "\0" -#define STRING_Xwd0 STR_X STR_w STR_d "\0" -#define STRING_Yi0 STR_Y STR_i "\0" -#define STRING_Z0 STR_Z "\0" -#define STRING_Zl0 STR_Z STR_l "\0" -#define STRING_Zp0 STR_Z STR_p "\0" -#define STRING_Zs0 STR_Z STR_s "\0" - -const char PRIV(utt_names)[] = - STRING_Any0 - STRING_Arabic0 - STRING_Armenian0 - STRING_Avestan0 - STRING_Balinese0 - STRING_Bamum0 - STRING_Batak0 - STRING_Bengali0 - STRING_Bopomofo0 - STRING_Brahmi0 - STRING_Braille0 - STRING_Buginese0 - STRING_Buhid0 - STRING_C0 - STRING_Canadian_Aboriginal0 - STRING_Carian0 - STRING_Cc0 - STRING_Cf0 - STRING_Chakma0 - STRING_Cham0 - STRING_Cherokee0 - STRING_Cn0 - STRING_Co0 - STRING_Common0 - STRING_Coptic0 - STRING_Cs0 - STRING_Cuneiform0 - STRING_Cypriot0 - STRING_Cyrillic0 - STRING_Deseret0 - STRING_Devanagari0 - STRING_Egyptian_Hieroglyphs0 - STRING_Ethiopic0 - STRING_Georgian0 - STRING_Glagolitic0 - STRING_Gothic0 - STRING_Greek0 - STRING_Gujarati0 - STRING_Gurmukhi0 - STRING_Han0 - STRING_Hangul0 - STRING_Hanunoo0 - STRING_Hebrew0 - STRING_Hiragana0 - STRING_Imperial_Aramaic0 - STRING_Inherited0 - STRING_Inscriptional_Pahlavi0 - STRING_Inscriptional_Parthian0 - STRING_Javanese0 - STRING_Kaithi0 - STRING_Kannada0 - STRING_Katakana0 - STRING_Kayah_Li0 - STRING_Kharoshthi0 - STRING_Khmer0 - STRING_L0 - STRING_L_AMPERSAND0 - STRING_Lao0 - STRING_Latin0 - STRING_Lepcha0 - STRING_Limbu0 - STRING_Linear_B0 - STRING_Lisu0 - STRING_Ll0 - STRING_Lm0 - STRING_Lo0 - STRING_Lt0 - STRING_Lu0 - STRING_Lycian0 - STRING_Lydian0 - STRING_M0 - STRING_Malayalam0 - STRING_Mandaic0 - STRING_Mc0 - STRING_Me0 - STRING_Meetei_Mayek0 - STRING_Meroitic_Cursive0 - STRING_Meroitic_Hieroglyphs0 - STRING_Miao0 - STRING_Mn0 - STRING_Mongolian0 - STRING_Myanmar0 - STRING_N0 - STRING_Nd0 - STRING_New_Tai_Lue0 - STRING_Nko0 - STRING_Nl0 - STRING_No0 - STRING_Ogham0 - STRING_Ol_Chiki0 - STRING_Old_Italic0 - STRING_Old_Persian0 - STRING_Old_South_Arabian0 - STRING_Old_Turkic0 - STRING_Oriya0 - STRING_Osmanya0 - STRING_P0 - STRING_Pc0 - STRING_Pd0 - STRING_Pe0 - STRING_Pf0 - STRING_Phags_Pa0 - STRING_Phoenician0 - STRING_Pi0 - STRING_Po0 - STRING_Ps0 - STRING_Rejang0 - STRING_Runic0 - STRING_S0 - STRING_Samaritan0 - STRING_Saurashtra0 - STRING_Sc0 - STRING_Sharada0 - STRING_Shavian0 - STRING_Sinhala0 - STRING_Sk0 - STRING_Sm0 - STRING_So0 - STRING_Sora_Sompeng0 - STRING_Sundanese0 - STRING_Syloti_Nagri0 - STRING_Syriac0 - STRING_Tagalog0 - STRING_Tagbanwa0 - STRING_Tai_Le0 - STRING_Tai_Tham0 - STRING_Tai_Viet0 - STRING_Takri0 - STRING_Tamil0 - STRING_Telugu0 - STRING_Thaana0 - STRING_Thai0 - STRING_Tibetan0 - STRING_Tifinagh0 - STRING_Ugaritic0 - STRING_Vai0 - STRING_Xan0 - STRING_Xps0 - STRING_Xsp0 - STRING_Xwd0 - STRING_Yi0 - STRING_Z0 - STRING_Zl0 - STRING_Zp0 - STRING_Zs0; - -const ucp_type_table PRIV(utt)[] = { - { 0, PT_ANY, 0 }, - { 4, PT_SC, ucp_Arabic }, - { 11, PT_SC, ucp_Armenian }, - { 20, PT_SC, ucp_Avestan }, - { 28, PT_SC, ucp_Balinese }, - { 37, PT_SC, ucp_Bamum }, - { 43, PT_SC, ucp_Batak }, - { 49, PT_SC, ucp_Bengali }, - { 57, PT_SC, ucp_Bopomofo }, - { 66, PT_SC, ucp_Brahmi }, - { 73, PT_SC, ucp_Braille }, - { 81, PT_SC, ucp_Buginese }, - { 90, PT_SC, ucp_Buhid }, - { 96, PT_GC, ucp_C }, - { 98, PT_SC, ucp_Canadian_Aboriginal }, - { 118, PT_SC, ucp_Carian }, - { 125, PT_PC, ucp_Cc }, - { 128, PT_PC, ucp_Cf }, - { 131, PT_SC, ucp_Chakma }, - { 138, PT_SC, ucp_Cham }, - { 143, PT_SC, ucp_Cherokee }, - { 152, PT_PC, ucp_Cn }, - { 155, PT_PC, ucp_Co }, - { 158, PT_SC, ucp_Common }, - { 165, PT_SC, ucp_Coptic }, - { 172, PT_PC, ucp_Cs }, - { 175, PT_SC, ucp_Cuneiform }, - { 185, PT_SC, ucp_Cypriot }, - { 193, PT_SC, ucp_Cyrillic }, - { 202, PT_SC, ucp_Deseret }, - { 210, PT_SC, ucp_Devanagari }, - { 221, PT_SC, ucp_Egyptian_Hieroglyphs }, - { 242, PT_SC, ucp_Ethiopic }, - { 251, PT_SC, ucp_Georgian }, - { 260, PT_SC, ucp_Glagolitic }, - { 271, PT_SC, ucp_Gothic }, - { 278, PT_SC, ucp_Greek }, - { 284, PT_SC, ucp_Gujarati }, - { 293, PT_SC, ucp_Gurmukhi }, - { 302, PT_SC, ucp_Han }, - { 306, PT_SC, ucp_Hangul }, - { 313, PT_SC, ucp_Hanunoo }, - { 321, PT_SC, ucp_Hebrew }, - { 328, PT_SC, ucp_Hiragana }, - { 337, PT_SC, ucp_Imperial_Aramaic }, - { 354, PT_SC, ucp_Inherited }, - { 364, PT_SC, ucp_Inscriptional_Pahlavi }, - { 386, PT_SC, ucp_Inscriptional_Parthian }, - { 409, PT_SC, ucp_Javanese }, - { 418, PT_SC, ucp_Kaithi }, - { 425, PT_SC, ucp_Kannada }, - { 433, PT_SC, ucp_Katakana }, - { 442, PT_SC, ucp_Kayah_Li }, - { 451, PT_SC, ucp_Kharoshthi }, - { 462, PT_SC, ucp_Khmer }, - { 468, PT_GC, ucp_L }, - { 470, PT_LAMP, 0 }, - { 473, PT_SC, ucp_Lao }, - { 477, PT_SC, ucp_Latin }, - { 483, PT_SC, ucp_Lepcha }, - { 490, PT_SC, ucp_Limbu }, - { 496, PT_SC, ucp_Linear_B }, - { 505, PT_SC, ucp_Lisu }, - { 510, PT_PC, ucp_Ll }, - { 513, PT_PC, ucp_Lm }, - { 516, PT_PC, ucp_Lo }, - { 519, PT_PC, ucp_Lt }, - { 522, PT_PC, ucp_Lu }, - { 525, PT_SC, ucp_Lycian }, - { 532, PT_SC, ucp_Lydian }, - { 539, PT_GC, ucp_M }, - { 541, PT_SC, ucp_Malayalam }, - { 551, PT_SC, ucp_Mandaic }, - { 559, PT_PC, ucp_Mc }, - { 562, PT_PC, ucp_Me }, - { 565, PT_SC, ucp_Meetei_Mayek }, - { 578, PT_SC, ucp_Meroitic_Cursive }, - { 595, PT_SC, ucp_Meroitic_Hieroglyphs }, - { 616, PT_SC, ucp_Miao }, - { 621, PT_PC, ucp_Mn }, - { 624, PT_SC, ucp_Mongolian }, - { 634, PT_SC, ucp_Myanmar }, - { 642, PT_GC, ucp_N }, - { 644, PT_PC, ucp_Nd }, - { 647, PT_SC, ucp_New_Tai_Lue }, - { 659, PT_SC, ucp_Nko }, - { 663, PT_PC, ucp_Nl }, - { 666, PT_PC, ucp_No }, - { 669, PT_SC, ucp_Ogham }, - { 675, PT_SC, ucp_Ol_Chiki }, - { 684, PT_SC, ucp_Old_Italic }, - { 695, PT_SC, ucp_Old_Persian }, - { 707, PT_SC, ucp_Old_South_Arabian }, - { 725, PT_SC, ucp_Old_Turkic }, - { 736, PT_SC, ucp_Oriya }, - { 742, PT_SC, ucp_Osmanya }, - { 750, PT_GC, ucp_P }, - { 752, PT_PC, ucp_Pc }, - { 755, PT_PC, ucp_Pd }, - { 758, PT_PC, ucp_Pe }, - { 761, PT_PC, ucp_Pf }, - { 764, PT_SC, ucp_Phags_Pa }, - { 773, PT_SC, ucp_Phoenician }, - { 784, PT_PC, ucp_Pi }, - { 787, PT_PC, ucp_Po }, - { 790, PT_PC, ucp_Ps }, - { 793, PT_SC, ucp_Rejang }, - { 800, PT_SC, ucp_Runic }, - { 806, PT_GC, ucp_S }, - { 808, PT_SC, ucp_Samaritan }, - { 818, PT_SC, ucp_Saurashtra }, - { 829, PT_PC, ucp_Sc }, - { 832, PT_SC, ucp_Sharada }, - { 840, PT_SC, ucp_Shavian }, - { 848, PT_SC, ucp_Sinhala }, - { 856, PT_PC, ucp_Sk }, - { 859, PT_PC, ucp_Sm }, - { 862, PT_PC, ucp_So }, - { 865, PT_SC, ucp_Sora_Sompeng }, - { 878, PT_SC, ucp_Sundanese }, - { 888, PT_SC, ucp_Syloti_Nagri }, - { 901, PT_SC, ucp_Syriac }, - { 908, PT_SC, ucp_Tagalog }, - { 916, PT_SC, ucp_Tagbanwa }, - { 925, PT_SC, ucp_Tai_Le }, - { 932, PT_SC, ucp_Tai_Tham }, - { 941, PT_SC, ucp_Tai_Viet }, - { 950, PT_SC, ucp_Takri }, - { 956, PT_SC, ucp_Tamil }, - { 962, PT_SC, ucp_Telugu }, - { 969, PT_SC, ucp_Thaana }, - { 976, PT_SC, ucp_Thai }, - { 981, PT_SC, ucp_Tibetan }, - { 989, PT_SC, ucp_Tifinagh }, - { 998, PT_SC, ucp_Ugaritic }, - { 1007, PT_SC, ucp_Vai }, - { 1011, PT_ALNUM, 0 }, - { 1015, PT_PXSPACE, 0 }, - { 1019, PT_SPACE, 0 }, - { 1023, PT_WORD, 0 }, - { 1027, PT_SC, ucp_Yi }, - { 1030, PT_GC, ucp_Z }, - { 1032, PT_PC, ucp_Zl }, - { 1035, PT_PC, ucp_Zp }, - { 1038, PT_PC, ucp_Zs } -}; - -const int PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table); - -unsigned int -_pcre_ucp_othercase(const unsigned int c) -{ - unsigned int oc = NOTACHAR; - - if ((oc = g_unichar_toupper(c)) != c) - return oc; - if ((oc = g_unichar_tolower(c)) != c) - return oc; - - return c; -} - -#endif /* SUPPORT_UTF */ - -/* End of pcre_tables.c */ diff --git a/glib/pcre/pcre_valid_utf8.c b/glib/pcre/pcre_valid_utf8.c deleted file mode 100644 index cecaf347f..000000000 --- a/glib/pcre/pcre_valid_utf8.c +++ /dev/null @@ -1,297 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains an internal function for validating UTF-8 character -strings. */ - - -#include "config.h" - -#include "pcre_internal.h" - - -/************************************************* -* Validate a UTF-8 string * -*************************************************/ - -/* This function is called (optionally) at the start of compile or match, to -check that a supposed UTF-8 string is actually valid. The early check means -that subsequent code can assume it is dealing with a valid string. The check -can be turned off for maximum performance, but the consequences of supplying an -invalid string are then undefined. - -Originally, this function checked according to RFC 2279, allowing for values in -the range 0 to 0x7fffffff, up to 6 bytes long, but ensuring that they were in -the canonical format. Once somebody had pointed out RFC 3629 to me (it -obsoletes 2279), additional restrictions were applied. The values are now -limited to be between 0 and 0x0010ffff, no more than 4 bytes long, and the -subrange 0xd000 to 0xdfff is excluded. However, the format of 5-byte and 6-byte -characters is still checked. - -From release 8.13 more information about the details of the error are passed -back in the returned value: - -PCRE_UTF8_ERR0 No error -PCRE_UTF8_ERR1 Missing 1 byte at the end of the string -PCRE_UTF8_ERR2 Missing 2 bytes at the end of the string -PCRE_UTF8_ERR3 Missing 3 bytes at the end of the string -PCRE_UTF8_ERR4 Missing 4 bytes at the end of the string -PCRE_UTF8_ERR5 Missing 5 bytes at the end of the string -PCRE_UTF8_ERR6 2nd-byte's two top bits are not 0x80 -PCRE_UTF8_ERR7 3rd-byte's two top bits are not 0x80 -PCRE_UTF8_ERR8 4th-byte's two top bits are not 0x80 -PCRE_UTF8_ERR9 5th-byte's two top bits are not 0x80 -PCRE_UTF8_ERR10 6th-byte's two top bits are not 0x80 -PCRE_UTF8_ERR11 5-byte character is not permitted by RFC 3629 -PCRE_UTF8_ERR12 6-byte character is not permitted by RFC 3629 -PCRE_UTF8_ERR13 4-byte character with value > 0x10ffff is not permitted -PCRE_UTF8_ERR14 3-byte character with value 0xd000-0xdfff is not permitted -PCRE_UTF8_ERR15 Overlong 2-byte sequence -PCRE_UTF8_ERR16 Overlong 3-byte sequence -PCRE_UTF8_ERR17 Overlong 4-byte sequence -PCRE_UTF8_ERR18 Overlong 5-byte sequence (won't ever occur) -PCRE_UTF8_ERR19 Overlong 6-byte sequence (won't ever occur) -PCRE_UTF8_ERR20 Isolated 0x80 byte (not within UTF-8 character) -PCRE_UTF8_ERR21 Byte with the illegal value 0xfe or 0xff - -Arguments: - string points to the string - length length of string, or -1 if the string is zero-terminated - errp pointer to an error position offset variable - -Returns: = 0 if the string is a valid UTF-8 string - > 0 otherwise, setting the offset of the bad character -*/ - -int -PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset) -{ -#ifdef SUPPORT_UTF -PCRE_PUCHAR p; - -if (length < 0) - { - for (p = string; *p != 0; p++); - length = (int)(p - string); - } - -for (p = string; length-- > 0; p++) - { - int ab, c, d; - - c = *p; - if (c < 128) continue; /* ASCII character */ - - if (c < 0xc0) /* Isolated 10xx xxxx byte */ - { - *erroroffset = (int)(p - string); - return PCRE_UTF8_ERR20; - } - - if (c >= 0xfe) /* Invalid 0xfe or 0xff bytes */ - { - *erroroffset = (int)(p - string); - return PCRE_UTF8_ERR21; - } - - ab = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */ - if (length < ab) - { - *erroroffset = (int)(p - string); /* Missing bytes */ - return ab - length; /* Codes ERR1 to ERR5 */ - } - length -= ab; /* Length remaining */ - - /* Check top bits in the second byte */ - - if (((d = *(++p)) & 0xc0) != 0x80) - { - *erroroffset = (int)(p - string) - 1; - return PCRE_UTF8_ERR6; - } - - /* For each length, check that the remaining bytes start with the 0x80 bit - set and not the 0x40 bit. Then check for an overlong sequence, and for the - excluded range 0xd800 to 0xdfff. */ - - switch (ab) - { - /* 2-byte character. No further bytes to check for 0x80. Check first byte - for for xx00 000x (overlong sequence). */ - - case 1: if ((c & 0x3e) == 0) - { - *erroroffset = (int)(p - string) - 1; - return PCRE_UTF8_ERR15; - } - break; - - /* 3-byte character. Check third byte for 0x80. Then check first 2 bytes - for 1110 0000, xx0x xxxx (overlong sequence) or - 1110 1101, 1010 xxxx (0xd800 - 0xdfff) */ - - case 2: - if ((*(++p) & 0xc0) != 0x80) /* Third byte */ - { - *erroroffset = (int)(p - string) - 2; - return PCRE_UTF8_ERR7; - } - if (c == 0xe0 && (d & 0x20) == 0) - { - *erroroffset = (int)(p - string) - 2; - return PCRE_UTF8_ERR16; - } - if (c == 0xed && d >= 0xa0) - { - *erroroffset = (int)(p - string) - 2; - return PCRE_UTF8_ERR14; - } - break; - - /* 4-byte character. Check 3rd and 4th bytes for 0x80. Then check first 2 - bytes for for 1111 0000, xx00 xxxx (overlong sequence), then check for a - character greater than 0x0010ffff (f4 8f bf bf) */ - - case 3: - if ((*(++p) & 0xc0) != 0x80) /* Third byte */ - { - *erroroffset = (int)(p - string) - 2; - return PCRE_UTF8_ERR7; - } - if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */ - { - *erroroffset = (int)(p - string) - 3; - return PCRE_UTF8_ERR8; - } - if (c == 0xf0 && (d & 0x30) == 0) - { - *erroroffset = (int)(p - string) - 3; - return PCRE_UTF8_ERR17; - } - if (c > 0xf4 || (c == 0xf4 && d > 0x8f)) - { - *erroroffset = (int)(p - string) - 3; - return PCRE_UTF8_ERR13; - } - break; - - /* 5-byte and 6-byte characters are not allowed by RFC 3629, and will be - rejected by the length test below. However, we do the appropriate tests - here so that overlong sequences get diagnosed, and also in case there is - ever an option for handling these larger code points. */ - - /* 5-byte character. Check 3rd, 4th, and 5th bytes for 0x80. Then check for - 1111 1000, xx00 0xxx */ - - case 4: - if ((*(++p) & 0xc0) != 0x80) /* Third byte */ - { - *erroroffset = (int)(p - string) - 2; - return PCRE_UTF8_ERR7; - } - if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */ - { - *erroroffset = (int)(p - string) - 3; - return PCRE_UTF8_ERR8; - } - if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */ - { - *erroroffset = (int)(p - string) - 4; - return PCRE_UTF8_ERR9; - } - if (c == 0xf8 && (d & 0x38) == 0) - { - *erroroffset = (int)(p - string) - 4; - return PCRE_UTF8_ERR18; - } - break; - - /* 6-byte character. Check 3rd-6th bytes for 0x80. Then check for - 1111 1100, xx00 00xx. */ - - case 5: - if ((*(++p) & 0xc0) != 0x80) /* Third byte */ - { - *erroroffset = (int)(p - string) - 2; - return PCRE_UTF8_ERR7; - } - if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */ - { - *erroroffset = (int)(p - string) - 3; - return PCRE_UTF8_ERR8; - } - if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */ - { - *erroroffset = (int)(p - string) - 4; - return PCRE_UTF8_ERR9; - } - if ((*(++p) & 0xc0) != 0x80) /* Sixth byte */ - { - *erroroffset = (int)(p - string) - 5; - return PCRE_UTF8_ERR10; - } - if (c == 0xfc && (d & 0x3c) == 0) - { - *erroroffset = (int)(p - string) - 5; - return PCRE_UTF8_ERR19; - } - break; - } - - /* Character is valid under RFC 2279, but 4-byte and 5-byte characters are - excluded by RFC 3629. The pointer p is currently at the last byte of the - character. */ - - if (ab > 3) - { - *erroroffset = (int)(p - string) - ab; - return (ab == 4)? PCRE_UTF8_ERR11 : PCRE_UTF8_ERR12; - } - } - -#else /* SUPPORT_UTF */ -(void)(string); /* Keep picky compilers happy */ -(void)(length); -#endif - -return PCRE_UTF8_ERR0; /* This indicates success */ -} - -/* End of pcre_valid_utf8.c */ diff --git a/glib/pcre/pcre_version.c b/glib/pcre/pcre_version.c deleted file mode 100644 index 3dd60a5bc..000000000 --- a/glib/pcre/pcre_version.c +++ /dev/null @@ -1,93 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains the external function pcre_version(), which returns a -string that identifies the PCRE version that is in use. */ - - -#include "config.h" - -#include "pcre_internal.h" - - -/************************************************* -* Return version string * -*************************************************/ - -/* These macros are the standard way of turning unquoted text into C strings. -They allow macros like PCRE_MAJOR to be defined without quotes, which is -convenient for user programs that want to test its value. */ - -#define STRING(a) # a -#define XSTRING(s) STRING(s) - -/* A problem turned up with PCRE_PRERELEASE, which is defined empty for -production releases. Originally, it was used naively in this code: - - return XSTRING(PCRE_MAJOR) - "." XSTRING(PCRE_MINOR) - XSTRING(PCRE_PRERELEASE) - " " XSTRING(PCRE_DATE); - -However, when PCRE_PRERELEASE is empty, this leads to an attempted expansion of -STRING(). The C standard states: "If (before argument substitution) any -argument consists of no preprocessing tokens, the behavior is undefined." It -turns out the gcc treats this case as a single empty string - which is what we -really want - but Visual C grumbles about the lack of an argument for the -macro. Unfortunately, both are within their rights. To cope with both ways of -handling this, I had resort to some messy hackery that does a test at run time. -I could find no way of detecting that a macro is defined as an empty string at -pre-processor time. This hack uses a standard trick for avoiding calling -the STRING macro with an empty argument when doing the test. */ - -#ifdef COMPILE_PCRE8 -PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION -pcre_version(void) -#else -PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION -pcre16_version(void) -#endif -{ -return (XSTRING(Z PCRE_PRERELEASE)[1] == 0)? - XSTRING(PCRE_MAJOR.PCRE_MINOR PCRE_DATE) : - XSTRING(PCRE_MAJOR.PCRE_MINOR) XSTRING(PCRE_PRERELEASE PCRE_DATE); -} - -/* End of pcre_version.c */ diff --git a/glib/pcre/pcre_xclass.c b/glib/pcre/pcre_xclass.c deleted file mode 100644 index 89ad09f54..000000000 --- a/glib/pcre/pcre_xclass.c +++ /dev/null @@ -1,196 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Copyright (c) 1997-2012 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -/* This module contains an internal function that is used to match an extended -class. It is used by both pcre_exec() and pcre_def_exec(). */ - - -#include "config.h" - -#include "pcre_internal.h" - - -/************************************************* -* Match character against an XCLASS * -*************************************************/ - -/* This function is called to match a character against an extended class that -might contain values > 255 and/or Unicode properties. - -Arguments: - c the character - data points to the flag byte of the XCLASS data - -Returns: TRUE if character matches, else FALSE -*/ - -BOOL -PRIV(xclass)(int c, const pcre_uchar *data, BOOL utf) -{ -int t; -BOOL negated = (*data & XCL_NOT) != 0; - -(void)utf; -#ifdef COMPILE_PCRE8 -/* In 8 bit mode, this must always be TRUE. Help the compiler to know that. */ -utf = TRUE; -#endif - -/* Character values < 256 are matched against a bitmap, if one is present. If -not, we still carry on, because there may be ranges that start below 256 in the -additional data. */ - -if (c < 256) - { - if ((*data & XCL_MAP) != 0 && - (((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0) - return !negated; /* char found */ - } - -/* First skip the bit map if present. Then match against the list of Unicode -properties or large chars or ranges that end with a large char. We won't ever -encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */ - -if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(pcre_uchar); - -while ((t = *data++) != XCL_END) - { - int x, y; - if (t == XCL_SINGLE) - { -#ifdef SUPPORT_UTF - if (utf) - { - GETCHARINC(x, data); /* macro generates multiple statements */ - } - else -#endif - x = *data++; - if (c == x) return !negated; - } - else if (t == XCL_RANGE) - { -#ifdef SUPPORT_UTF - if (utf) - { - GETCHARINC(x, data); /* macro generates multiple statements */ - GETCHARINC(y, data); /* macro generates multiple statements */ - } - else -#endif - { - x = *data++; - y = *data++; - } - if (c >= x && c <= y) return !negated; - } - -#ifdef SUPPORT_UCP - else /* XCL_PROP & XCL_NOTPROP */ - { - const pcre_uint8 chartype = UCD_CHARTYPE(c); - - switch(*data) - { - case PT_ANY: - if (t == XCL_PROP) return !negated; - break; - - case PT_LAMP: - if ((chartype == ucp_Lu || chartype == ucp_Ll || - chartype == ucp_Lt) == (t == XCL_PROP)) return !negated; - break; - - case PT_GC: - if ((data[1] == PRIV(ucp_gentype)[chartype]) == (t == XCL_PROP)) - return !negated; - break; - - case PT_PC: - if ((data[1] == chartype) == (t == XCL_PROP)) return !negated; - break; - - case PT_SC: - if ((data[1] == UCD_SCRIPT(c)) == (t == XCL_PROP)) return !negated; - break; - - case PT_ALNUM: - if ((PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N) == (t == XCL_PROP)) - return !negated; - break; - - case PT_SPACE: /* Perl space */ - if ((PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR) - == (t == XCL_PROP)) - return !negated; - break; - - case PT_PXSPACE: /* POSIX space */ - if ((PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR) == (t == XCL_PROP)) - return !negated; - break; - - case PT_WORD: - if ((PRIV(ucp_gentype)[chartype] == ucp_L || - PRIV(ucp_gentype)[chartype] == ucp_N || c == CHAR_UNDERSCORE) - == (t == XCL_PROP)) - return !negated; - break; - - /* This should never occur, but compilers may mutter if there is no - default. */ - - default: - return FALSE; - } - - data += 2; - } -#endif /* SUPPORT_UCP */ - } - -return negated; /* char did not match */ -} - -/* End of pcre_xclass.c */ diff --git a/glib/pcre/ucp.h b/glib/pcre/ucp.h deleted file mode 100644 index f1c14be5d..000000000 --- a/glib/pcre/ucp.h +++ /dev/null @@ -1,179 +0,0 @@ -/************************************************* -* Unicode Property Table handler * -*************************************************/ - -#ifndef _UCP_H -#define _UCP_H - -/* This file contains definitions of the property values that are returned by -the UCD access macros. New values that are added for new releases of Unicode -should always be at the end of each enum, for backwards compatibility. */ - -/* These are the general character categories. */ -#ifdef GLIB_COMPILATION -#include "gunicode.h" -#else -#include <glib.h> -#endif - -enum { - ucp_C, /* Other */ - ucp_L, /* Letter */ - ucp_M, /* Mark */ - ucp_N, /* Number */ - ucp_P, /* Punctuation */ - ucp_S, /* Symbol */ - ucp_Z /* Separator */ -}; - -/* These are the particular character types. */ - -enum { - ucp_Cc = G_UNICODE_CONTROL, /* Control */ - ucp_Cf = G_UNICODE_FORMAT, /* Format */ - ucp_Cn = G_UNICODE_UNASSIGNED, /* Unassigned */ - ucp_Co = G_UNICODE_PRIVATE_USE, /* Private use */ - ucp_Cs = G_UNICODE_SURROGATE, /* Surrogate */ - ucp_Ll = G_UNICODE_LOWERCASE_LETTER, /* Lower case letter */ - ucp_Lm = G_UNICODE_MODIFIER_LETTER, /* Modifier letter */ - ucp_Lo = G_UNICODE_OTHER_LETTER, /* Other letter */ - ucp_Lt = G_UNICODE_TITLECASE_LETTER, /* Title case letter */ - ucp_Lu = G_UNICODE_UPPERCASE_LETTER, /* Upper case letter */ - ucp_Mc = G_UNICODE_SPACING_MARK, /* Spacing mark */ - ucp_Me = G_UNICODE_ENCLOSING_MARK, /* Enclosing mark */ - ucp_Mn = G_UNICODE_NON_SPACING_MARK, /* Non-spacing mark */ - ucp_Nd = G_UNICODE_DECIMAL_NUMBER, /* Decimal number */ - ucp_Nl = G_UNICODE_LETTER_NUMBER, /* Letter number */ - ucp_No = G_UNICODE_OTHER_NUMBER, /* Other number */ - ucp_Pc = G_UNICODE_CONNECT_PUNCTUATION, /* Connector punctuation */ - ucp_Pd = G_UNICODE_DASH_PUNCTUATION, /* Dash punctuation */ - ucp_Pe = G_UNICODE_CLOSE_PUNCTUATION, /* Close punctuation */ - ucp_Pf = G_UNICODE_FINAL_PUNCTUATION, /* Final punctuation */ - ucp_Pi = G_UNICODE_INITIAL_PUNCTUATION, /* Initial punctuation */ - ucp_Po = G_UNICODE_OTHER_PUNCTUATION, /* Other punctuation */ - ucp_Ps = G_UNICODE_OPEN_PUNCTUATION, /* Open punctuation */ - ucp_Sc = G_UNICODE_CURRENCY_SYMBOL, /* Currency symbol */ - ucp_Sk = G_UNICODE_MODIFIER_SYMBOL, /* Modifier symbol */ - ucp_Sm = G_UNICODE_MATH_SYMBOL, /* Mathematical symbol */ - ucp_So = G_UNICODE_OTHER_SYMBOL, /* Other symbol */ - ucp_Zl = G_UNICODE_LINE_SEPARATOR, /* Line separator */ - ucp_Zp = G_UNICODE_PARAGRAPH_SEPARATOR, /* Paragraph separator */ - ucp_Zs = G_UNICODE_SPACE_SEPARATOR /* Space separator */ -}; - -/* These are the script identifications. */ - -enum { - ucp_Common = G_UNICODE_SCRIPT_COMMON, - ucp_Inherited = G_UNICODE_SCRIPT_INHERITED, - - ucp_Arabic = G_UNICODE_SCRIPT_ARABIC, - ucp_Armenian = G_UNICODE_SCRIPT_ARMENIAN, - ucp_Bengali = G_UNICODE_SCRIPT_BENGALI, - ucp_Bopomofo = G_UNICODE_SCRIPT_BOPOMOFO, - ucp_Braille = G_UNICODE_SCRIPT_BRAILLE, - ucp_Buginese = G_UNICODE_SCRIPT_BUGINESE, - ucp_Buhid = G_UNICODE_SCRIPT_BUHID, - ucp_Canadian_Aboriginal = G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL, - ucp_Cherokee = G_UNICODE_SCRIPT_CHEROKEE, - ucp_Coptic = G_UNICODE_SCRIPT_COPTIC, - ucp_Cypriot = G_UNICODE_SCRIPT_CYPRIOT, - ucp_Cyrillic = G_UNICODE_SCRIPT_CYRILLIC, - ucp_Deseret = G_UNICODE_SCRIPT_DESERET, - ucp_Devanagari = G_UNICODE_SCRIPT_DEVANAGARI, - ucp_Ethiopic = G_UNICODE_SCRIPT_ETHIOPIC, - ucp_Georgian = G_UNICODE_SCRIPT_GEORGIAN, - ucp_Glagolitic = G_UNICODE_SCRIPT_GLAGOLITIC, - ucp_Gothic = G_UNICODE_SCRIPT_GOTHIC, - ucp_Greek = G_UNICODE_SCRIPT_GREEK, - ucp_Gujarati = G_UNICODE_SCRIPT_GUJARATI, - ucp_Gurmukhi = G_UNICODE_SCRIPT_GURMUKHI, - ucp_Han = G_UNICODE_SCRIPT_HAN, - ucp_Hangul = G_UNICODE_SCRIPT_HANGUL, - ucp_Hanunoo = G_UNICODE_SCRIPT_HANUNOO, - ucp_Hebrew = G_UNICODE_SCRIPT_HEBREW, - ucp_Hiragana = G_UNICODE_SCRIPT_HIRAGANA, - ucp_Kannada = G_UNICODE_SCRIPT_KANNADA, - ucp_Katakana = G_UNICODE_SCRIPT_KATAKANA, - ucp_Kharoshthi = G_UNICODE_SCRIPT_KHAROSHTHI, - ucp_Khmer = G_UNICODE_SCRIPT_KHMER, - ucp_Lao = G_UNICODE_SCRIPT_LAO, - ucp_Latin = G_UNICODE_SCRIPT_LATIN, - ucp_Limbu = G_UNICODE_SCRIPT_LIMBU, - ucp_Linear_B = G_UNICODE_SCRIPT_LINEAR_B, - ucp_Malayalam = G_UNICODE_SCRIPT_MALAYALAM, - ucp_Mongolian = G_UNICODE_SCRIPT_MONGOLIAN, - ucp_Myanmar = G_UNICODE_SCRIPT_MYANMAR, - ucp_New_Tai_Lue = G_UNICODE_SCRIPT_NEW_TAI_LUE, - ucp_Ogham = G_UNICODE_SCRIPT_OGHAM, - ucp_Old_Italic = G_UNICODE_SCRIPT_OLD_ITALIC, - ucp_Old_Persian = G_UNICODE_SCRIPT_OLD_PERSIAN, - ucp_Oriya = G_UNICODE_SCRIPT_ORIYA, - ucp_Osmanya = G_UNICODE_SCRIPT_OSMANYA, - ucp_Runic = G_UNICODE_SCRIPT_RUNIC, - ucp_Shavian = G_UNICODE_SCRIPT_SHAVIAN, - ucp_Sinhala = G_UNICODE_SCRIPT_SINHALA, - ucp_Syloti_Nagri = G_UNICODE_SCRIPT_SYLOTI_NAGRI, - ucp_Syriac = G_UNICODE_SCRIPT_SYRIAC, - ucp_Tagalog = G_UNICODE_SCRIPT_TAGALOG, - ucp_Tagbanwa = G_UNICODE_SCRIPT_TAGBANWA, - ucp_Tai_Le = G_UNICODE_SCRIPT_TAI_LE, - ucp_Tamil = G_UNICODE_SCRIPT_TAMIL, - ucp_Telugu = G_UNICODE_SCRIPT_TELUGU, - ucp_Thaana = G_UNICODE_SCRIPT_THAANA, - ucp_Thai = G_UNICODE_SCRIPT_THAI, - ucp_Tibetan = G_UNICODE_SCRIPT_TIBETAN, - ucp_Tifinagh = G_UNICODE_SCRIPT_TIFINAGH, - ucp_Ugaritic = G_UNICODE_SCRIPT_UGARITIC, - ucp_Yi = G_UNICODE_SCRIPT_YI, - /* New for Unicode 5.0: */ - ucp_Balinese = G_UNICODE_SCRIPT_BALINESE, - ucp_Cuneiform = G_UNICODE_SCRIPT_CUNEIFORM, - ucp_Nko = G_UNICODE_SCRIPT_NKO, - ucp_Phags_Pa = G_UNICODE_SCRIPT_PHAGS_PA, - ucp_Phoenician = G_UNICODE_SCRIPT_PHOENICIAN, - /* New for Unicode 5.1: */ - ucp_Carian = G_UNICODE_SCRIPT_CARIAN, - ucp_Cham = G_UNICODE_SCRIPT_CHAM, - ucp_Kayah_Li = G_UNICODE_SCRIPT_KAYAH_LI, - ucp_Lepcha = G_UNICODE_SCRIPT_LEPCHA, - ucp_Lycian = G_UNICODE_SCRIPT_LYCIAN, - ucp_Lydian = G_UNICODE_SCRIPT_LYDIAN, - ucp_Ol_Chiki = G_UNICODE_SCRIPT_OL_CHIKI, - ucp_Rejang = G_UNICODE_SCRIPT_REJANG, - ucp_Saurashtra = G_UNICODE_SCRIPT_SAURASHTRA, - ucp_Sundanese = G_UNICODE_SCRIPT_SUNDANESE, - ucp_Vai = G_UNICODE_SCRIPT_VAI, - /* New for Unicode 5.2: */ - ucp_Avestan = G_UNICODE_SCRIPT_AVESTAN, - ucp_Bamum = G_UNICODE_SCRIPT_BAMUM, - ucp_Egyptian_Hieroglyphs = G_UNICODE_SCRIPT_EGYPTIAN_HIEROGLYPHS, - ucp_Imperial_Aramaic = G_UNICODE_SCRIPT_IMPERIAL_ARAMAIC, - ucp_Inscriptional_Pahlavi = G_UNICODE_SCRIPT_INSCRIPTIONAL_PAHLAVI, - ucp_Inscriptional_Parthian = G_UNICODE_SCRIPT_INSCRIPTIONAL_PARTHIAN, - ucp_Javanese = G_UNICODE_SCRIPT_JAVANESE, - ucp_Kaithi = G_UNICODE_SCRIPT_KAITHI, - ucp_Lisu = G_UNICODE_SCRIPT_LISU, - ucp_Meetei_Mayek = G_UNICODE_SCRIPT_MEETEI_MAYEK, - ucp_Old_South_Arabian = G_UNICODE_SCRIPT_OLD_SOUTH_ARABIAN, - ucp_Old_Turkic = G_UNICODE_SCRIPT_OLD_TURKIC, - ucp_Samaritan = G_UNICODE_SCRIPT_SAMARITAN, - ucp_Tai_Tham = G_UNICODE_SCRIPT_TAI_THAM, - ucp_Tai_Viet = G_UNICODE_SCRIPT_TAI_VIET, - /* New for Unicode 6.0.0: */ - ucp_Batak = G_UNICODE_SCRIPT_BATAK, - ucp_Brahmi = G_UNICODE_SCRIPT_BRAHMI, - ucp_Mandaic = G_UNICODE_SCRIPT_MANDAIC, - /* New for Unicode 6.1.0: */ - ucp_Chakma = G_UNICODE_SCRIPT_CHAKMA, - ucp_Meroitic_Cursive = G_UNICODE_SCRIPT_MEROITIC_CURSIVE, - ucp_Meroitic_Hieroglyphs = G_UNICODE_SCRIPT_MEROITIC_HIEROGLYPHS, - ucp_Miao = G_UNICODE_SCRIPT_MIAO, - ucp_Sharada = G_UNICODE_SCRIPT_SHARADA, - ucp_Sora_Sompeng = G_UNICODE_SCRIPT_SORA_SOMPENG, - ucp_Takri = G_UNICODE_SCRIPT_TAKRI, -}; - -#endif - -/* End of ucp.h */ diff --git a/glib/tests/642026.c b/glib/tests/642026.c index 26ab2ed06..aface4ea0 100644 --- a/glib/tests/642026.c +++ b/glib/tests/642026.c @@ -51,7 +51,7 @@ static gpointer thread_func (gpointer nil) static void testcase (void) { - g_test_bug ("642026"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=642026"); mutex = g_mutex_new (); cond = g_cond_new (); @@ -86,7 +86,6 @@ main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugzilla.gnome.org/show_bug.cgi?id="); g_test_add_func ("/glib/642026", testcase); diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c index fef63f672..471f6171d 100644 --- a/glib/tests/array-test.c +++ b/glib/tests/array-test.c @@ -1991,8 +1991,6 @@ main (int argc, char *argv[]) g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugzilla.gnome.org/"); - /* array tests */ g_test_add_func ("/array/new/zero-terminated", array_new_zero_terminated); g_test_add_func ("/array/ref-count", array_ref_count); diff --git a/glib/tests/atomic.c b/glib/tests/atomic.c index 14e6e454e..8bc100f4e 100644 --- a/glib/tests/atomic.c +++ b/glib/tests/atomic.c @@ -97,9 +97,12 @@ test_types (void) /* Note that atomic variables should almost certainly not be marked as * `volatile` — see http://isvolatileusefulwiththreads.in/c/. This test exists * to make sure that we don’t warn when built against older third party code. */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wincompatible-pointer-types" g_atomic_pointer_set (&vp_str_vol, NULL); res = g_atomic_pointer_compare_and_exchange (&vp_str_vol, NULL, str); g_assert_true (res); +#pragma GCC diagnostic pop g_atomic_pointer_set (&ip, 0); ip2 = g_atomic_pointer_get (&ip); @@ -112,7 +115,7 @@ test_types (void) vp2 = (gpointer) g_atomic_pointer_get (&gs); gs2 = (gsize) vp2; g_assert_cmpuint (gs2, ==, 0); - res = g_atomic_pointer_compare_and_exchange (&gs, NULL, NULL); + res = g_atomic_pointer_compare_and_exchange (&gs, NULL, (gsize) NULL); g_assert_true (res); g_assert_cmpuint (gs, ==, 0); gs2 = (gsize) g_atomic_pointer_add (&gs, 5); @@ -129,7 +132,7 @@ test_types (void) g_assert_cmpuint (gs, ==, 8); g_assert_cmpint (g_atomic_int_get (csp), ==, s); - g_assert_true (g_atomic_pointer_get (cspp) == csp); + g_assert_true (g_atomic_pointer_get ((const gint **) cspp) == csp); /* repeat, without the macros */ #undef g_atomic_int_set diff --git a/glib/tests/base64.c b/glib/tests/base64.c index bf32ac629..93b1b1dd0 100644 --- a/glib/tests/base64.c +++ b/glib/tests/base64.c @@ -247,7 +247,7 @@ test_base64_encode_incremental_small_block (gconstpointer block_size_p) gsize i; struct MyRawData myraw; - g_test_bug ("780066"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=780066"); generate_databuffer_for_base64 (&myraw); @@ -492,7 +492,6 @@ main (int argc, char *argv[]) gint i; g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugzilla.gnome.org/browse.cgi?product="); for (i = 0; i < DATA_SIZE; i++) data[i] = (guchar)i; diff --git a/glib/tests/bookmarkfile.c b/glib/tests/bookmarkfile.c index bc1a7a213..1700ad8b8 100644 --- a/glib/tests/bookmarkfile.c +++ b/glib/tests/bookmarkfile.c @@ -1,6 +1,7 @@ #undef G_DISABLE_ASSERT #include <glib.h> +#include <glib/gstdio.h> #include <time.h> #include <locale.h> #include <string.h> @@ -44,19 +45,25 @@ test_to_file (void) gboolean res; GError *error = NULL; char *in, *out; + gchar *tmp_filename = NULL; + gint fd; + + fd = g_file_open_tmp ("bookmarkfile-test-XXXXXX.xbel", &tmp_filename, NULL); + g_assert_cmpint (fd, >, -1); + g_close (fd, NULL); bookmark = g_bookmark_file_new (); - g_test_message ("Roundtrip from newly created bookmark file"); + g_test_message ("Roundtrip from newly created bookmark file %s", tmp_filename); g_bookmark_file_set_title (bookmark, "file:///tmp/schedule.ps", "schedule.ps"); g_bookmark_file_set_mime_type (bookmark, "file:///tmp/schedule.ps", "application/postscript"); g_bookmark_file_add_application (bookmark, "file:///tmp/schedule.ps", "ghostscript", "ghostscript %F"); - res = g_bookmark_file_to_file (bookmark, "out.xbel", &error); + res = g_bookmark_file_to_file (bookmark, tmp_filename, &error); g_assert_no_error (error); g_assert_true (res); - res = g_bookmark_file_load_from_file (bookmark, "out.xbel", &error); + res = g_bookmark_file_load_from_file (bookmark, tmp_filename, &error); g_assert_no_error (error); g_assert_true (res); @@ -70,7 +77,7 @@ test_to_file (void) g_assert_cmpstr (out, ==, "application/postscript"); g_free (out); - remove ("out.xbel"); + remove (tmp_filename); g_test_message ("Roundtrip from a valid bookmark file"); filename = g_test_get_filename (G_TEST_DIST, "bookmarks", "valid-01.xbel", NULL); @@ -78,7 +85,7 @@ test_to_file (void) g_assert_no_error (error); g_assert_true (res); - res = g_bookmark_file_to_file (bookmark, "out.xbel", &error); + res = g_bookmark_file_to_file (bookmark, tmp_filename, &error); g_assert_no_error (error); g_assert_true (res); @@ -86,16 +93,17 @@ test_to_file (void) g_assert_no_error (error); g_assert_true (res); - res = g_file_get_contents ("out.xbel", &out, NULL, &error); + res = g_file_get_contents (tmp_filename, &out, NULL, &error); g_assert_no_error (error); g_assert_true (res); - remove ("out.xbel"); + remove (tmp_filename); g_assert_cmpstr (in, ==, out); g_free (in); g_free (out); g_bookmark_file_free (bookmark); + g_free (tmp_filename); } static void diff --git a/glib/tests/bytes.c b/glib/tests/bytes.c index cbc4d699c..8178bc2a8 100644 --- a/glib/tests/bytes.c +++ b/glib/tests/bytes.c @@ -38,8 +38,8 @@ test_new (void) data = "test"; bytes = g_bytes_new (data, 4); - g_assert (bytes != NULL); - g_assert (g_bytes_get_data (bytes, &size) != data); + g_assert_nonnull (bytes); + g_assert_true (g_bytes_get_data (bytes, &size) != data); g_assert_cmpuint (size, ==, 4); g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4); g_assert_cmpmem (data, 4, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes)); @@ -56,8 +56,8 @@ test_new_take (void) data = g_strdup ("test"); bytes = g_bytes_new_take (data, 4); - g_assert (bytes != NULL); - g_assert (g_bytes_get_data (bytes, &size) == data); + g_assert_nonnull (bytes); + g_assert_true (g_bytes_get_data (bytes, &size) == data); g_assert_cmpuint (size, ==, 4); g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4); @@ -73,8 +73,8 @@ test_new_static (void) data = "test"; bytes = g_bytes_new_static (data, 4); - g_assert (bytes != NULL); - g_assert (g_bytes_get_data (bytes, &size) == data); + g_assert_nonnull (bytes); + g_assert_true (g_bytes_get_data (bytes, &size) == data); g_assert_cmpuint (size, ==, 4); g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4); @@ -91,8 +91,8 @@ test_new_from_bytes (void) bytes = g_bytes_new (data, 14); sub = g_bytes_new_from_bytes (bytes, 10, 4); - g_assert (sub != NULL); - g_assert (g_bytes_get_data (sub, NULL) == ((gchar *)g_bytes_get_data (bytes, NULL)) + 10); + g_assert_nonnull (sub); + g_assert_true (g_bytes_get_data (sub, NULL) == ((gchar *)g_bytes_get_data (bytes, NULL)) + 10); g_bytes_unref (bytes); g_assert_cmpmem (g_bytes_get_data (sub, NULL), g_bytes_get_size (sub), "wave", 4); @@ -116,9 +116,9 @@ test_new_from_bytes_slice (void) g_assert_cmpint (bytes3->ref_count, ==, 1); g_assert_null (bytes->user_data); - g_assert (bytes1->user_data == bytes); - g_assert (bytes2->user_data == bytes); - g_assert (bytes3->user_data == bytes); + g_assert_true (bytes1->user_data == bytes); + g_assert_true (bytes2->user_data == bytes); + g_assert_true (bytes3->user_data == bytes); g_assert_cmpint (17, ==, g_bytes_get_size (bytes)); g_assert_cmpint (13, ==, g_bytes_get_size (bytes1)); @@ -145,7 +145,7 @@ test_new_from_bytes_shared_ref (void) GBytes *bytes = g_bytes_new_static ("Some data", strlen ("Some data") + 1); GBytes *other = g_bytes_new_from_bytes (bytes, 0, g_bytes_get_size (bytes)); - g_assert (bytes == other); + g_assert_true (bytes == other); g_assert_cmpint (bytes->ref_count, ==, 2); g_bytes_unref (bytes); @@ -156,7 +156,7 @@ static void on_destroy_increment (gpointer data) { gint *count = data; - g_assert (count != NULL); + g_assert_nonnull (count); (*count)++; } @@ -170,9 +170,9 @@ test_new_with_free_func (void) data = "test"; bytes = g_bytes_new_with_free_func (data, 4, on_destroy_increment, &count); - g_assert (bytes != NULL); + g_assert_nonnull (bytes); g_assert_cmpint (count, ==, 0); - g_assert (g_bytes_get_data (bytes, &size) == data); + g_assert_true (g_bytes_get_data (bytes, &size) == data); g_assert_cmpuint (size, ==, 4); g_assert_cmpuint (g_bytes_get_size (bytes), ==, 4); @@ -193,7 +193,7 @@ test_hash (void) hash1 = g_bytes_hash (bytes1); hash2 = g_bytes_hash (bytes2); - g_assert (hash1 == hash2); + g_assert_cmpuint (hash1, ==, hash2); g_bytes_unref (bytes1); g_bytes_unref (bytes2); @@ -208,18 +208,18 @@ test_equal (void) bytes = g_bytes_new ("blah", 4); bytes2 = g_bytes_new ("blah", 4); - g_assert (g_bytes_equal (bytes, bytes2)); - g_assert (g_bytes_equal (bytes2, bytes)); + g_assert_true (g_bytes_equal (bytes, bytes2)); + g_assert_true (g_bytes_equal (bytes2, bytes)); g_bytes_unref (bytes2); bytes2 = g_bytes_new ("bla", 3); - g_assert (!g_bytes_equal (bytes, bytes2)); - g_assert (!g_bytes_equal (bytes2, bytes)); + g_assert_false (g_bytes_equal (bytes, bytes2)); + g_assert_false (g_bytes_equal (bytes2, bytes)); g_bytes_unref (bytes2); bytes2 = g_bytes_new ("true", 4); - g_assert (!g_bytes_equal (bytes, bytes2)); - g_assert (!g_bytes_equal (bytes2, bytes)); + g_assert_false (g_bytes_equal (bytes, bytes2)); + g_assert_false (g_bytes_equal (bytes2, bytes)); g_bytes_unref (bytes2); g_bytes_unref (bytes); @@ -272,7 +272,7 @@ test_to_data_transferred (void) bytes = g_bytes_new (NYAN, N_NYAN); memory = g_bytes_get_data (bytes, NULL); data = g_bytes_unref_to_data (bytes, &size); - g_assert (data == memory); + g_assert_true (data == memory); g_assert_cmpmem (data, size, NYAN, N_NYAN); g_free (data); } @@ -290,10 +290,10 @@ test_to_data_two_refs (void) bytes = g_bytes_ref (bytes); memory = g_bytes_get_data (bytes, NULL); data = g_bytes_unref_to_data (bytes, &size); - g_assert (data != memory); + g_assert_true (data != memory); g_assert_cmpmem (data, size, NYAN, N_NYAN); g_free (data); - g_assert (g_bytes_get_data (bytes, &size) == memory); + g_assert_true (g_bytes_get_data (bytes, &size) == memory); g_assert_cmpuint (size, ==, N_NYAN); g_assert_cmpuint (g_bytes_get_size (bytes), ==, N_NYAN); g_bytes_unref (bytes); @@ -308,14 +308,38 @@ test_to_data_non_malloc (void) /* Memory copied: non malloc memory */ bytes = g_bytes_new_static (NYAN, N_NYAN); - g_assert (g_bytes_get_data (bytes, NULL) == NYAN); + g_assert_true (g_bytes_get_data (bytes, NULL) == NYAN); data = g_bytes_unref_to_data (bytes, &size); - g_assert (data != (gpointer)NYAN); + g_assert_true (data != (gpointer)NYAN); g_assert_cmpmem (data, size, NYAN, N_NYAN); g_free (data); } static void +test_to_data_different_free_func (void) +{ + gpointer data; + gsize size; + GBytes *bytes; + gchar *sentinel = g_strdup ("hello"); + + /* Memory copied: free func and user_data don’t point to the bytes data */ + bytes = g_bytes_new_with_free_func (NYAN, N_NYAN, g_free, sentinel); + g_assert_true (g_bytes_get_data (bytes, NULL) == NYAN); + + data = g_bytes_unref_to_data (bytes, &size); + g_assert_true (data != (gpointer)NYAN); + g_assert_cmpmem (data, size, NYAN, N_NYAN); + g_free (data); + + /* @sentinel should not be leaked; testing that requires this test to be run + * under valgrind. We can’t use a custom free func to check it isn’t leaked, + * as the point of this test is to hit a condition in `try_steal_and_unref()` + * which is short-circuited if the free func isn’t g_free(). + * See discussion in https://gitlab.gnome.org/GNOME/glib/-/merge_requests/2152 */ +} + +static void test_to_array_transferred (void) { gconstpointer memory; @@ -326,8 +350,8 @@ test_to_array_transferred (void) bytes = g_bytes_new (NYAN, N_NYAN); memory = g_bytes_get_data (bytes, NULL); array = g_bytes_unref_to_array (bytes); - g_assert (array != NULL); - g_assert (array->data == memory); + g_assert_nonnull (array); + g_assert_true (array->data == memory); g_assert_cmpmem (array->data, array->len, NYAN, N_NYAN); g_byte_array_unref (array); } @@ -377,11 +401,11 @@ test_to_array_two_refs (void) bytes = g_bytes_ref (bytes); memory = g_bytes_get_data (bytes, NULL); array = g_bytes_unref_to_array (bytes); - g_assert (array != NULL); - g_assert (array->data != memory); + g_assert_nonnull (array); + g_assert_true (array->data != memory); g_assert_cmpmem (array->data, array->len, NYAN, N_NYAN); g_byte_array_unref (array); - g_assert (g_bytes_get_data (bytes, &size) == memory); + g_assert_true (g_bytes_get_data (bytes, &size) == memory); g_assert_cmpuint (size, ==, N_NYAN); g_assert_cmpuint (g_bytes_get_size (bytes), ==, N_NYAN); g_bytes_unref (bytes); @@ -395,10 +419,10 @@ test_to_array_non_malloc (void) /* Memory copied: non malloc memory */ bytes = g_bytes_new_static (NYAN, N_NYAN); - g_assert (g_bytes_get_data (bytes, NULL) == NYAN); + g_assert_true (g_bytes_get_data (bytes, NULL) == NYAN); array = g_bytes_unref_to_array (bytes); - g_assert (array != NULL); - g_assert (array->data != (gpointer)NYAN); + g_assert_nonnull (array); + g_assert_true (array->data != (gpointer)NYAN); g_assert_cmpmem (array->data, array->len, NYAN, N_NYAN); g_byte_array_unref (array); } @@ -414,8 +438,47 @@ test_null (void) data = g_bytes_unref_to_data (bytes, &size); - g_assert (data == NULL); - g_assert (size == 0); + g_assert_null (data); + g_assert_cmpuint (size, ==, 0); +} + +static void +test_get_region (void) +{ + GBytes *bytes; + + bytes = g_bytes_new_static (NYAN, N_NYAN); + + /* simple valid gets at the start */ + g_assert_true (g_bytes_get_region (bytes, 1, 0, 1) == NYAN); + g_assert_true (g_bytes_get_region (bytes, 1, 0, N_NYAN) == NYAN); + + /* an invalid get because the range is too wide */ + g_assert_true (g_bytes_get_region (bytes, 1, 0, N_NYAN + 1) == NULL); + + /* an valid get, but of a zero-byte range at the end */ + g_assert_true (g_bytes_get_region (bytes, 1, N_NYAN, 0) == NYAN + N_NYAN); + + /* not a valid get because it overlap ones byte */ + g_assert_true (g_bytes_get_region (bytes, 1, N_NYAN, 1) == NULL); + + /* let's try some multiplication overflow now */ + g_assert_true (g_bytes_get_region (bytes, 32, 0, G_MAXSIZE / 32 + 1) == NULL); + g_assert_true (g_bytes_get_region (bytes, G_MAXSIZE / 32 + 1, 0, 32) == NULL); + + /* and some addition overflow */ + g_assert_true (g_bytes_get_region (bytes, 1, G_MAXSIZE, -G_MAXSIZE) == NULL); + g_assert_true (g_bytes_get_region (bytes, 1, G_MAXSSIZE, ((gsize) G_MAXSSIZE) + 1) == NULL); + g_assert_true (g_bytes_get_region (bytes, 1, G_MAXSIZE, 1) == NULL); + + g_bytes_unref (bytes); +} + +static void +test_unref_null (void) +{ + g_test_summary ("Test that calling g_bytes_unref() on NULL is a no-op"); + g_bytes_unref (NULL); } int @@ -423,8 +486,6 @@ main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://bugzilla.gnome.org/"); - g_test_add_func ("/bytes/new", test_new); g_test_add_func ("/bytes/new-take", test_new_take); g_test_add_func ("/bytes/new-static", test_new_static); @@ -438,11 +499,14 @@ main (int argc, char *argv[]) g_test_add_func ("/bytes/to-data/transferred", test_to_data_transferred); g_test_add_func ("/bytes/to-data/two-refs", test_to_data_two_refs); g_test_add_func ("/bytes/to-data/non-malloc", test_to_data_non_malloc); + g_test_add_func ("/bytes/to-data/different-free-func", test_to_data_different_free_func); g_test_add_func ("/bytes/to-array/transferred", test_to_array_transferred); g_test_add_func ("/bytes/to-array/transferred/oversize", test_to_array_transferred_oversize); g_test_add_func ("/bytes/to-array/two-refs", test_to_array_two_refs); g_test_add_func ("/bytes/to-array/non-malloc", test_to_array_non_malloc); g_test_add_func ("/bytes/null", test_null); + g_test_add_func ("/bytes/get-region", test_get_region); + g_test_add_func ("/bytes/unref-null", test_unref_null); return g_test_run (); } diff --git a/glib/tests/charset.c b/glib/tests/charset.c index 363eedfd1..53f12ec72 100644 --- a/glib/tests/charset.c +++ b/glib/tests/charset.c @@ -76,8 +76,6 @@ main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugs.gnome.org/"); - g_test_add_func ("/charset/language_names_with_category", test_language_names_with_category); g_test_add_func ("/charset/language_names_with_category_async", test_language_names_with_category_async); diff --git a/glib/tests/cond.c b/glib/tests/cond.c index ed338cce3..bcd8fbd8c 100644 --- a/glib/tests/cond.c +++ b/glib/tests/cond.c @@ -324,8 +324,7 @@ test_wait_until_errno (void) act.sa_handler = signal_handler; g_test_summary ("Check proper handling of errno in g_cond_wait_until with a contended mutex"); - g_test_bug_base ("https://gitlab.gnome.org/GNOME/glib/"); - g_test_bug ("merge_requests/957"); + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/merge_requests/957"); g_mutex_init (&lock); g_cond_init (&cond); diff --git a/glib/tests/date.c b/glib/tests/date.c index 542293c4b..5c60ffcba 100644 --- a/glib/tests/date.c +++ b/glib/tests/date.c @@ -242,7 +242,7 @@ test_month_substring (void) { GDate date; - g_test_bug ("793550"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=793550"); if (setlocale (LC_ALL, "pl_PL") == NULL) { @@ -282,7 +282,7 @@ test_month_names (void) #endif #endif /* defined(HAVE_LANGINFO_ABALTMON) || defined(G_OS_WIN32) */ - g_test_bug ("749206"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=749206"); /* If running uninstalled (G_TEST_BUILDDIR is set), skip this test, since we * need the translations to be installed. We can’t mess around with @@ -789,7 +789,6 @@ main (int argc, char** argv) #endif g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ("/date/basic", test_basic); g_test_add_func ("/date/empty", test_empty_constructor); diff --git a/glib/tests/error.c b/glib/tests/error.c index 48f480222..51a0c35dc 100644 --- a/glib/tests/error.c +++ b/glib/tests/error.c @@ -70,6 +70,27 @@ test_prefix (void) } static void +test_prefix_literal (void) +{ + GError *error = NULL; + + g_prefix_error_literal (NULL, "foo: "); + + g_prefix_error_literal (&error, "foo: "); + g_assert_null (error); + + error = NULL; + g_prefix_error_literal (&error, "foo: "); + g_assert_null (error); + + error = g_error_new_literal (G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY, "bla"); + g_assert_nonnull (error); + g_prefix_error_literal (&error, "foo: "); + g_assert_cmpstr (error->message, ==, "foo: bla"); + g_error_free (error); +} + +static void test_literal (void) { GError *error; @@ -374,6 +395,7 @@ main (int argc, char *argv[]) g_test_add_func ("/error/overwrite", test_overwrite); g_test_add_func ("/error/prefix", test_prefix); + g_test_add_func ("/error/prefix-literal", test_prefix_literal); g_test_add_func ("/error/literal", test_literal); g_test_add_func ("/error/copy", test_copy); g_test_add_func ("/error/matches", test_matches); diff --git a/glib/tests/fileutils.c b/glib/tests/fileutils.c index 76ba9086d..a3c1c33d0 100644 --- a/glib/tests/fileutils.c +++ b/glib/tests/fileutils.c @@ -1439,7 +1439,7 @@ test_fopen_modes (void) "ab+" }; - g_test_bug ("119"); + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/merge_requests/119"); if (g_file_test (path, G_FILE_TEST_EXISTS)) g_error ("failed, %s exists, cannot test g_fopen()", path); @@ -1826,8 +1826,6 @@ main (int argc, g_setenv ("LC_ALL", "C", TRUE); g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL); - g_test_bug_base ("https://gitlab.gnome.org/GNOME/glib/merge_requests/"); - #ifdef G_OS_WIN32 g_test_add_func ("/fileutils/stdio-win32-pathstrip", test_win32_pathstrip); g_test_add_func ("/fileutils/stdio-win32-zero-terminate-symlink", test_win32_zero_terminate_symlink); diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c index bc4eba93a..12f332b44 100644 --- a/glib/tests/gdatetime.c +++ b/glib/tests/gdatetime.c @@ -2318,6 +2318,116 @@ test_format_iso8601 (void) g_time_zone_unref (tz); } +typedef struct +{ + gboolean utf8_messages; + gboolean utf8_time; +} MixedUtf8TestData; + +static const MixedUtf8TestData utf8_time_non_utf8_messages = { + .utf8_messages = FALSE, + .utf8_time = TRUE +}; + +static const MixedUtf8TestData non_utf8_time_utf8_messages = { + .utf8_messages = TRUE, + .utf8_time = FALSE +}; + +static const MixedUtf8TestData utf8_time_utf8_messages = { + .utf8_messages = TRUE, + .utf8_time = TRUE +}; + +static const MixedUtf8TestData non_utf8_time_non_utf8_messages = { + .utf8_messages = FALSE, + .utf8_time = FALSE +}; + +static gboolean +check_and_set_locale (int category, + const gchar *name) +{ + setlocale (category, name); + if (strstr (setlocale (category, NULL), name) == NULL) + { + g_print ("Unavaible '%s' locale\n", name); + g_test_skip ("required locale not available, skipping tests"); + return FALSE; + } + return TRUE; +} + +static void +test_format_time_mixed_utf8 (gconstpointer data) +{ + const MixedUtf8TestData *test_data; + gchar *old_time_locale; + gchar *old_messages_locale; + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2055"); + + test_data = (MixedUtf8TestData *) data; + old_time_locale = g_strdup (setlocale (LC_TIME, NULL)); + old_messages_locale = g_strdup (setlocale (LC_MESSAGES, NULL)); + if (test_data->utf8_time) + { + if (!check_and_set_locale (LC_TIME, "C.UTF-8")) + { + g_free (old_time_locale); + setlocale (LC_MESSAGES, old_messages_locale); + g_free (old_messages_locale); + return; + } + } + else + { + if (!check_and_set_locale (LC_TIME, "de_DE.iso88591")) + { + g_free (old_time_locale); + setlocale (LC_MESSAGES, old_messages_locale); + g_free (old_messages_locale); + return; + } + } + if (test_data->utf8_messages) + { + if (!check_and_set_locale (LC_MESSAGES, "C.UTF-8")) + { + g_free (old_messages_locale); + setlocale (LC_TIME, old_time_locale); + g_free (old_time_locale); + return; + } + } + else + { + if (!check_and_set_locale (LC_MESSAGES, "de_DE.iso88591")) + { + g_free (old_messages_locale); + setlocale (LC_TIME, old_time_locale); + g_free (old_time_locale); + return; + } + } + + if (!test_data->utf8_time) + { + /* March to have März in german */ + TEST_PRINTF_DATE (2020, 3, 1, "%b", "Mär"); + TEST_PRINTF_DATE (2020, 3, 1, "%B", "März"); + } + else + { + TEST_PRINTF_DATE (2020, 3, 1, "%b", "mar"); + TEST_PRINTF_DATE (2020, 3, 1, "%B", "march"); + } + + setlocale (LC_TIME, old_time_locale); + setlocale (LC_MESSAGES, old_messages_locale); + g_free (old_time_locale); + g_free (old_messages_locale); +} + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-y2k" static void @@ -2980,6 +3090,18 @@ main (gint argc, g_test_add_func ("/GDateTime/non_utf8_printf", test_non_utf8_printf); g_test_add_func ("/GDateTime/format_unrepresentable", test_format_unrepresentable); g_test_add_func ("/GDateTime/format_iso8601", test_format_iso8601); + g_test_add_data_func ("/GDateTime/format_mixed/utf8_time_non_utf8_messages", + &utf8_time_non_utf8_messages, + test_format_time_mixed_utf8); + g_test_add_data_func ("/GDateTime/format_mixed/utf8_time_utf8_messages", + &utf8_time_utf8_messages, + test_format_time_mixed_utf8); + g_test_add_data_func ("/GDateTime/format_mixed/non_utf8_time_non_utf8_messages", + &non_utf8_time_non_utf8_messages, + test_format_time_mixed_utf8); + g_test_add_data_func ("/GDateTime/format_mixed/non_utf8_time_utf8_messages", + &non_utf8_time_utf8_messages, + test_format_time_mixed_utf8); g_test_add_func ("/GDateTime/strftime", test_strftime); g_test_add_func ("/GDateTime/strftime/error_handling", test_GDateTime_strftime_error_handling); g_test_add_func ("/GDateTime/modifiers", test_modifiers); diff --git a/glib/tests/gutils-user-database.c b/glib/tests/gutils-user-database.c index aef599a7b..89a0e0b0f 100644 --- a/glib/tests/gutils-user-database.c +++ b/glib/tests/gutils-user-database.c @@ -35,7 +35,6 @@ int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://gitlab.gnome.org/GNOME/glib/issues"); g_test_add_func ("/gutils/get_user_database_entry", test_get_user_database_entry); diff --git a/glib/tests/guuid.c b/glib/tests/guuid.c index 41e2c81e9..bfe27955b 100644 --- a/glib/tests/guuid.c +++ b/glib/tests/guuid.c @@ -61,7 +61,6 @@ int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); /* GUuid Tests */ g_test_add_func ("/uuid/string", test_guuid_string); diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c index 35434cae9..0110f2664 100644 --- a/glib/tests/gvariant.c +++ b/glib/tests/gvariant.c @@ -997,7 +997,7 @@ check_offsets (GVariantTypeInfo *info, position++; /* and store the offset, just like it would be in the - * serialised data. + * serialized data. */ last_offset = position; last_offset_index++; @@ -1093,7 +1093,7 @@ test_gvarianttypeinfo (void) #define MAX_TUPLE_CHILDREN 128 /* this function generates a random type such that all characteristics - * that are "interesting" to the serialiser are tested. + * that are "interesting" to the serializer are tested. * * this basically means: * - test different alignments @@ -2311,19 +2311,19 @@ test_serialiser_children (void) g_test_summary ("Test that getting a child variant before and after " "serialisation of the parent works"); - /* Construct a variable sized array containing a child which serialises to a + /* Construct a variable sized array containing a child which serializes to a * zero-length bytestring. */ child = g_variant_new_maybe (G_VARIANT_TYPE_VARIANT, NULL); variant = g_variant_new_array (mv_type, &child, 1); - /* Get the child before serialising. */ + /* Get the child before serializing. */ child1 = g_variant_get_child_value (variant, 0); data1 = g_variant_get_data_as_bytes (child1); - /* Serialise the parent variant. */ + /* Serialize the parent variant. */ g_variant_get_data (variant); - /* Get the child again after serialising — this uses a different code path. */ + /* Get the child again after serializing — this uses a different code path. */ child2 = g_variant_get_child_value (variant, 0); data2 = g_variant_get_data_as_bytes (child2); @@ -2348,7 +2348,7 @@ test_fuzz (gdouble *fuzziness) /* make an instance */ tree = tree_instance_new (NULL, 3); - /* serialise it */ + /* serialize it */ serialise_tree (tree, &serialised); g_assert_true (g_variant_serialised_is_normal (serialised)); @@ -2371,17 +2371,17 @@ test_fuzz (gdouble *fuzziness) } } - /* at least one byte in the serialised data has changed. + /* at least one byte in the serialized data has changed. * * this means that at least one of the following is true: * - * - the serialised data now represents a different value: + * - the serialized data now represents a different value: * check_tree() will return FALSE * - * - the serialised data is in non-normal form: + * - the serialized data is in non-normal form: * g_variant_serialiser_is_normal() will return FALSE * - * we always do both checks to increase exposure of the serialiser + * we always do both checks to increase exposure of the serializer * to corrupt data. */ a = g_variant_serialised_is_normal (serialised); @@ -3743,9 +3743,9 @@ test_gv_byteswap (void) # define swapped16(x) x, 0 #endif /* all kinds of of crazy randomised testing already performed on the - * byteswapper in the /gvariant/serialiser/byteswap test and all kinds - * of crazy randomised testing performed against the serialiser - * normalisation functions in the /gvariant/serialiser/fuzz/ tests. + * byteswapper in the /gvariant/serializer/byteswap test and all kinds + * of crazy randomised testing performed against the serializer + * normalisation functions in the /gvariant/serializer/fuzz/ tests. * * just test a few simple cases here to make sure they each work */ @@ -4755,7 +4755,7 @@ test_gbytes (void) g_bytes_unref (bytes2); tuple = g_variant_new_parsed ("['foo', 'bar']"); - bytes = g_variant_get_data_as_bytes (tuple); /* force serialisation */ + bytes = g_variant_get_data_as_bytes (tuple); /* force serialization */ a = g_variant_get_child_value (tuple, 1); bytes2 = g_variant_get_data_as_bytes (a); g_assert_false (g_bytes_equal (bytes, bytes2)); @@ -4898,7 +4898,7 @@ test_normal_checking_tuples (void) } /* Check that deeply nested variants are not considered in normal form when - * deserialised from untrusted data.*/ + * deserialized from untrusted data.*/ static void test_recursion_limits_variant_in_variant (void) { @@ -4914,7 +4914,7 @@ test_recursion_limits_variant_in_variant (void) for (i = 0; i < G_VARIANT_MAX_RECURSION_DEPTH - 1; i++) wrapper_variant = g_variant_new_variant (g_steal_pointer (&wrapper_variant)); - /* Serialise and deserialise it as untrusted data, to force normalisation. */ + /* Serialize and deserialize it as untrusted data, to force normalisation. */ bytes = g_variant_get_data_as_bytes (wrapper_variant); deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT, bytes, FALSE); @@ -4935,7 +4935,7 @@ test_recursion_limits_variant_in_variant (void) g_variant_unref (deserialised_variant); - /* Deserialise it again, but trusted this time. This should succeed. */ + /* Deserialize it again, but trusted this time. This should succeed. */ deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT, bytes, TRUE); g_assert_nonnull (deserialised_variant); @@ -4947,7 +4947,7 @@ test_recursion_limits_variant_in_variant (void) } /* Check that deeply nested arrays are not considered in normal form when - * deserialised from untrusted data after being wrapped in a variant. This is + * deserialized from untrusted data after being wrapped in a variant. This is * worth testing, because neither the deeply nested array, nor the variant, * have a static #GVariantType which is too deep — only when nested together do * they become too deep. */ @@ -4967,7 +4967,7 @@ test_recursion_limits_array_in_variant (void) for (i = 0; i < G_VARIANT_MAX_RECURSION_DEPTH - 1; i++) child_variant = g_variant_new_array (NULL, &child_variant, 1); - /* Serialise and deserialise it as untrusted data, to force normalisation. */ + /* Serialize and deserialize it as untrusted data, to force normalisation. */ bytes = g_variant_get_data_as_bytes (child_variant); deserialised_variant = g_variant_new_from_bytes (g_variant_get_type (child_variant), bytes, FALSE); @@ -4988,7 +4988,7 @@ test_recursion_limits_array_in_variant (void) g_variant_unref (deserialised_variant); - /* Deserialise it again, but trusted this time. This should succeed. */ + /* Deserialize it again, but trusted this time. This should succeed. */ deserialised_variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT, bytes, TRUE); g_assert_nonnull (deserialised_variant); @@ -5122,7 +5122,6 @@ main (int argc, char **argv) guint i; g_test_init (&argc, &argv, NULL); - g_test_bug_base (""); g_test_add_func ("/gvariant/type", test_gvarianttype); g_test_add_func ("/gvariant/type/string-scan/recursion/tuple", diff --git a/glib/tests/hash.c b/glib/tests/hash.c index f4ff55ce1..fe72606f8 100644 --- a/glib/tests/hash.c +++ b/glib/tests/hash.c @@ -759,7 +759,7 @@ test_lookup_null_key (void) gpointer key; gpointer value; - g_test_bug ("642944"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=642944"); h = g_hash_table_new (null_safe_str_hash, null_safe_str_equal); g_hash_table_insert (h, "abc", "ABC"); @@ -1012,7 +1012,7 @@ test_destroy_modify (void) FakeFreeData *ffd; guint i; - g_test_bug ("650459"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=650459"); fake_free_data = g_ptr_array_new (); @@ -1518,7 +1518,7 @@ test_iter_replace (void) gpointer k, v; gchar *s; - g_test_bug ("662544"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=662544"); h = g_hash_table_new_full (g_str_hash, g_str_equal, my_key_free, my_value_free); @@ -1555,7 +1555,7 @@ test_set_insert_corruption (void) gchar b[] = "foo"; gpointer key, value; - g_test_bug ("692815"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=692815"); g_hash_table_insert (hash_table, a, a); g_assert (g_hash_table_contains (hash_table, "foo")); @@ -1664,8 +1664,6 @@ main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); - g_test_add_func ("/hash/misc", test_hash_misc); g_test_add_data_func ("/hash/one", GINT_TO_POINTER (TRUE), second_hash_test); g_test_add_data_func ("/hash/honeyman", GINT_TO_POINTER (FALSE), second_hash_test); diff --git a/glib/tests/keyfile.c b/glib/tests/keyfile.c index 975ef8167..1f5be8b38 100644 --- a/glib/tests/keyfile.c +++ b/glib/tests/keyfile.c @@ -897,7 +897,7 @@ test_group_remove (void) "key1=bla\n" "key2=bla\n"; - g_test_bug ("165887"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=165887"); keyfile = load_data (data, 0); @@ -952,7 +952,7 @@ test_key_remove (void) "key1=bla\n" "key2=bla\n"; - g_test_bug ("165980"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=165980"); keyfile = load_data (data, 0); @@ -986,7 +986,7 @@ test_groups (void) "[2]\n" "key2=123\n"; - g_test_bug ("316309"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=316309"); keyfile = load_data (data, 0); @@ -1267,7 +1267,7 @@ test_duplicate_groups (void) "[Desktop Entry]\n" "key2=123\n"; - g_test_bug ("157877"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=157877"); keyfile = load_data (data, 0); check_string_value (keyfile, "Desktop Entry", "key1", "123"); @@ -1288,7 +1288,7 @@ test_duplicate_groups2 (void) "[A]\n" "foo=bang\n"; - g_test_bug ("385910"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=385910"); keyfile = load_data (data, 0); check_string_value (keyfile, "A", "foo", "bang"); @@ -1324,7 +1324,7 @@ test_reload_idempotency (void) gchar *data1, *data2; gsize len1, len2; - g_test_bug ("420686"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=420686"); /* check that we only insert a single new line between groups */ keyfile = g_key_file_new (); @@ -1371,7 +1371,7 @@ test_int64 (void) gint64 d; gchar *value; - g_test_bug ("614864"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=614864"); file = g_key_file_new (); @@ -1552,7 +1552,7 @@ test_page_boundary (void) #define LAST_KEY 99 #define VALUE 92 - g_test_bug ("640695"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=640695"); file = g_key_file_new (); @@ -1823,8 +1823,6 @@ main (int argc, char *argv[]) g_setenv ("XDG_DATA_HOME", g_test_get_dir (G_TEST_DIST), TRUE); #endif - g_test_bug_base ("http://bugzilla.gnome.org/"); - g_test_add_func ("/keyfile/line-ends", test_line_ends); g_test_add_func ("/keyfile/whitespace", test_whitespace); g_test_add_func ("/keyfile/comments", test_comments); diff --git a/glib/tests/logging.c b/glib/tests/logging.c index 096fe4467..e246cdf5b 100644 --- a/glib/tests/logging.c +++ b/glib/tests/logging.c @@ -340,7 +340,7 @@ test_handler (const gchar *log_domain, static void bug653052 (void) { - g_test_bug ("653052"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=653052"); g_test_log_set_fatal_handler (good_failure_handler, fail_str); g_log_set_default_handler (test_handler, log_str); @@ -637,7 +637,6 @@ main (int argc, char *argv[]) g_unsetenv ("G_MESSAGES_DEBUG"); g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ("/logging/default-handler", test_default_handler); g_test_add_func ("/logging/default-handler/subprocess/error", test_default_handler_error); diff --git a/glib/tests/mainloop.c b/glib/tests/mainloop.c index d43b2cf08..77e21f548 100644 --- a/glib/tests/mainloop.c +++ b/glib/tests/mainloop.c @@ -21,6 +21,7 @@ */ #include <glib.h> +#include <glib/gstdio.h> #include "glib-private.h" #include <stdio.h> #include <string.h> @@ -686,7 +687,7 @@ test_blocked_child_sources (void) GMainLoop *loop; GSource *source; - g_test_bug ("701283"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=701283"); ctx = g_main_context_new (); loop = g_main_loop_new (ctx, FALSE); @@ -885,7 +886,7 @@ test_mainloop_overflow (void) TestOverflowData data; guint i; - g_test_bug ("687098"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=687098"); memset (&data, 0, sizeof (data)); @@ -2066,13 +2067,42 @@ test_maincontext_source_finalization_from_dispatch (gconstpointer user_data) g_main_context_unref (c); } +static void +test_steal_fd (void) +{ + GError *error = NULL; + gchar *tmpfile = NULL; + int fd = -42; + int borrowed; + int stolen; + + g_assert_cmpint (g_steal_fd (&fd), ==, -42); + g_assert_cmpint (fd, ==, -1); + g_assert_cmpint (g_steal_fd (&fd), ==, -1); + g_assert_cmpint (fd, ==, -1); + + fd = g_file_open_tmp (NULL, &tmpfile, &error); + g_assert_cmpint (fd, >=, 0); + g_assert_no_error (error); + borrowed = fd; + stolen = g_steal_fd (&fd); + g_assert_cmpint (fd, ==, -1); + g_assert_cmpint (borrowed, ==, stolen); + + g_close (g_steal_fd (&stolen), &error); + g_assert_no_error (error); + g_assert_cmpint (stolen, ==, -1); + + g_assert_no_errno (remove (tmpfile)); + g_free (tmpfile); +} + int main (int argc, char *argv[]) { gint i; g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ("/maincontext/basic", test_maincontext_basic); g_test_add_func ("/maincontext/source_finalization", test_maincontext_source_finalization); @@ -2111,6 +2141,7 @@ main (int argc, char *argv[]) g_test_add_func ("/mainloop/unix-fd-priority", test_unix_fd_priority); #endif g_test_add_func ("/mainloop/nfds", test_nfds); + g_test_add_func ("/mainloop/steal-fd", test_steal_fd); return g_test_run (); } diff --git a/glib/tests/mem-overflow.c b/glib/tests/mem-overflow.c index 61225b763..1654ab7fc 100644 --- a/glib/tests/mem-overflow.c +++ b/glib/tests/mem-overflow.c @@ -191,7 +191,7 @@ empty_alloc_subprocess (void) static void empty_alloc (void) { - g_test_bug ("615379"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=615379"); g_assert_cmpint (sizeof (Empty), ==, 0); @@ -210,8 +210,6 @@ main (int argc, { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); - g_test_add_func ("/mem/overflow", mem_overflow); g_test_add_func ("/mem/overflow/subprocess/malloc_n_a_a", mem_overflow_malloc_n_a_a); g_test_add_func ("/mem/overflow/subprocess/malloc_n_a_b", mem_overflow_malloc_n_a_b); diff --git a/glib/tests/once.c b/glib/tests/once.c index 8fc8d5014..ea521c05b 100644 --- a/glib/tests/once.c +++ b/glib/tests/once.c @@ -192,7 +192,7 @@ test_once_init_multi_threaded (void) static void test_once_init_string (void) { - static const gchar *val; + static gchar *val; g_test_summary ("Test g_once_init_{enter,leave}() usage with a string"); diff --git a/glib/tests/option-argv0.c b/glib/tests/option-argv0.c index ce3609743..37ac44a9f 100644 --- a/glib/tests/option-argv0.c +++ b/glib/tests/option-argv0.c @@ -35,7 +35,7 @@ test_platform_argv0 (void) gboolean arg; GOptionEntry entries [] = { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; const gchar * const expected_prgnames[] = { "option-argv0", diff --git a/glib/tests/option-context.c b/glib/tests/option-context.c index 13d3ffc76..d4ed3a94f 100644 --- a/glib/tests/option-context.c +++ b/glib/tests/option-context.c @@ -28,37 +28,19 @@ #include <locale.h> #include <math.h> -#ifdef _MSC_VER -# ifndef NAN -/* - * From the Visual Studio 2013+ math.h, we have the following: - * #ifndef _HUGE_ENUF - * #define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow - * #endif - * - * #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) - * ... - * #define NAN ((float)(INFINITY * 0.0F)) - * ... - * so, HUVE_VAL * HUGE_VAL would be a good approximation of INFINITY without - * defining anything extra - */ -# define NAN HUGE_VAL * HUGE_VAL * 0.0f -# endif -#endif static GOptionEntry main_entries[] = { { "main-switch", 0, 0, G_OPTION_ARG_NONE, NULL, "A switch that is in the main group", NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; static GOptionEntry group_entries[] = { { "test-switch", 0, 0, G_OPTION_ARG_NONE, NULL, "A switch that is in the test group", NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; static GOptionContext * @@ -134,7 +116,7 @@ test_group_captions (void) guint i; gsize j; - g_test_bug ("504142"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=504142"); for (i = 0; i < 4; ++i) { @@ -334,7 +316,7 @@ error_test1 (void) GOptionGroup *main_group; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_INT, &error_test1_int, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; error_test1_int = 0x12345678; @@ -402,7 +384,7 @@ error_test2 (void) GOptionGroup *main_group; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_STRING, &error_test2_string, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; error_test2_string = "foo"; @@ -468,7 +450,7 @@ error_test3 (void) GOptionGroup *main_group; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_NONE, &error_test3_boolean, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; error_test3_boolean = FALSE; @@ -508,7 +490,7 @@ arg_test1 (void) int argc; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_INT, &arg_test1_int, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -543,7 +525,7 @@ arg_test2 (void) int argc; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_STRING, &arg_test2_string, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -577,7 +559,7 @@ arg_test3 (void) int argc; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_FILENAME, &arg_test3_filename, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -611,7 +593,7 @@ arg_test4 (void) int argc; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &arg_test4_double, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -645,7 +627,7 @@ arg_test5 (void) const char *locale = "de_DE.UTF-8"; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &arg_test5_double, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -692,7 +674,7 @@ arg_test6 (void) GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_INT64, &arg_test6_int64, NULL, NULL }, { "test2", 0, 0, G_OPTION_ARG_INT64, &arg_test6_int64_2, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -733,7 +715,7 @@ callback_test1 (void) int argc; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_CALLBACK, callback_parse1, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -774,7 +756,7 @@ callback_test2 (void) int argc; GOptionEntry entries [] = { { "test", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, callback_parse2, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -818,7 +800,7 @@ callback_test_optional_1 (void) GOptionEntry entries [] = { { "test", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_parse_optional, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -854,7 +836,7 @@ callback_test_optional_2 (void) GOptionEntry entries [] = { { "test", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_parse_optional, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -890,7 +872,7 @@ callback_test_optional_3 (void) GOptionEntry entries [] = { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_parse_optional, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -927,7 +909,7 @@ callback_test_optional_4 (void) GOptionEntry entries [] = { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_parse_optional, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -965,7 +947,7 @@ callback_test_optional_5 (void) { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL, NULL }, { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_parse_optional, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -1003,7 +985,7 @@ callback_test_optional_6 (void) { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL, NULL }, { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_parse_optional, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -1041,7 +1023,7 @@ callback_test_optional_7 (void) { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL, NULL }, { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_parse_optional, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -1079,7 +1061,7 @@ callback_test_optional_8 (void) { { "dummy", 'd', 0, G_OPTION_ARG_NONE, &dummy, NULL, NULL }, { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_parse_optional, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -1123,7 +1105,7 @@ callback_remaining_test1 (void) int argc; GOptionEntry entries [] = { { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_CALLBACK, callback_remaining_test1_callback, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; callback_remaining_args = g_ptr_array_new (); context = g_option_context_new (NULL); @@ -1170,7 +1152,7 @@ callback_returns_false (void) { { "error", 0, 0, G_OPTION_ARG_CALLBACK, callback_error, NULL, NULL }, { "error-no-arg", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, callback_error, NULL, NULL }, { "error-optional-arg", 0, G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, callback_error, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -1253,7 +1235,7 @@ ignore_test1 (void) gchar *arg; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_set_ignore_unknown_options (context, TRUE); @@ -1289,7 +1271,7 @@ ignore_test2 (void) gchar *arg; GOptionEntry entries [] = { { "test", 't', 0, G_OPTION_ARG_NONE, &ignore_test2_boolean, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_set_ignore_unknown_options (context, TRUE); @@ -1324,7 +1306,7 @@ ignore_test3 (void) gchar *arg; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_STRING, &ignore_test3_string, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_set_ignore_unknown_options (context, TRUE); @@ -1362,7 +1344,7 @@ array_test1 (void) int argc; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -1394,10 +1376,10 @@ add_test1 (void) GOptionEntry entries1 [] = { { "test1", 0, 0, G_OPTION_ARG_STRING_ARRAY, NULL, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; GOptionEntry entries2 [] = { { "test2", 0, 0, G_OPTION_ARG_STRING_ARRAY, NULL, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries1, NULL); @@ -1445,7 +1427,7 @@ rest_test1 (void) int argc; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); @@ -1483,7 +1465,7 @@ rest_test2 (void) int argc; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); @@ -1522,7 +1504,7 @@ rest_test2a (void) int argc; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); @@ -1559,7 +1541,7 @@ rest_test2b (void) int argc; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); @@ -1597,7 +1579,7 @@ rest_test2c (void) int argc; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); @@ -1634,7 +1616,7 @@ rest_test2d (void) int argc; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); @@ -1674,7 +1656,7 @@ rest_test3 (void) GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); @@ -1715,7 +1697,7 @@ rest_test4 (void) GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &array_test1_array, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); @@ -1755,7 +1737,7 @@ rest_test5 (void) GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_NONE, &ignore_test1_boolean, NULL, NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &array_test1_array, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); @@ -1791,9 +1773,9 @@ unknown_short_test (void) gchar **argv; gchar **argv_copy; int argc; - GOptionEntry entries [] = { { NULL } }; + GOptionEntry entries [] = { G_OPTION_ENTRY_NULL }; - g_test_bug ("166609"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=166609"); context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -1823,7 +1805,7 @@ lonely_dash_test (void) gchar **argv_copy; int argc; - g_test_bug ("168008"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=168008"); context = g_option_context_new (NULL); @@ -1856,11 +1838,11 @@ triple_dash_test (void) gint arg1, arg2; GOptionEntry entries [] = { { "foo", 0, 0, G_OPTION_ARG_INT, &arg1, NULL, NULL}, - { NULL } + G_OPTION_ENTRY_NULL }; GOptionEntry group_entries [] = { { "test", 0, 0, G_OPTION_ARG_INT, &arg2, NULL, NULL}, - { NULL } + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); @@ -1897,9 +1879,9 @@ missing_arg_test (void) gchar *arg = NULL; GOptionEntry entries [] = { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; - g_test_bug ("305576"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=305576"); context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -1963,9 +1945,9 @@ dash_arg_test (void) GOptionEntry entries [] = { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK, cb, NULL, NULL }, { "three", '3', 0, G_OPTION_ARG_NONE, &argb, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; - g_test_bug ("577638"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=577638"); context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -2008,7 +1990,7 @@ test_basic (void) gchar *arg = NULL; GOptionEntry entries [] = { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -2069,7 +2051,7 @@ test_translate (void) gchar *arg = NULL; GOptionEntry entries [] = { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; TranslateData data = { 0, }; gchar *str; @@ -2103,12 +2085,12 @@ test_help (void) { "test2", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, NULL, "Tests also", NULL }, { "frob", 0, 0, G_OPTION_ARG_NONE, NULL, "Main frob", NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &sarr, "Rest goes here", "REST" }, - { NULL } + G_OPTION_ENTRY_NULL }; GOptionEntry group_entries[] = { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, "Group test", "Group test arg" }, { "frob", 0, G_OPTION_FLAG_NOALIAS, G_OPTION_ARG_NONE, NULL, "Group frob", NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; context = g_option_context_new ("blabla"); @@ -2152,7 +2134,7 @@ test_help_no_options (void) gchar **sarr = NULL; GOptionEntry entries[] = { { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &sarr, "Rest goes here", "REST" }, - { NULL } + G_OPTION_ENTRY_NULL }; gchar *str; @@ -2182,15 +2164,15 @@ test_help_no_help_options (void) { "test2", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, NULL, "Tests also", NULL }, { "frob", 0, 0, G_OPTION_ARG_NONE, NULL, "Main frob", NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &sarr, "Rest goes here", "REST" }, - { NULL } + G_OPTION_ENTRY_NULL }; GOptionEntry group_entries[] = { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, "Group test", "Group test arg" }, { "frob", 0, G_OPTION_FLAG_NOALIAS, G_OPTION_ARG_NONE, NULL, "Group frob", NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; - g_test_bug ("697652"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=697652"); context = g_option_context_new ("blabla"); g_option_context_add_main_entries (context, entries, NULL); @@ -2278,7 +2260,7 @@ test_error_hook (void) gchar *arg = NULL; GOptionEntry entries [] = { { "test", 't', 0, G_OPTION_ARG_STRING, &arg, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; GOptionGroup *group; gchar **argv; gchar **argv_copy; @@ -2323,13 +2305,13 @@ test_group_parse (void) GOptionEntry entries[] = { { "test", 't', 0, G_OPTION_ARG_STRING, &arg1, NULL, NULL }, { "faz", 'f', 0, G_OPTION_ARG_STRING, &arg2, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; GOptionEntry group_entries[] = { { "test", 0, 0, G_OPTION_ARG_STRING, &arg3, NULL, NULL }, { "frob", 'f', 0, G_OPTION_ARG_STRING, &arg4, NULL, NULL }, { "faz", 'z', 0, G_OPTION_ARG_STRING, &arg5, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; gchar **argv, **orig_argv; gint argc; @@ -2393,7 +2375,7 @@ test_strict_posix (void) GOptionEntry entries[] = { { "foo", 'f', 0, G_OPTION_ARG_NONE, &foo, NULL, NULL }, { "bar", 'b', 0, G_OPTION_ARG_NONE, &bar, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; gint n_parsed; @@ -2438,7 +2420,7 @@ flag_reverse_string (void) gchar *arg = NULL; GOptionEntry entries [] = { { "test", 't', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_STRING, &arg, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; gchar **argv; gint argc; gboolean retval; @@ -2471,7 +2453,7 @@ flag_optional_int (void) gint arg = 0; GOptionEntry entries [] = { { "test", 't', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &arg, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; gchar **argv; gint argc; gboolean retval; @@ -2512,13 +2494,13 @@ short_remaining (void) { "number", 'n', 0, G_OPTION_ARG_INT, &number, NULL, NULL }, { "text", 't', 0, G_OPTION_ARG_STRING, &text, NULL, NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &files, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; GOptionContext* context; gchar **argv, **argv_copy; gint argc; - g_test_bug ("729563"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=729563"); argv = split_string ("program -ri -n 4 -t hello file1 file2", &argc); argv_copy = copy_stringv (argv, argc); @@ -2553,14 +2535,14 @@ double_free (void) GOptionEntry entries[] = { { "known", 0, 0, G_OPTION_ARG_STRING, &text, NULL, NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; GOptionContext* context; gchar **argv; gint argc; GError *error = NULL; - g_test_bug ("646926"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=646926"); argv = split_string ("program --known=foo --known=bar --unknown=baz", &argc); @@ -2591,7 +2573,7 @@ double_zero (void) double test_val = NAN; GOptionEntry entries [] = { { "test", 0, 0, G_OPTION_ARG_DOUBLE, &test_val, NULL, NULL }, - { NULL } }; + G_OPTION_ENTRY_NULL }; context = g_option_context_new (NULL); g_option_context_add_main_entries (context, entries, NULL); @@ -2622,8 +2604,6 @@ main (int argc, g_setenv ("LC_ALL", "C", TRUE); g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); - g_test_add_func ("/option/help/options", test_help); g_test_add_func ("/option/help/no-options", test_help_no_options); g_test_add_func ("/option/help/no-help-options", test_help_no_help_options); diff --git a/glib/tests/pattern.c b/glib/tests/pattern.c index 70553a882..ecc27db26 100644 --- a/glib/tests/pattern.c +++ b/glib/tests/pattern.c @@ -51,12 +51,12 @@ struct _CompileTest guint min; }; -static CompileTest compile_tests[] = -{ +static CompileTest compile_tests[] = { { "*A?B*", G_MATCH_ALL, "*A?B*", 3 }, { "ABC*DEFGH", G_MATCH_ALL_TAIL, "HGFED*CBA", 8 }, { "ABCDEF*GH", G_MATCH_ALL, "ABCDEF*GH", 8 }, { "ABC**?***??**DEF*GH", G_MATCH_ALL, "ABC*???DEF*GH", 11 }, + { "**ABC***?🤌DEF**", G_MATCH_ALL, "*ABC*?🤌DEF*", 11 }, { "*A?AA", G_MATCH_ALL_TAIL, "AA?A*", 4 }, { "ABCD*", G_MATCH_HEAD, "ABCD", 4 }, { "*ABCD", G_MATCH_TAIL, "ABCD", 4 }, @@ -84,6 +84,24 @@ test_compilation (gconstpointer d) g_pattern_spec_free (spec); } +static void +test_copy (gconstpointer d) +{ + const CompileTest *test = d; + GPatternSpec *p1, *p2; + + p1 = g_pattern_spec_new (test->src); + p2 = g_pattern_spec_copy (p1); + + g_assert_cmpint (p2->match_type, ==, test->match_type); + g_assert_cmpstr (p2->pattern, ==, test->pattern); + g_assert_cmpint (p2->pattern_length, ==, strlen (p1->pattern)); + g_assert_cmpint (p2->min_length, ==, test->min); + + g_pattern_spec_free (p1); + g_pattern_spec_free (p2); +} + typedef struct _MatchTest MatchTest; struct _MatchTest @@ -158,10 +176,16 @@ test_match (gconstpointer d) g_assert_cmpint (g_pattern_match_simple (test->pattern, test->string), ==, test->match); p = g_pattern_spec_new (test->pattern); + g_assert_cmpint (g_pattern_spec_match_string (p, test->string), ==, test->match); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_assert_cmpint (g_pattern_match_string (p, test->string), ==, test->match); + G_GNUC_END_IGNORE_DEPRECATIONS r = g_utf8_strreverse (test->string, -1); + g_assert_cmpint (g_pattern_spec_match (p, strlen (test->string), test->string, r), ==, test->match); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS g_assert_cmpint (g_pattern_match (p, strlen (test->string), test->string, r), ==, test->match); + G_GNUC_END_IGNORE_DEPRECATIONS g_free (r); g_pattern_spec_free (p); @@ -222,6 +246,13 @@ main (int argc, char** argv) g_free (path); } + for (i = 0; i < G_N_ELEMENTS (compile_tests); i++) + { + path = g_strdup_printf ("/pattern/copy/%" G_GSIZE_FORMAT, i); + g_test_add_data_func (path, &compile_tests[i], test_copy); + g_free (path); + } + for (i = 0; i < G_N_ELEMENTS (match_tests); i++) { path = g_strdup_printf ("/pattern/match/%" G_GSIZE_FORMAT, i); diff --git a/glib/tests/rand.c b/glib/tests/rand.c index 94fb4e822..37f4ddd41 100644 --- a/glib/tests/rand.c +++ b/glib/tests/rand.c @@ -160,7 +160,7 @@ test_double_range (void) { gdouble d; - g_test_bug ("502560"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=502560"); d = g_random_double_range (-G_MAXDOUBLE, G_MAXDOUBLE); @@ -173,7 +173,6 @@ main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ("/rand/test-rand", test_rand); g_test_add_func ("/rand/double-range", test_double_range); diff --git a/glib/tests/regex.c b/glib/tests/regex.c index c57bd8cdc..88d12edf6 100644 --- a/glib/tests/regex.c +++ b/glib/tests/regex.c @@ -25,11 +25,7 @@ #include <locale.h> #include "glib.h" -#ifdef USE_SYSTEM_PCRE #include <pcre.h> -#else -#include "glib/pcre/pcre.h" -#endif /* U+20AC EURO SIGN (symbol, currency) */ #define EURO "\xe2\x82\xac" @@ -2124,7 +2120,7 @@ test_multiline (void) GMatchInfo *info; gint count; - g_test_bug ("640489"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=640489"); regex = g_regex_new ("^a$", G_REGEX_MULTILINE|G_REGEX_DOTALL, 0, NULL); @@ -2194,8 +2190,6 @@ main (int argc, char *argv[]) g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); - g_test_add_func ("/regex/properties", test_properties); g_test_add_func ("/regex/class", test_class); g_test_add_func ("/regex/lookahead", test_lookahead); @@ -2559,13 +2553,16 @@ main (int argc, char *argv[]) TEST_SUB_PATTERN("(a)?(b)", "b", 0, 0, "b", 0, 1); TEST_SUB_PATTERN("(a)?(b)", "b", 0, 1, "", -1, -1); TEST_SUB_PATTERN("(a)?(b)", "b", 0, 2, "b", 0, 1); + TEST_SUB_PATTERN("(a)?b", "b", 0, 0, "b", 0, 1); + TEST_SUB_PATTERN("(a)?b", "b", 0, 1, "", -1, -1); + TEST_SUB_PATTERN("(a)?b", "b", 0, 2, NULL, UNTOUCHED, UNTOUCHED); /* TEST_NAMED_SUB_PATTERN(pattern, string, start_position, sub_name, * expected_sub, expected_start, expected_end) */ TEST_NAMED_SUB_PATTERN("a(?P<A>.)(?P<B>.)?", "ab", 0, "A", "b", 1, 2); TEST_NAMED_SUB_PATTERN("a(?P<A>.)(?P<B>.)?", "aab", 1, "A", "b", 2, 3); TEST_NAMED_SUB_PATTERN("a(?P<A>.)(?P<B>.)?", EURO "ab", 0, "A", "b", 4, 5); - TEST_NAMED_SUB_PATTERN("a(?P<A>.)(?P<B>.)?", EURO "ab", 0, "B", NULL, UNTOUCHED, UNTOUCHED); + TEST_NAMED_SUB_PATTERN("a(?P<A>.)(?P<B>.)?", EURO "ab", 0, "B", "", -1, -1); TEST_NAMED_SUB_PATTERN("a(?P<A>.)(?P<B>.)?", EURO "ab", 0, "C", NULL, UNTOUCHED, UNTOUCHED); TEST_NAMED_SUB_PATTERN("a(?P<A>.)(?P<B>.)?", "a" EGRAVE "x", 0, "A", EGRAVE, 1, 3); TEST_NAMED_SUB_PATTERN("a(?P<A>.)(?P<B>.)?", "a" EGRAVE "x", 0, "B", "x", 3, 4); @@ -2677,7 +2674,7 @@ main (int argc, char *argv[]) TEST_EXPAND("a", "a", "\\0130", FALSE, "X"); TEST_EXPAND("a", "a", "\\\\\\0", FALSE, "\\a"); TEST_EXPAND("a(?P<G>.)c", "xabcy", "X\\g<G>X", FALSE, "XbX"); -#ifndef USE_SYSTEM_PCRE +#if !(PCRE_MAJOR > 8 || (PCRE_MAJOR == 8 && PCRE_MINOR >= 34)) /* PCRE >= 8.34 no longer allows this usage. */ TEST_EXPAND("(.)(?P<1>.)", "ab", "\\1", FALSE, "a"); TEST_EXPAND("(.)(?P<1>.)", "ab", "\\g<1>", FALSE, "a"); diff --git a/glib/tests/spawn-path-search-helper.c b/glib/tests/spawn-path-search-helper.c index 378c203c7..37be43b7f 100644 --- a/glib/tests/spawn-path-search-helper.c +++ b/glib/tests/spawn-path-search-helper.c @@ -79,7 +79,7 @@ main (int argc, { "slow-path", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &slow_path, "Use a child-setup function to avoid the posix_spawn fast path", NULL }, - { NULL } + G_OPTION_ENTRY_NULL }; GError *error = NULL; int ret = 1; diff --git a/glib/tests/spawn-singlethread.c b/glib/tests/spawn-singlethread.c index 51a1da514..6b17027fd 100644 --- a/glib/tests/spawn-singlethread.c +++ b/glib/tests/spawn-singlethread.c @@ -408,17 +408,17 @@ test_spawn_nonexistent (void) GError *error = NULL; GPtrArray *argv = NULL; gchar *stdout_str = NULL; - gint exit_status = -1; + gint wait_status = -1; argv = g_ptr_array_new (); g_ptr_array_add (argv, "this does not exist"); g_ptr_array_add (argv, NULL); g_spawn_sync (NULL, (char**) argv->pdata, NULL, 0, NULL, NULL, &stdout_str, - NULL, &exit_status, &error); + NULL, &wait_status, &error); g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT); g_assert_null (stdout_str); - g_assert_cmpint (exit_status, ==, -1); + g_assert_cmpint (wait_status, ==, -1); g_ptr_array_free (argv, TRUE); @@ -433,7 +433,7 @@ test_spawn_nonexistent (void) static void test_spawn_fd_assignment_clash (void) { -#ifdef G_OS_UNIX +#if defined(G_OS_UNIX) && defined(F_DUPFD_CLOEXEC) int tmp_fd; guint i; const guint n_fds = 10; @@ -487,7 +487,7 @@ test_spawn_fd_assignment_clash (void) for (i = 0; i < n_fds; i++) g_close (source_fds[i], NULL); #else /* !G_OS_UNIX */ - g_test_skip ("FD redirection only supported on Unix"); + g_test_skip ("FD redirection only supported on Unix with F_DUPFD_CLOEXEC"); #endif /* !G_OS_UNIX */ } diff --git a/glib/tests/string.c b/glib/tests/string.c index 24098d1be..6e22cd287 100644 --- a/glib/tests/string.c +++ b/glib/tests/string.c @@ -498,64 +498,30 @@ test_string_to_bytes (void) static void test_string_replace (void) { - static const struct - { - const char *string; - const char *original; - const char *replacement; - guint limit; - const char *expected; - guint expected_n; - } - tests[] = - { - { "foo bar foo baz foo bar foobarbaz", "bar", "baz", 0, - "foo baz foo baz foo baz foobazbaz", 3 }, - { "foo baz foo baz foo baz foobazbaz", "baz", "bar", 3, - "foo bar foo bar foo bar foobazbaz", 3 }, - { "foo bar foo bar foo bar foobazbaz", "foobar", "bar", 1, - "foo bar foo bar foo bar foobazbaz", 0 }, - { "aaaaaaaa", "a", "abcdefghijkl", 0, - "abcdefghijklabcdefghijklabcdefghijklabcdefghijklabcdefghijklabcdefghijklabcdefghijklabcdefghijkl", - 8 }, - { "/usr/$LIB/libMangoHud.so", "$LIB", "lib32", 0, - "/usr/lib32/libMangoHud.so", 1 }, - { "food for foals", "o", "", 0, - "fd fr fals", 4 }, - { "aaa", "a", "aaa", 0, - "aaaaaaaaa", 3 }, - { "aaa", "a", "", 0, - "", 3 }, - { "aaa", "aa", "bb", 0, - "bba", 1 }, - { "foo", "", "bar", 0, - "barfbarobarobar", 4 }, - { "", "", "x", 0, - "x", 1 }, - { "", "", "", 0, - "", 1 }, - }; - gsize i; - - for (i = 0; i < G_N_ELEMENTS (tests); i++) - { - GString *s; - guint n; - - s = g_string_new (tests[i].string); - g_test_message ("%" G_GSIZE_FORMAT ": Replacing \"%s\" with \"%s\" (limit %u) in \"%s\"", - i, tests[i].original, tests[i].replacement, - tests[i].limit, tests[i].string); - n = g_string_replace (s, tests[i].original, tests[i].replacement, - tests[i].limit); - g_test_message ("-> %u replacements, \"%s\"", - n, s->str); - g_assert_cmpstr (tests[i].expected, ==, s->str); - g_assert_cmpuint (strlen (tests[i].expected), ==, s->len); - g_assert_cmpuint (strlen (tests[i].expected) + 1, <=, s->allocated_len); - g_assert_cmpuint (tests[i].expected_n, ==, n); - g_string_free (s, TRUE); - } + GString *s; + gint n; + + s = g_string_new ("foo bar foo baz foo bar foobarbaz"); + + n = g_string_replace (s, "bar", "baz", 0); + g_assert_cmpstr ("foo baz foo baz foo baz foobazbaz", ==, s->str); + g_assert_cmpint (n, ==, 3); + + n = g_string_replace (s, "baz", "bar", 3); + g_assert_cmpstr ("foo bar foo bar foo bar foobazbaz", ==, s->str); + g_assert_cmpint (n, ==, 3); + + n = g_string_replace (s, "foobar", "bar", 1); + g_assert_cmpstr ("foo bar foo bar foo bar foobazbaz", ==, s->str); + g_assert_cmpint (n, ==, 0); + + s = g_string_assign (s, "aaaaaaaa"); + n = g_string_replace (s, "a", "abcdefghijkl", 0); + g_assert_cmpstr ("abcdefghijklabcdefghijklabcdefghijklabcdefghijklabcdefghijklabcdefghijklabcdefghijklabcdefghijkl", + ==, s->str); + g_assert_cmpint (n, ==, 8); + + g_string_free (s, TRUE); } int diff --git a/glib/tests/strvbuilder.c b/glib/tests/strvbuilder.c index 5f3b9329f..904af0e71 100644 --- a/glib/tests/strvbuilder.c +++ b/glib/tests/strvbuilder.c @@ -1,5 +1,6 @@ /* * Copyright © 2020 Canonical Ltd. + * Copyright © 2021 Alexandros Theodotou * * This work is provided "as is"; redistribution and modification * in whole or in part, in any medium, physical or electronic is @@ -56,6 +57,40 @@ test_strvbuilder_add (void) } static void +test_strvbuilder_addv (void) +{ + GStrvBuilder *builder; + GStrv result; + const gchar *expected[] = { "one", "two", "three", NULL }; + + builder = g_strv_builder_new (); + g_strv_builder_addv (builder, expected); + result = g_strv_builder_end (builder); + g_assert_nonnull (result); + g_assert_cmpstrv ((const gchar *const *) result, expected); + + g_strfreev (result); + g_strv_builder_unref (builder); +} + +static void +test_strvbuilder_add_many (void) +{ + GStrvBuilder *builder; + GStrv result; + const gchar *expected[] = { "one", "two", "three", NULL }; + + builder = g_strv_builder_new (); + g_strv_builder_add_many (builder, "one", "two", "three", NULL); + result = g_strv_builder_end (builder); + g_assert_nonnull (result); + g_assert_cmpstrv ((const gchar *const *) result, expected); + + g_strfreev (result); + g_strv_builder_unref (builder); +} + +static void test_strvbuilder_ref (void) { GStrvBuilder *builder; @@ -74,6 +109,8 @@ main (int argc, g_test_add_func ("/strvbuilder/empty", test_strvbuilder_empty); g_test_add_func ("/strvbuilder/add", test_strvbuilder_add); + g_test_add_func ("/strvbuilder/addv", test_strvbuilder_addv); + g_test_add_func ("/strvbuilder/add_many", test_strvbuilder_add_many); g_test_add_func ("/strvbuilder/ref", test_strvbuilder_ref); return g_test_run (); diff --git a/glib/tests/test-printf.c b/glib/tests/test-printf.c index dd1107432..59a461ddb 100644 --- a/glib/tests/test-printf.c +++ b/glib/tests/test-printf.c @@ -728,7 +728,7 @@ test_64bit (void) /* However, gcc doesn't know about this, so we need to disable printf * format warnings... */ -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#if G_GNUC_CHECK_VERSION(4, 6) _Pragma ("GCC diagnostic push") _Pragma ("GCC diagnostic ignored \"-Wformat\"") _Pragma ("GCC diagnostic ignored \"-Wformat-extra-args\"") @@ -766,7 +766,7 @@ _Pragma ("GCC diagnostic ignored \"-Wformat-extra-args\"") g_assert_cmpint (res, ==, 5); g_assert_cmpstr (buf, ==, "1E240"); -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#if G_GNUC_CHECK_VERSION(4, 6) _Pragma ("GCC diagnostic pop") #endif @@ -819,7 +819,7 @@ test_64bit2_win32 (void) /* However, gcc doesn't know about this, so we need to disable printf * format warnings... */ -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#if G_GNUC_CHECK_VERSION(4, 6) _Pragma ("GCC diagnostic push") _Pragma ("GCC diagnostic ignored \"-Wformat\"") _Pragma ("GCC diagnostic ignored \"-Wformat-extra-args\"") @@ -849,7 +849,7 @@ _Pragma ("GCC diagnostic ignored \"-Wformat-extra-args\"") res = g_printf ("%" "ll" "X\n", (gint64)123456); g_assert_cmpint (res, ==, 6); -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#if G_GNUC_CHECK_VERSION(4, 6) _Pragma ("GCC diagnostic pop") #endif } diff --git a/glib/tests/testing.c b/glib/tests/testing.c index 7faa7b5ec..81b8f5405 100644 --- a/glib/tests/testing.c +++ b/glib/tests/testing.c @@ -878,7 +878,7 @@ test_combining (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_error (error, G_SPAWN_EXIT_ERROR, 77); g_clear_error (&error); @@ -900,7 +900,7 @@ test_combining (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_error (error, G_SPAWN_EXIT_ERROR, 77); g_clear_error (&error); @@ -918,7 +918,7 @@ test_combining (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_error (error, G_SPAWN_EXIT_ERROR, 77); g_clear_error (&error); @@ -940,7 +940,7 @@ test_combining (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_test_message ("one pass and some incomplete -> overall status 0"); @@ -959,7 +959,7 @@ test_combining (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_test_message ("one pass and mix of skipped and incomplete -> overall status 0"); @@ -980,7 +980,7 @@ test_combining (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_test_message ("one fail and some skipped -> overall status fail"); @@ -1001,7 +1001,7 @@ test_combining (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_error (error, G_SPAWN_EXIT_ERROR, 1); g_clear_error (&error); @@ -1021,7 +1021,7 @@ test_combining (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_error (error, G_SPAWN_EXIT_ERROR, 1); g_clear_error (&error); @@ -1043,7 +1043,7 @@ test_combining (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_error (error, G_SPAWN_EXIT_ERROR, 1); g_clear_error (&error); @@ -1075,7 +1075,7 @@ test_tap (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_assert_nonnull (strstr (output, "\nok 1 /pass\n")); g_free (output); @@ -1094,7 +1094,7 @@ test_tap (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_assert_nonnull (strstr (output, "\nok 1 /skip # SKIP not enough tea\n")); g_free (output); @@ -1113,7 +1113,7 @@ test_tap (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_assert_nonnull (strstr (output, "\nnot ok 1 /incomplete # TODO mind reading not implemented yet\n")); g_free (output); @@ -1132,7 +1132,7 @@ test_tap (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_error (error, G_SPAWN_EXIT_ERROR, 1); g_assert_nonnull (strstr (output, "\nnot ok 1 /fail\n")); g_free (output); @@ -1166,7 +1166,7 @@ test_tap (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_ptr_array_unref (argv); @@ -1197,7 +1197,7 @@ test_tap (void) g_assert_nonnull (strstr (output, "\nok 9 /c/a\n")); g_assert_nonnull (strstr (output, "\nok 10 /d/a\n")); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_free (output); @@ -1229,7 +1229,7 @@ test_tap (void) g_assert_nonnull (strstr (output, "\nok 9 /c/a\n")); g_assert_nonnull (strstr (output, "\nok 10 /d/a\n")); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_free (output); @@ -1261,7 +1261,7 @@ test_tap (void) g_assert_nonnull (strstr (output, "\nok 9 /c/a # SKIP\n")); g_assert_nonnull (strstr (output, "\nok 10 /d/a # SKIP\n")); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_free (output); @@ -1292,7 +1292,7 @@ test_tap (void) g_assert_nonnull (strstr (output, "\nok 5 /b/b\n")); g_assert_nonnull (strstr (output, "\n1..5\n")); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_free (output); @@ -1324,7 +1324,7 @@ test_tap (void) g_assert_nonnull (strstr (output, "\nok 6 /b/b/a\n")); g_assert_nonnull (strstr (output, "\n1..6\n")); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_free (output); @@ -1350,7 +1350,7 @@ test_tap (void) g_assert_nonnull (strstr (output, "\nok 2 /b/b/a\n")); g_assert_nonnull (strstr (output, "\n1..2\n")); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_free (output); @@ -1374,7 +1374,7 @@ test_tap (void) NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_nonnull (error); g_assert_nonnull (strstr (output, "do not mix [-r | --run-prefix] with '-p'\n")); g_clear_error (&error); @@ -1416,7 +1416,7 @@ test_tap (void) g_assert_nonnull (strstr (output, "\nok 9 /c/a # SKIP by request")); g_assert_nonnull (strstr (output, "\nok 10 /d/a\n")); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_free (output); @@ -1453,7 +1453,7 @@ test_tap (void) g_assert_nonnull (strstr (output, "\nok 9 /c/a # SKIP by request")); g_assert_nonnull (strstr (output, "\nok 10 /d/a\n")); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); g_free (output); @@ -1477,7 +1477,7 @@ test_tap (void) NULL, NULL, &output, NULL, &status, &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_nonnull (error); g_assert_nonnull (strstr (output, "do not mix [-x | --skip-prefix] with '-s'\n")); g_clear_error (&error); @@ -1511,7 +1511,7 @@ test_tap_summary (void) &error); g_assert_no_error (error); - g_spawn_check_exit_status (status, &error); + g_spawn_check_wait_status (status, &error); g_assert_no_error (error); /* Note: The test path in the output is not `/tap/summary` because it’s the * test path from testing-helper, not from this function. */ diff --git a/glib/tests/thread-pool.c b/glib/tests/thread-pool.c index 703da5d7a..50a72a632 100644 --- a/glib/tests/thread-pool.c +++ b/glib/tests/thread-pool.c @@ -88,6 +88,12 @@ dummy_pool_func (gpointer data, gpointer user_data) } static void +dummy_pool_func_full (gpointer data, gpointer user_data) +{ + g_assert_true (data == user_data); +} + +static void test_create_first_pool (gconstpointer shared_first) { GThreadPool *pool; @@ -142,6 +148,55 @@ test_create_first_pool (gconstpointer shared_first) g_thread_pool_free (pool, TRUE, TRUE); } +static void +free_func (gpointer user_data) +{ + gboolean *free_func_called = user_data; + *free_func_called = TRUE; +} + +static void +test_thread_pool_full (gconstpointer shared_first) +{ + GThreadPool *pool; + gboolean free_func_called = FALSE; + GError *err = NULL; + gboolean success; + + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/121"); + + g_thread_pool_set_max_unused_threads (0); + + if (GPOINTER_TO_INT (shared_first)) + pool = g_thread_pool_new_full (dummy_pool_func_full, &free_func_called, free_func, -1, FALSE, &err); + else + pool = g_thread_pool_new_full (dummy_pool_func_full, &free_func_called, free_func, 2, TRUE, &err); + g_assert_no_error (err); + g_assert_nonnull (pool); + + success = g_thread_pool_push (pool, &free_func_called, &err); + g_assert_no_error (err); + g_assert_true (success); + + g_thread_pool_free (pool, TRUE, TRUE); + g_assert_true (free_func_called); + + free_func_called = FALSE; + if (GPOINTER_TO_INT (shared_first)) + pool = g_thread_pool_new_full (dummy_pool_func_full, &free_func_called, free_func, 2, TRUE, &err); + else + pool = g_thread_pool_new_full (dummy_pool_func_full, &free_func_called, free_func, -1, FALSE, &err); + g_assert_no_error (err); + g_assert_nonnull (pool); + + success = g_thread_pool_push (pool, &free_func_called, &err); + g_assert_no_error (err); + g_assert_true (success); + + g_thread_pool_free (pool, TRUE, TRUE); + g_assert_true (free_func_called); +} + int main (int argc, char *argv[]) { @@ -150,6 +205,7 @@ main (int argc, char *argv[]) g_test_add_data_func ("/thread_pool/shared", GINT_TO_POINTER (TRUE), test_simple); g_test_add_data_func ("/thread_pool/exclusive", GINT_TO_POINTER (FALSE), test_simple); g_test_add_data_func ("/thread_pool/create_shared_after_exclusive", GINT_TO_POINTER (FALSE), test_create_first_pool); + g_test_add_data_func ("/thread_pool/create_full", GINT_TO_POINTER (FALSE), test_thread_pool_full); g_test_add_data_func ("/thread_pool/create_exclusive_after_shared", GINT_TO_POINTER (TRUE), test_create_first_pool); return g_test_run (); diff --git a/glib/tests/tree.c b/glib/tests/tree.c index 8811d962d..5174479b9 100644 --- a/glib/tests/tree.c +++ b/glib/tests/tree.c @@ -68,17 +68,21 @@ my_search (gconstpointer a, static gpointer destroyed_key = NULL; static gpointer destroyed_value = NULL; +static guint destroyed_key_count = 0; +static guint destroyed_value_count = 0; static void my_key_destroy (gpointer key) { destroyed_key = key; + destroyed_key_count++; } static void my_value_destroy (gpointer value) { destroyed_value = value; + destroyed_value_count++; } static gint @@ -282,6 +286,32 @@ test_tree_remove (void) } static void +test_tree_remove_all (void) +{ + GTree *tree; + gsize i; + + tree = g_tree_new_full ((GCompareDataFunc)my_compare, NULL, + my_key_destroy, + my_value_destroy); + + for (i = 0; chars[i]; i++) + g_tree_insert (tree, &chars[i], &chars[i]); + + destroyed_key_count = 0; + destroyed_value_count = 0; + + g_tree_remove_all (tree); + + g_assert_cmpuint (destroyed_key_count, ==, strlen (chars)); + g_assert_cmpuint (destroyed_value_count, ==, strlen (chars)); + g_assert_cmpint (g_tree_height (tree), ==, 0); + g_assert_cmpint (g_tree_nnodes (tree), ==, 0); + + g_tree_unref (tree); +} + +static void test_tree_destroy (void) { GTree *tree; @@ -462,6 +492,7 @@ main (int argc, char *argv[]) g_test_add_func ("/tree/destroy", test_tree_destroy); g_test_add_func ("/tree/traverse", test_tree_traverse); g_test_add_func ("/tree/insert", test_tree_insert); + g_test_add_func ("/tree/remove-all", test_tree_remove_all); return g_test_run (); } diff --git a/glib/tests/uri.c b/glib/tests/uri.c index 1f3209f97..7a251af64 100644 --- a/glib/tests/uri.c +++ b/glib/tests/uri.c @@ -714,7 +714,7 @@ static const UriAbsoluteTest absolute_tests[] = { /* ".." past top */ { "http://example.com/..", G_URI_FLAGS_NONE, TRUE, 0, - { "http", NULL, "example.com", -1, "/..", NULL, NULL } + { "http", NULL, "example.com", -1, "/", NULL, NULL } }, /* scheme parsing */ diff --git a/glib/tests/utf8-validate.c b/glib/tests/utf8-validate.c index 51543f4b2..5fc37a3a3 100644 --- a/glib/tests/utf8-validate.c +++ b/glib/tests/utf8-validate.c @@ -268,7 +268,7 @@ Test test[] = { { "\x20\xed\xaf\xbf\xed\xb0\x80\x20", -1, 1, FALSE }, { "\x20\xed\xaf\xbf\xed\xbf\xbf\x20", -1, 1, FALSE }, - { NULL, } + { NULL, 0, 0, 0 } }; static void diff --git a/glib/tests/utils.c b/glib/tests/utils.c index 2c5d16c3a..f47e3595c 100644 --- a/glib/tests/utils.c +++ b/glib/tests/utils.c @@ -161,7 +161,7 @@ test_appname (void) static void test_tmpdir (void) { - g_test_bug ("627969"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=627969"); g_assert_cmpstr (g_get_tmp_dir (), !=, ""); } @@ -246,6 +246,11 @@ test_find_program (void) gchar *res; #ifdef G_OS_UNIX + gchar *relative_path; + gchar *absolute_path; + gchar *cwd; + gsize i; + res = g_find_program_in_path ("sh"); g_assert (res != NULL); g_free (res); @@ -253,6 +258,27 @@ test_find_program (void) res = g_find_program_in_path ("/bin/sh"); g_assert (res != NULL); g_free (res); + + cwd = g_get_current_dir (); + absolute_path = g_find_program_in_path ("sh"); + relative_path = g_strdup (absolute_path); + for (i = 0; cwd[i] != '\0'; i++) + { + if (cwd[i] == '/' && cwd[i + 1] != '\0') + { + gchar *relative_path_2 = g_strconcat ("../", relative_path, NULL); + g_free (relative_path); + relative_path = relative_path_2; + } + } + res = g_find_program_in_path (relative_path); + g_assert_nonnull (res); + g_assert_true (g_path_is_absolute (res)); + g_free (cwd); + g_free (absolute_path); + g_free (relative_path); + g_free (res); + #else /* There's not a lot we can search for that would reliably work both * on real Windows and mingw. @@ -829,7 +855,6 @@ main (int argc, g_set_prgname (argv[0]); g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ("/utils/language-names", test_language_names); g_test_add_func ("/utils/locale-variants", test_locale_variants); diff --git a/glib/tests/win32.c b/glib/tests/win32.c index 97e5887cf..121997311 100644 --- a/glib/tests/win32.c +++ b/glib/tests/win32.c @@ -33,34 +33,40 @@ static char *argv0 = NULL; static void test_subst_pid_and_event (void) { - const gchar not_enough[] = "too long when %e and %p are substituted"; - gchar debugger_3[3]; - gchar debugger_not_enough[G_N_ELEMENTS (not_enough)]; - gchar debugger_enough[G_N_ELEMENTS (not_enough) + 1]; - gchar debugger_big[65535] = {0}; + const wchar_t not_enough[] = L"too long when %e and %p are substituted"; + wchar_t debugger_3[3]; + wchar_t debugger_not_enough[G_N_ELEMENTS (not_enough)]; + wchar_t debugger_enough[G_N_ELEMENTS (not_enough) + 1]; + char *debugger_enough_utf8; + wchar_t debugger_big[65535] = {0}; + char *debugger_big_utf8; gchar *output; guintptr be = (guintptr) 0xFFFFFFFF; DWORD bp = G_MAXSIZE; /* %f is not valid */ - g_assert_false (_g_win32_subst_pid_and_event (debugger_3, G_N_ELEMENTS (debugger_3), - "%f", 0, 0)); + g_assert_false (_g_win32_subst_pid_and_event_w (debugger_3, G_N_ELEMENTS (debugger_3), + L"%f", 0, 0)); - g_assert_false (_g_win32_subst_pid_and_event (debugger_3, G_N_ELEMENTS (debugger_3), - "string longer than 10", 0, 0)); + g_assert_false (_g_win32_subst_pid_and_event_w (debugger_3, G_N_ELEMENTS (debugger_3), + L"string longer than 10", 0, 0)); /* 200 is longer than %e, so the string doesn't fit by 1 byte */ - g_assert_false (_g_win32_subst_pid_and_event (debugger_not_enough, G_N_ELEMENTS (debugger_not_enough), - "too long when %e and %p are substituted", 10, 200)); + g_assert_false (_g_win32_subst_pid_and_event_w (debugger_not_enough, G_N_ELEMENTS (debugger_not_enough), + not_enough, 10, 200)); /* This should fit */ - g_assert_true (_g_win32_subst_pid_and_event (debugger_enough, G_N_ELEMENTS (debugger_enough), - "too long when %e and %p are substituted", 10, 200)); - g_assert_cmpstr (debugger_enough, ==, "too long when 200 and 10 are substituted"); - - g_assert_true (_g_win32_subst_pid_and_event (debugger_big, G_N_ELEMENTS (debugger_big), - "multipl%e big %e %entries and %pids are %provided here", bp, be)); + g_assert_true (_g_win32_subst_pid_and_event_w (debugger_enough, G_N_ELEMENTS (debugger_enough), + not_enough, 10, 200)); + debugger_enough_utf8 = g_utf16_to_utf8 (debugger_enough, -1, NULL, NULL, NULL); + g_assert_cmpstr (debugger_enough_utf8, ==, "too long when 200 and 10 are substituted"); + g_free (debugger_enough_utf8); + + g_assert_true (_g_win32_subst_pid_and_event_w (debugger_big, G_N_ELEMENTS (debugger_big), + L"multipl%e big %e %entries and %pids are %provided here", bp, be)); + debugger_big_utf8 = g_utf16_to_utf8 (debugger_big, -1, NULL, NULL, NULL); output = g_strdup_printf ("multipl%llu big %llu %lluntries and %luids are %lurovided here", (guint64) be, (guint64) be, (guint64) be, bp, bp); - g_assert_cmpstr (debugger_big, ==, output); + g_assert_cmpstr (debugger_big_utf8, ==, output); + g_free (debugger_big_utf8); g_free (output); } @@ -95,7 +101,6 @@ test_veh_crash_access_violation (void) /* Run a test that crashes */ g_test_trap_subprocess ("/win32/subprocess/access_violation", 0, 0); g_test_trap_assert_failed (); - g_test_trap_assert_stderr ("Exception code=0xc0000005*"); } static void @@ -105,21 +110,11 @@ test_veh_crash_illegal_instruction (void) /* Run a test that crashes */ g_test_trap_subprocess ("/win32/subprocess/illegal_instruction", 0, 0); g_test_trap_assert_failed (); - g_test_trap_assert_stderr ("Exception code=0xc000001d*"); } static void test_veh_debug (void) { - /* Run a test that crashes and runs a debugger */ - g_test_trap_subprocess ("/win32/subprocess/debuggee", 0, 0); - g_test_trap_assert_failed (); - g_test_trap_assert_stderr ("Exception code=0xc0000005*Debugger invoked, attaching to*"); -} - -static void -test_veh_debuggee (void) -{ /* Set up a debugger to be run on crash */ gchar *command = g_strdup_printf ("%s %s", argv0, "%p %e"); g_setenv ("G_DEBUGGER", command, TRUE); @@ -129,6 +124,15 @@ test_veh_debuggee (void) */ g_setenv ("G_DEBUGGER_OLD_CONSOLE", "1", TRUE); g_free (command); + /* Run a test that crashes and runs a debugger */ + g_test_trap_subprocess ("/win32/subprocess/debuggee", 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("Debugger invoked, attaching to*"); +} + +static void +test_veh_debuggee (void) +{ /* Crash */ test_access_violation (); } diff --git a/glib/update-pcre/digitab.patch b/glib/update-pcre/digitab.patch deleted file mode 100644 index a12efc526..000000000 --- a/glib/update-pcre/digitab.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 5238ab10c5f3082a4be38410bd01a47ab176dfde Mon Sep 17 00:00:00 2001 -From: Christian Persch <chpe@gnome.org> -Date: Sun, 12 Feb 2012 19:29:42 +0100 -Subject: [PATCH] regex: Use g_ascii_is[x]digit - ---- - glib/pcre/pcre_compile.c | 22 ++++++++++++---------- - 1 files changed, 12 insertions(+), 10 deletions(-) - -diff --git a/glib/pcre/pcre_compile.c b/glib/pcre/pcre_compile.c -index 8070f51..eb985df 100644 ---- a/glib/pcre/pcre_compile.c -+++ b/glib/pcre/pcre_compile.c -@@ -52,6 +52,7 @@ supporting internal functions that are not used by other modules. */ - - #include "pcre_internal.h" - -+#include "gstrfuncs.h" - - /* When PCRE_DEBUG is defined, we need the pcre(16)_printint() function, which - is also used by pcretest. PCRE_DEBUG is not defined when building a production -@@ -513,6 +514,7 @@ into a subtraction and unsigned comparison). */ - - #define IS_DIGIT(x) ((x) >= CHAR_0 && (x) <= CHAR_9) - -+#if 0 - #ifndef EBCDIC - - /* This is the "normal" case, for ASCII systems, and EBCDIC systems running in -@@ -626,7 +628,7 @@ static const pcre_uint8 ebcdic_chartab[] = { /* chartable partial dup */ - 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ - 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ - #endif -- -+#endif /* 0 */ - - /* Definition to allow mutual recursion */ - -@@ -812,10 +814,10 @@ else - { - /* In JavaScript, \u must be followed by four hexadecimal numbers. - Otherwise it is a lowercase u letter. */ -- if (MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0 -- && MAX_255(ptr[2]) && (digitab[ptr[2]] & ctype_xdigit) != 0 -- && MAX_255(ptr[3]) && (digitab[ptr[3]] & ctype_xdigit) != 0 -- && MAX_255(ptr[4]) && (digitab[ptr[4]] & ctype_xdigit) != 0) -+ if (MAX_255(ptr[1]) && g_ascii_isxdigit(ptr[1]) != 0 -+ && MAX_255(ptr[2]) && g_ascii_isxdigit(ptr[2]) != 0 -+ && MAX_255(ptr[3]) && g_ascii_isxdigit(ptr[3]) != 0 -+ && MAX_255(ptr[4]) && g_ascii_isxdigit(ptr[4]) != 0) - { - c = 0; - for (i = 0; i < 4; ++i) -@@ -1012,8 +1014,8 @@ else - { - /* In JavaScript, \x must be followed by two hexadecimal numbers. - Otherwise it is a lowercase x letter. */ -- if (MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0 -- && MAX_255(ptr[2]) && (digitab[ptr[2]] & ctype_xdigit) != 0) -+ if (MAX_255(ptr[1]) && g_ascii_isxdigit(ptr[1]) != 0 -+ && MAX_255(ptr[2]) && g_ascii_isxdigit(ptr[2]) != 0) - { - c = 0; - for (i = 0; i < 2; ++i) -@@ -1036,7 +1038,7 @@ else - const pcre_uchar *pt = ptr + 2; - - c = 0; -- while (MAX_255(*pt) && (digitab[*pt] & ctype_xdigit) != 0) -+ while (MAX_255(*pt) && g_ascii_isxdigit(*pt) != 0) - { - register int cc = *pt++; - if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */ -@@ -1060,7 +1062,7 @@ else - - if (c < 0) - { -- while (MAX_255(*pt) && (digitab[*pt] & ctype_xdigit) != 0) pt++; -+ while (MAX_255(*pt) && g_ascii_isxdigit(*pt) != 0) pt++; - *errorcodeptr = ERR34; - } - -@@ -1078,7 +1080,7 @@ else - /* Read just a single-byte hex-defined char */ - - c = 0; -- while (i++ < 2 && MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0) -+ while (i++ < 2 && MAX_255(ptr[1]) && g_ascii_isxdigit(ptr[1]) != 0) - { - int cc; /* Some compilers don't like */ - cc = *(++ptr); /* ++ in initializers */ --- -1.7.5.1.217.g4e3aa.dirty - diff --git a/glib/update-pcre/memory.patch b/glib/update-pcre/memory.patch deleted file mode 100644 index f3a04c784..000000000 --- a/glib/update-pcre/memory.patch +++ /dev/null @@ -1,40 +0,0 @@ -From acf401f1353a37b6edff9577ff07d055c625e4ca Mon Sep 17 00:00:00 2001 -From: Christian Persch <chpe@gnome.org> -Date: Sun, 12 Feb 2012 19:40:48 +0100 -Subject: [PATCH] regex: Use glib memory allocator - ---- - glib/pcre/pcre_globals.c | 10 ++++++---- - 1 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/glib/pcre/pcre_globals.c b/glib/pcre/pcre_globals.c -index 36e6ddb..93d3af5 100644 ---- a/glib/pcre/pcre_globals.c -+++ b/glib/pcre/pcre_globals.c -@@ -58,6 +58,8 @@ global variables are not used. */ - - #include "pcre_internal.h" - -+#include "gmem.h" -+ - #if defined _MSC_VER || defined __SYMBIAN32__ - static void* LocalPcreMalloc(size_t aSize) - { -@@ -74,10 +76,10 @@ PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = LocalPcreFree; - PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL; - - #elif !defined VPCOMPAT --PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = malloc; --PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = free; --PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = malloc; --PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = free; -+PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = g_try_malloc; -+PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = g_free; -+PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = g_try_malloc; -+PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = g_free; - PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL; - #endif - --- -1.7.5.1.217.g4e3aa.dirty - diff --git a/glib/update-pcre/ucp.patch b/glib/update-pcre/ucp.patch deleted file mode 100644 index 402020fa8..000000000 --- a/glib/update-pcre/ucp.patch +++ /dev/null @@ -1,834 +0,0 @@ -From 23d48c5fc7aa889dc7798f9c64acd43d9cb34683 Mon Sep 17 00:00:00 2001 -From: Christian Persch <chpe@gnome.org> -Date: Sun, 12 Feb 2012 21:20:33 +0100 -Subject: [PATCH] regex: Use glib for unicode data - -Use g_unichar_type() and g_unichar_get_script() instead of pcre tables. ---- - glib/pcre/pcre_compile.c | 26 +++--- - glib/pcre/pcre_dfa_exec.c | 96 ++++++++-------- - glib/pcre/pcre_exec.c | 26 +++--- - glib/pcre/pcre_internal.h | 11 +-- - glib/pcre/pcre_tables.c | 16 +++ - glib/pcre/pcre_xclass.c | 24 ++-- - glib/pcre/ucp.h | 265 +++++++++++++++++++++++---------------------- - 7 files changed, 239 insertions(+), 225 deletions(-) - -diff --git a/glib/pcre/pcre_compile.c b/glib/pcre/pcre_compile.c -index 21bef80..a6c84e1 100644 ---- a/glib/pcre/pcre_compile.c -+++ b/glib/pcre/pcre_compile.c -@@ -2920,43 +2920,43 @@ Returns: TRUE if auto-possessifying is OK - static BOOL - check_char_prop(int c, int ptype, int pdata, BOOL negated) - { --const ucd_record *prop = GET_UCD(c); -+const pcre_uint8 chartype = UCD_CHARTYPE(c); - switch(ptype) - { - case PT_LAMP: -- return (prop->chartype == ucp_Lu || -- prop->chartype == ucp_Ll || -- prop->chartype == ucp_Lt) == negated; -+ return (chartype == ucp_Lu || -+ chartype == ucp_Ll || -+ chartype == ucp_Lt) == negated; - - case PT_GC: -- return (pdata == PRIV(ucp_gentype)[prop->chartype]) == negated; -+ return (pdata == PRIV(ucp_gentype)[chartype]) == negated; - - case PT_PC: -- return (pdata == prop->chartype) == negated; -+ return (pdata == chartype) == negated; - - case PT_SC: -- return (pdata == prop->script) == negated; -+ return (pdata == UCD_SCRIPT(c)) == negated; - - /* These are specials */ - - case PT_ALNUM: -- return (PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N) == negated; -+ return (PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N) == negated; - - case PT_SPACE: /* Perl space */ -- return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ return (PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR) - == negated; - - case PT_PXSPACE: /* POSIX space */ -- return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ return (PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR) - == negated; - - case PT_WORD: -- return (PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N || -+ return (PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N || - c == CHAR_UNDERSCORE) == negated; - } - return FALSE; -diff --git a/glib/pcre/pcre_dfa_exec.c b/glib/pcre/pcre_dfa_exec.c -index 9565d46..3f913ce 100644 ---- a/glib/pcre/pcre_dfa_exec.c -+++ b/glib/pcre/pcre_dfa_exec.c -@@ -1060,7 +1060,7 @@ for (;;) - if (clen > 0) - { - BOOL OK; -- const ucd_record * prop = GET_UCD(c); -+ const pcre_uint8 chartype = UCD_CHARTYPE(c); - switch(code[1]) - { - case PT_ANY: -@@ -1068,43 +1068,43 @@ for (;;) - break; - - case PT_LAMP: -- OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || -- prop->chartype == ucp_Lt; -+ OK = chartype == ucp_Lu || chartype == ucp_Ll || -+ chartype == ucp_Lt; - break; - - case PT_GC: -- OK = PRIV(ucp_gentype)[prop->chartype] == code[2]; -+ OK = PRIV(ucp_gentype)[chartype] == code[2]; - break; - - case PT_PC: -- OK = prop->chartype == code[2]; -+ OK = chartype == code[2]; - break; - - case PT_SC: -- OK = prop->script == code[2]; -+ OK = UCD_SCRIPT(c) == code[2]; - break; - - /* These are specials for combination cases. */ - - case PT_ALNUM: -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N; -+ OK = PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N; - break; - - case PT_SPACE: /* Perl space */ -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR; - break; - - case PT_PXSPACE: /* POSIX space */ -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR; - break; - - case PT_WORD: -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N || -+ OK = PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N || - c == CHAR_UNDERSCORE; - break; - -@@ -1294,7 +1294,7 @@ for (;;) - if (clen > 0) - { - BOOL OK; -- const ucd_record * prop = GET_UCD(c); -+ const pcre_uint8 chartype = UCD_CHARTYPE(c); - switch(code[2]) - { - case PT_ANY: -@@ -1302,43 +1302,43 @@ for (;;) - break; - - case PT_LAMP: -- OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || -- prop->chartype == ucp_Lt; -+ OK = chartype == ucp_Lu || chartype == ucp_Ll || -+ chartype == ucp_Lt; - break; - - case PT_GC: -- OK = PRIV(ucp_gentype)[prop->chartype] == code[3]; -+ OK = PRIV(ucp_gentype)[chartype] == code[3]; - break; - - case PT_PC: -- OK = prop->chartype == code[3]; -+ OK = chartype == code[3]; - break; - - case PT_SC: -- OK = prop->script == code[3]; -+ OK = UCD_SCRIPT(c) == code[3]; - break; - - /* These are specials for combination cases. */ - - case PT_ALNUM: -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N; -+ OK = PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N; - break; - - case PT_SPACE: /* Perl space */ -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR; - break; - - case PT_PXSPACE: /* POSIX space */ -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR; - break; - - case PT_WORD: -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N || -+ OK = PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N || - c == CHAR_UNDERSCORE; - break; - -@@ -1541,7 +1541,7 @@ for (;;) - if (clen > 0) - { - BOOL OK; -- const ucd_record * prop = GET_UCD(c); -+ const pcre_uint8 chartype = UCD_CHARTYPE(c); - switch(code[2]) - { - case PT_ANY: -@@ -1549,43 +1549,43 @@ for (;;) - break; - - case PT_LAMP: -- OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || -- prop->chartype == ucp_Lt; -+ OK = chartype == ucp_Lu || chartype == ucp_Ll || -+ chartype == ucp_Lt; - break; - - case PT_GC: -- OK = PRIV(ucp_gentype)[prop->chartype] == code[3]; -+ OK = PRIV(ucp_gentype)[chartype] == code[3]; - break; - - case PT_PC: -- OK = prop->chartype == code[3]; -+ OK = chartype == code[3]; - break; - - case PT_SC: -- OK = prop->script == code[3]; -+ OK = UCD_SCRIPT(c) == code[3]; - break; - - /* These are specials for combination cases. */ - - case PT_ALNUM: -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N; -+ OK = PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N; - break; - - case PT_SPACE: /* Perl space */ -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR; - break; - - case PT_PXSPACE: /* POSIX space */ -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR; - break; - - case PT_WORD: -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N || -+ OK = PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N || - c == CHAR_UNDERSCORE; - break; - -@@ -1813,7 +1813,7 @@ for (;;) - if (clen > 0) - { - BOOL OK; -- const ucd_record * prop = GET_UCD(c); -+ const pcre_uint8 chartype = UCD_CHARTYPE(c); - switch(code[1 + IMM2_SIZE + 1]) - { - case PT_ANY: -@@ -1821,43 +1821,43 @@ for (;;) - break; - - case PT_LAMP: -- OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || -- prop->chartype == ucp_Lt; -+ OK = chartype == ucp_Lu || chartype == ucp_Ll || -+ chartype == ucp_Lt; - break; - - case PT_GC: -- OK = PRIV(ucp_gentype)[prop->chartype] == code[1 + IMM2_SIZE + 2]; -+ OK = PRIV(ucp_gentype)[chartype] == code[1 + IMM2_SIZE + 2]; - break; - - case PT_PC: -- OK = prop->chartype == code[1 + IMM2_SIZE + 2]; -+ OK = chartype == code[1 + IMM2_SIZE + 2]; - break; - - case PT_SC: -- OK = prop->script == code[1 + IMM2_SIZE + 2]; -+ OK = UCD_SCRIPT(c) == code[1 + IMM2_SIZE + 2]; - break; - - /* These are specials for combination cases. */ - - case PT_ALNUM: -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N; -+ OK = PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N; - break; - - case PT_SPACE: /* Perl space */ -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR; - break; - - case PT_PXSPACE: /* POSIX space */ -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ OK = PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR; - break; - - case PT_WORD: -- OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N || -+ OK = PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N || - c == CHAR_UNDERSCORE; - break; - -diff --git a/glib/pcre/pcre_exec.c b/glib/pcre/pcre_exec.c -index 830b8b5..c89a3f9 100644 ---- a/glib/pcre/pcre_exec.c -+++ b/glib/pcre/pcre_exec.c -@@ -2565,7 +2565,7 @@ for (;;) - } - GETCHARINCTEST(c, eptr); - { -- const ucd_record *prop = GET_UCD(c); -+ const pcre_uint8 chartype = UCD_CHARTYPE(c); - - switch(ecode[1]) - { -@@ -2574,44 +2574,44 @@ for (;;) - break; - - case PT_LAMP: -- if ((prop->chartype == ucp_Lu || -- prop->chartype == ucp_Ll || -- prop->chartype == ucp_Lt) == (op == OP_NOTPROP)) -+ if ((chartype == ucp_Lu || -+ chartype == ucp_Ll || -+ chartype == ucp_Lt) == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_GC: -- if ((ecode[2] != PRIV(ucp_gentype)[prop->chartype]) == (op == OP_PROP)) -+ if ((ecode[2] != PRIV(ucp_gentype)[chartype]) == (op == OP_PROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_PC: -- if ((ecode[2] != prop->chartype) == (op == OP_PROP)) -+ if ((ecode[2] != chartype) == (op == OP_PROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_SC: -- if ((ecode[2] != prop->script) == (op == OP_PROP)) -+ if ((ecode[2] != UCD_SCRIPT(c)) == (op == OP_PROP)) - RRETURN(MATCH_NOMATCH); - break; - - /* These are specials */ - - case PT_ALNUM: -- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (op == OP_NOTPROP)) -+ if ((PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N) == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_SPACE: /* Perl space */ -- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ if ((PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR) - == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; - - case PT_PXSPACE: /* POSIX space */ -- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ if ((PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR) - == (op == OP_NOTPROP)) -@@ -2619,8 +2619,8 @@ for (;;) - break; - - case PT_WORD: -- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N || -+ if ((PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N || - c == CHAR_UNDERSCORE) == (op == OP_NOTPROP)) - RRETURN(MATCH_NOMATCH); - break; -diff --git a/glib/pcre/pcre_internal.h b/glib/pcre/pcre_internal.h -index 181c312..234af1b 100644 ---- a/glib/pcre/pcre_internal.h -+++ b/glib/pcre/pcre_internal.h -@@ -2329,15 +2329,12 @@ extern const int PRIV(ucp_typerange)[]; - #ifdef SUPPORT_UCP - /* UCD access macros */ - --#define UCD_BLOCK_SIZE 128 --#define GET_UCD(ch) (PRIV(ucd_records) + \ -- PRIV(ucd_stage2)[PRIV(ucd_stage1)[(ch) / UCD_BLOCK_SIZE] * \ -- UCD_BLOCK_SIZE + (ch) % UCD_BLOCK_SIZE]) -+unsigned int _pcre_ucp_othercase(const unsigned int c); - --#define UCD_CHARTYPE(ch) GET_UCD(ch)->chartype --#define UCD_SCRIPT(ch) GET_UCD(ch)->script -+#define UCD_CHARTYPE(ch) (pcre_uint8)g_unichar_type((gunichar)(ch)) -+#define UCD_SCRIPT(ch) (pcre_uint8)g_unichar_get_script((gunichar)(ch)) - #define UCD_CATEGORY(ch) PRIV(ucp_gentype)[UCD_CHARTYPE(ch)] --#define UCD_OTHERCASE(ch) (ch + GET_UCD(ch)->other_case) -+#define UCD_OTHERCASE(ch) (_pcre_ucp_othercase(ch)) - - #endif /* SUPPORT_UCP */ - -diff --git a/glib/pcre/pcre_tables.c b/glib/pcre/pcre_tables.c -index 7ac2d89..e401974 100644 ---- a/glib/pcre/pcre_tables.c -+++ b/glib/pcre/pcre_tables.c -@@ -584,6 +584,22 @@ const ucp_type_table PRIV(utt)[] = { - - const int PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table); - -+unsigned int -+_pcre_ucp_othercase(const unsigned int c) -+{ -+ int other_case = NOTACHAR; -+ -+ if (g_unichar_islower(c)) -+ other_case = g_unichar_toupper(c); -+ else if (g_unichar_isupper(c)) -+ other_case = g_unichar_tolower(c); -+ -+ if (other_case == c) -+ other_case = NOTACHAR; -+ -+ return other_case; -+} -+ - #endif /* SUPPORT_UTF */ - - /* End of pcre_tables.c */ -diff --git a/glib/pcre/pcre_xclass.c b/glib/pcre/pcre_xclass.c -index dca7a39..e5a55d7 100644 ---- a/glib/pcre/pcre_xclass.c -+++ b/glib/pcre/pcre_xclass.c -@@ -127,7 +127,7 @@ while ((t = *data++) != XCL_END) - #ifdef SUPPORT_UCP - else /* XCL_PROP & XCL_NOTPROP */ - { -- const ucd_record *prop = GET_UCD(c); -+ const pcre_uint8 chartype = UCD_CHARTYPE(c); - - switch(*data) - { -@@ -136,46 +136,46 @@ while ((t = *data++) != XCL_END) - break; - - case PT_LAMP: -- if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || -- prop->chartype == ucp_Lt) == (t == XCL_PROP)) return !negated; -+ if ((chartype == ucp_Lu || chartype == ucp_Ll || -+ chartype == ucp_Lt) == (t == XCL_PROP)) return !negated; - break; - - case PT_GC: -- if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == (t == XCL_PROP)) -+ if ((data[1] == PRIV(ucp_gentype)[chartype]) == (t == XCL_PROP)) - return !negated; - break; - - case PT_PC: -- if ((data[1] == prop->chartype) == (t == XCL_PROP)) return !negated; -+ if ((data[1] == chartype) == (t == XCL_PROP)) return !negated; - break; - - case PT_SC: -- if ((data[1] == prop->script) == (t == XCL_PROP)) return !negated; -+ if ((data[1] == UCD_SCRIPT(c)) == (t == XCL_PROP)) return !negated; - break; - - case PT_ALNUM: -- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (t == XCL_PROP)) -+ if ((PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N) == (t == XCL_PROP)) - return !negated; - break; - - case PT_SPACE: /* Perl space */ -- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ if ((PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR) - == (t == XCL_PROP)) - return !negated; - break; - - case PT_PXSPACE: /* POSIX space */ -- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z || -+ if ((PRIV(ucp_gentype)[chartype] == ucp_Z || - c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || - c == CHAR_FF || c == CHAR_CR) == (t == XCL_PROP)) - return !negated; - break; - - case PT_WORD: -- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || -- PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE) -+ if ((PRIV(ucp_gentype)[chartype] == ucp_L || -+ PRIV(ucp_gentype)[chartype] == ucp_N || c == CHAR_UNDERSCORE) - == (t == XCL_PROP)) - return !negated; - break; -diff --git a/glib/pcre/ucp.h b/glib/pcre/ucp.h -index 59c3bec..53a48c9 100644 ---- a/glib/pcre/ucp.h -+++ b/glib/pcre/ucp.h -@@ -10,6 +10,7 @@ the UCD access macros. New values that are added for new releases of Unicode - should always be at the end of each enum, for backwards compatibility. */ - - /* These are the general character categories. */ -+#include "gunicode.h" - - enum { - ucp_C, /* Other */ -@@ -24,148 +25,148 @@ enum { - /* These are the particular character types. */ - - enum { -- ucp_Cc, /* Control */ -- ucp_Cf, /* Format */ -- ucp_Cn, /* Unassigned */ -- ucp_Co, /* Private use */ -- ucp_Cs, /* Surrogate */ -- ucp_Ll, /* Lower case letter */ -- ucp_Lm, /* Modifier letter */ -- ucp_Lo, /* Other letter */ -- ucp_Lt, /* Title case letter */ -- ucp_Lu, /* Upper case letter */ -- ucp_Mc, /* Spacing mark */ -- ucp_Me, /* Enclosing mark */ -- ucp_Mn, /* Non-spacing mark */ -- ucp_Nd, /* Decimal number */ -- ucp_Nl, /* Letter number */ -- ucp_No, /* Other number */ -- ucp_Pc, /* Connector punctuation */ -- ucp_Pd, /* Dash punctuation */ -- ucp_Pe, /* Close punctuation */ -- ucp_Pf, /* Final punctuation */ -- ucp_Pi, /* Initial punctuation */ -- ucp_Po, /* Other punctuation */ -- ucp_Ps, /* Open punctuation */ -- ucp_Sc, /* Currency symbol */ -- ucp_Sk, /* Modifier symbol */ -- ucp_Sm, /* Mathematical symbol */ -- ucp_So, /* Other symbol */ -- ucp_Zl, /* Line separator */ -- ucp_Zp, /* Paragraph separator */ -- ucp_Zs /* Space separator */ -+ ucp_Cc = G_UNICODE_CONTROL, /* Control */ -+ ucp_Cf = G_UNICODE_FORMAT, /* Format */ -+ ucp_Cn = G_UNICODE_UNASSIGNED, /* Unassigned */ -+ ucp_Co = G_UNICODE_PRIVATE_USE, /* Private use */ -+ ucp_Cs = G_UNICODE_SURROGATE, /* Surrogate */ -+ ucp_Ll = G_UNICODE_LOWERCASE_LETTER, /* Lower case letter */ -+ ucp_Lm = G_UNICODE_MODIFIER_LETTER, /* Modifier letter */ -+ ucp_Lo = G_UNICODE_OTHER_LETTER, /* Other letter */ -+ ucp_Lt = G_UNICODE_TITLECASE_LETTER, /* Title case letter */ -+ ucp_Lu = G_UNICODE_UPPERCASE_LETTER, /* Upper case letter */ -+ ucp_Mc = G_UNICODE_SPACING_MARK, /* Spacing mark */ -+ ucp_Me = G_UNICODE_ENCLOSING_MARK, /* Enclosing mark */ -+ ucp_Mn = G_UNICODE_NON_SPACING_MARK, /* Non-spacing mark */ -+ ucp_Nd = G_UNICODE_DECIMAL_NUMBER, /* Decimal number */ -+ ucp_Nl = G_UNICODE_LETTER_NUMBER, /* Letter number */ -+ ucp_No = G_UNICODE_OTHER_NUMBER, /* Other number */ -+ ucp_Pc = G_UNICODE_CONNECT_PUNCTUATION, /* Connector punctuation */ -+ ucp_Pd = G_UNICODE_DASH_PUNCTUATION, /* Dash punctuation */ -+ ucp_Pe = G_UNICODE_CLOSE_PUNCTUATION, /* Close punctuation */ -+ ucp_Pf = G_UNICODE_FINAL_PUNCTUATION, /* Final punctuation */ -+ ucp_Pi = G_UNICODE_INITIAL_PUNCTUATION, /* Initial punctuation */ -+ ucp_Po = G_UNICODE_OTHER_PUNCTUATION, /* Other punctuation */ -+ ucp_Ps = G_UNICODE_OPEN_PUNCTUATION, /* Open punctuation */ -+ ucp_Sc = G_UNICODE_CURRENCY_SYMBOL, /* Currency symbol */ -+ ucp_Sk = G_UNICODE_MODIFIER_SYMBOL, /* Modifier symbol */ -+ ucp_Sm = G_UNICODE_MATH_SYMBOL, /* Mathematical symbol */ -+ ucp_So = G_UNICODE_OTHER_SYMBOL, /* Other symbol */ -+ ucp_Zl = G_UNICODE_LINE_SEPARATOR, /* Line separator */ -+ ucp_Zp = G_UNICODE_PARAGRAPH_SEPARATOR, /* Paragraph separator */ -+ ucp_Zs = G_UNICODE_SPACE_SEPARATOR /* Space separator */ - }; - - /* These are the script identifications. */ - - enum { -- ucp_Arabic, -- ucp_Armenian, -- ucp_Bengali, -- ucp_Bopomofo, -- ucp_Braille, -- ucp_Buginese, -- ucp_Buhid, -- ucp_Canadian_Aboriginal, -- ucp_Cherokee, -- ucp_Common, -- ucp_Coptic, -- ucp_Cypriot, -- ucp_Cyrillic, -- ucp_Deseret, -- ucp_Devanagari, -- ucp_Ethiopic, -- ucp_Georgian, -- ucp_Glagolitic, -- ucp_Gothic, -- ucp_Greek, -- ucp_Gujarati, -- ucp_Gurmukhi, -- ucp_Han, -- ucp_Hangul, -- ucp_Hanunoo, -- ucp_Hebrew, -- ucp_Hiragana, -- ucp_Inherited, -- ucp_Kannada, -- ucp_Katakana, -- ucp_Kharoshthi, -- ucp_Khmer, -- ucp_Lao, -- ucp_Latin, -- ucp_Limbu, -- ucp_Linear_B, -- ucp_Malayalam, -- ucp_Mongolian, -- ucp_Myanmar, -- ucp_New_Tai_Lue, -- ucp_Ogham, -- ucp_Old_Italic, -- ucp_Old_Persian, -- ucp_Oriya, -- ucp_Osmanya, -- ucp_Runic, -- ucp_Shavian, -- ucp_Sinhala, -- ucp_Syloti_Nagri, -- ucp_Syriac, -- ucp_Tagalog, -- ucp_Tagbanwa, -- ucp_Tai_Le, -- ucp_Tamil, -- ucp_Telugu, -- ucp_Thaana, -- ucp_Thai, -- ucp_Tibetan, -- ucp_Tifinagh, -- ucp_Ugaritic, -- ucp_Yi, -+ ucp_Arabic = G_UNICODE_SCRIPT_ARABIC, -+ ucp_Armenian = G_UNICODE_SCRIPT_ARMENIAN, -+ ucp_Bengali = G_UNICODE_SCRIPT_BENGALI, -+ ucp_Bopomofo = G_UNICODE_SCRIPT_BOPOMOFO, -+ ucp_Braille = G_UNICODE_SCRIPT_BRAILLE, -+ ucp_Buginese = G_UNICODE_SCRIPT_BUGINESE, -+ ucp_Buhid = G_UNICODE_SCRIPT_BUHID, -+ ucp_Canadian_Aboriginal = G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL, -+ ucp_Cherokee = G_UNICODE_SCRIPT_CHEROKEE, -+ ucp_Common = G_UNICODE_SCRIPT_COMMON, -+ ucp_Coptic = G_UNICODE_SCRIPT_COPTIC, -+ ucp_Cypriot = G_UNICODE_SCRIPT_CYPRIOT, -+ ucp_Cyrillic = G_UNICODE_SCRIPT_CYRILLIC, -+ ucp_Deseret = G_UNICODE_SCRIPT_DESERET, -+ ucp_Devanagari = G_UNICODE_SCRIPT_DEVANAGARI, -+ ucp_Ethiopic = G_UNICODE_SCRIPT_ETHIOPIC, -+ ucp_Georgian = G_UNICODE_SCRIPT_GEORGIAN, -+ ucp_Glagolitic = G_UNICODE_SCRIPT_GLAGOLITIC, -+ ucp_Gothic = G_UNICODE_SCRIPT_GOTHIC, -+ ucp_Greek = G_UNICODE_SCRIPT_GREEK, -+ ucp_Gujarati = G_UNICODE_SCRIPT_GUJARATI, -+ ucp_Gurmukhi = G_UNICODE_SCRIPT_GURMUKHI, -+ ucp_Han = G_UNICODE_SCRIPT_HAN, -+ ucp_Hangul = G_UNICODE_SCRIPT_HANGUL, -+ ucp_Hanunoo = G_UNICODE_SCRIPT_HANUNOO, -+ ucp_Hebrew = G_UNICODE_SCRIPT_HEBREW, -+ ucp_Hiragana = G_UNICODE_SCRIPT_HIRAGANA, -+ ucp_Inherited = G_UNICODE_SCRIPT_INHERITED, -+ ucp_Kannada = G_UNICODE_SCRIPT_KANNADA, -+ ucp_Katakana = G_UNICODE_SCRIPT_KATAKANA, -+ ucp_Kharoshthi = G_UNICODE_SCRIPT_KHAROSHTHI, -+ ucp_Khmer = G_UNICODE_SCRIPT_KHMER, -+ ucp_Lao = G_UNICODE_SCRIPT_LAO, -+ ucp_Latin = G_UNICODE_SCRIPT_LATIN, -+ ucp_Limbu = G_UNICODE_SCRIPT_LIMBU, -+ ucp_Linear_B = G_UNICODE_SCRIPT_LINEAR_B, -+ ucp_Malayalam = G_UNICODE_SCRIPT_MALAYALAM, -+ ucp_Mongolian = G_UNICODE_SCRIPT_MONGOLIAN, -+ ucp_Myanmar = G_UNICODE_SCRIPT_MYANMAR, -+ ucp_New_Tai_Lue = G_UNICODE_SCRIPT_NEW_TAI_LUE, -+ ucp_Ogham = G_UNICODE_SCRIPT_OGHAM, -+ ucp_Old_Italic = G_UNICODE_SCRIPT_OLD_ITALIC, -+ ucp_Old_Persian = G_UNICODE_SCRIPT_OLD_PERSIAN, -+ ucp_Oriya = G_UNICODE_SCRIPT_ORIYA, -+ ucp_Osmanya = G_UNICODE_SCRIPT_OSMANYA, -+ ucp_Runic = G_UNICODE_SCRIPT_RUNIC, -+ ucp_Shavian = G_UNICODE_SCRIPT_SHAVIAN, -+ ucp_Sinhala = G_UNICODE_SCRIPT_SINHALA, -+ ucp_Syloti_Nagri = G_UNICODE_SCRIPT_SYLOTI_NAGRI, -+ ucp_Syriac = G_UNICODE_SCRIPT_SYRIAC, -+ ucp_Tagalog = G_UNICODE_SCRIPT_TAGALOG, -+ ucp_Tagbanwa = G_UNICODE_SCRIPT_TAGBANWA, -+ ucp_Tai_Le = G_UNICODE_SCRIPT_TAI_LE, -+ ucp_Tamil = G_UNICODE_SCRIPT_TAMIL, -+ ucp_Telugu = G_UNICODE_SCRIPT_TELUGU, -+ ucp_Thaana = G_UNICODE_SCRIPT_THAANA, -+ ucp_Thai = G_UNICODE_SCRIPT_THAI, -+ ucp_Tibetan = G_UNICODE_SCRIPT_TIBETAN, -+ ucp_Tifinagh = G_UNICODE_SCRIPT_TIFINAGH, -+ ucp_Ugaritic = G_UNICODE_SCRIPT_UGARITIC, -+ ucp_Yi = G_UNICODE_SCRIPT_YI, - /* New for Unicode 5.0: */ -- ucp_Balinese, -- ucp_Cuneiform, -- ucp_Nko, -- ucp_Phags_Pa, -- ucp_Phoenician, -+ ucp_Balinese = G_UNICODE_SCRIPT_BALINESE, -+ ucp_Cuneiform = G_UNICODE_SCRIPT_CUNEIFORM, -+ ucp_Nko = G_UNICODE_SCRIPT_NKO, -+ ucp_Phags_Pa = G_UNICODE_SCRIPT_PHAGS_PA, -+ ucp_Phoenician = G_UNICODE_SCRIPT_PHOENICIAN, - /* New for Unicode 5.1: */ -- ucp_Carian, -- ucp_Cham, -- ucp_Kayah_Li, -- ucp_Lepcha, -- ucp_Lycian, -- ucp_Lydian, -- ucp_Ol_Chiki, -- ucp_Rejang, -- ucp_Saurashtra, -- ucp_Sundanese, -- ucp_Vai, -+ ucp_Carian = G_UNICODE_SCRIPT_CARIAN, -+ ucp_Cham = G_UNICODE_SCRIPT_CHAM, -+ ucp_Kayah_Li = G_UNICODE_SCRIPT_KAYAH_LI, -+ ucp_Lepcha = G_UNICODE_SCRIPT_LEPCHA, -+ ucp_Lycian = G_UNICODE_SCRIPT_LYCIAN, -+ ucp_Lydian = G_UNICODE_SCRIPT_LYDIAN, -+ ucp_Ol_Chiki = G_UNICODE_SCRIPT_OL_CHIKI, -+ ucp_Rejang = G_UNICODE_SCRIPT_REJANG, -+ ucp_Saurashtra = G_UNICODE_SCRIPT_SAURASHTRA, -+ ucp_Sundanese = G_UNICODE_SCRIPT_SUNDANESE, -+ ucp_Vai = G_UNICODE_SCRIPT_VAI, - /* New for Unicode 5.2: */ -- ucp_Avestan, -- ucp_Bamum, -- ucp_Egyptian_Hieroglyphs, -- ucp_Imperial_Aramaic, -- ucp_Inscriptional_Pahlavi, -- ucp_Inscriptional_Parthian, -- ucp_Javanese, -- ucp_Kaithi, -- ucp_Lisu, -- ucp_Meetei_Mayek, -- ucp_Old_South_Arabian, -- ucp_Old_Turkic, -- ucp_Samaritan, -- ucp_Tai_Tham, -- ucp_Tai_Viet, -+ ucp_Avestan = G_UNICODE_SCRIPT_AVESTAN, -+ ucp_Bamum = G_UNICODE_SCRIPT_BAMUM, -+ ucp_Egyptian_Hieroglyphs = G_UNICODE_SCRIPT_EGYPTIAN_HIEROGLYPHS, -+ ucp_Imperial_Aramaic = G_UNICODE_SCRIPT_IMPERIAL_ARAMAIC, -+ ucp_Inscriptional_Pahlavi = G_UNICODE_SCRIPT_INSCRIPTIONAL_PAHLAVI, -+ ucp_Inscriptional_Parthian = G_UNICODE_SCRIPT_INSCRIPTIONAL_PARTHIAN, -+ ucp_Javanese = G_UNICODE_SCRIPT_JAVANESE, -+ ucp_Kaithi = G_UNICODE_SCRIPT_KAITHI, -+ ucp_Lisu = G_UNICODE_SCRIPT_LISU, -+ ucp_Meetei_Mayek = G_UNICODE_SCRIPT_MEETEI_MAYEK, -+ ucp_Old_South_Arabian = G_UNICODE_SCRIPT_OLD_SOUTH_ARABIAN, -+ ucp_Old_Turkic = G_UNICODE_SCRIPT_OLD_TURKIC, -+ ucp_Samaritan = G_UNICODE_SCRIPT_SAMARITAN, -+ ucp_Tai_Tham = G_UNICODE_SCRIPT_TAI_THAM, -+ ucp_Tai_Viet = G_UNICODE_SCRIPT_TAI_VIET, - /* New for Unicode 6.0.0: */ -- ucp_Batak, -- ucp_Brahmi, -- ucp_Mandaic, -+ ucp_Batak = G_UNICODE_SCRIPT_BATAK, -+ ucp_Brahmi = G_UNICODE_SCRIPT_BRAHMI, -+ ucp_Mandaic = G_UNICODE_SCRIPT_MANDAIC, - /* New for Unicode 6.1.0: */ -- ucp_Chakma, -- ucp_Meroitic_Cursive, -- ucp_Meroitic_Hieroglyphs, -- ucp_Miao, -- ucp_Sharada, -- ucp_Sora_Sompeng, -- ucp_Takri -+ ucp_Chakma = G_UNICODE_SCRIPT_CHAKMA, -+ ucp_Meroitic_Cursive = G_UNICODE_SCRIPT_MEROITIC_CURSIVE, -+ ucp_Meroitic_Hieroglyphs = G_UNICODE_SCRIPT_MEROITIC_HIEROGLYPHS, -+ ucp_Miao = G_UNICODE_SCRIPT_MIAO, -+ ucp_Sharada = G_UNICODE_SCRIPT_SHARADA, -+ ucp_Sora_Sompeng = G_UNICODE_SCRIPT_SORA_SOMPENG, -+ ucp_Takri = G_UNICODE_SCRIPT_TAKRI, - }; - - #endif --- -1.7.5.1.217.g4e3aa.dirty - diff --git a/glib/update-pcre/update.sh b/glib/update-pcre/update.sh deleted file mode 100644 index 69d7f8aa7..000000000 --- a/glib/update-pcre/update.sh +++ /dev/null @@ -1,124 +0,0 @@ -#! /bin/sh - -set -e - -IN="../update-pcre" -PCRE=$1 - -if [ "x$PCRE" = x ] || [ "x$PCRE" = x--help ] || [ "x$PCRE" = x-h ]; then - cat >&2 << EOF - -$0 PCRE-DIR - - Updates the local PCRE copy with a different version of the library, - contained in the directory PCRE-DIR. - - This will delete the content of the local pcre directory, copy the - necessary files from PCRE-DIR, and generate other needed files, such - as Makefile.am -EOF - exit -fi - -if [ ! -f gregex.h ]; then - echo "This script should be executed from the directory containing gregex.c." 2> /dev/null - exit 1 -fi - -if [ ! -f "${PCRE}/Makefile.in" ] || [ ! -f "${PCRE}/pcre_compile.c" ]; then - echo "'${PCRE}' does not contain a valid PCRE version." 2> /dev/null - exit 1 -fi - - -echo "Deleting old PCRE library" -mv pcre/.svn tmp-pcre-svn -rm -R pcre 2> /dev/null -mkdir pcre -cd pcre - -# pcre_chartables.c is generated by dfatables. -# We do not want to compile and execute dfatables.c every time, because -# this could be a problem (e.g. when cross-compiling), so now generate -# the file and then distribute it with GRegex. -echo "Generating pcre_chartables.c" -cp -R "${PCRE}" tmp-build -( -cd tmp-build || exit 1 -./configure --enable-utf8 --enable-unicode-properties --disable-cpp > /dev/null -make pcre_chartables.c > /dev/null -cat > ../pcre_chartables.c << \EOF -/* This file is autogenerated by ../update-pcre/update.sh during - * the update of the local copy of PCRE. - */ -EOF -cat pcre_chartables.c >> ../pcre_chartables.c -) -rm -R tmp-build - -# Compiled C files. -echo "Generating makefiles" -all_files=$(awk '/^OBJ = /, /^\\s*$/ ' \ - '{' \ - 'sub("^OBJ = ", "");' \ - 'sub(".@OBJEXT@[[:blank:]]*\\\\\\\\", "");' \ - 'sub("\\\\$\\\\(POSIX_OBJ\\\\)", "");' \ - 'print;' \ - '}' \ - "${PCRE}/Makefile.in") - -# Headers. -included_files="pcre.h pcre_internal.h ucp.h ucpinternal.h" - -# Generate Makefile.am. -cat $IN/Makefile.am-1 > Makefile.am -for name in $all_files; do - echo " $name.c \\" >> Makefile.am - if [ "${name}" != pcre_chartables ]; then - # pcre_chartables.c is a generated file. - cp "${PCRE}/${name}.c" . - fi -done -for f in $included_files; do - echo " $f \\" >> Makefile.am - cp "${PCRE}/${f}" . -done -cat $IN/Makefile.am-2 >> Makefile.am - -echo "Patching PCRE" - -# Copy the license. -cp "${PCRE}/COPYING" . - -# Use glib for memory allocation. -patch > /dev/null < $IN/memory.patch - -# Copy the modified version of pcre_valid_utf8.c. -cp $IN/pcre_valid_utf8.c . - -# Copy the modified version of pcre_ucp_searchfuncs.c that uses glib -# for Unicode properties. -cp $IN/pcre_ucp_searchfuncs.c . -patch > /dev/null < $IN/ucp.patch - -# Remove the digitab array in pcre_compile.c. -patch > /dev/null < $IN/digitab.patch -sed -i -e 's/(digitab\[\(.*\)\] & ctype_digit)/g_ascii_isdigit(\1)/' pcre_compile.c -sed -i -e 's/(digitab\[\(.*\)\] & ctype_xdigit)/g_ascii_isxdigit(\1)/' pcre_compile.c - -# Reduce the number of relocations. -python $IN/make_utt.py -patch > /dev/null < $IN/utt.patch -patch > /dev/null < $IN/table-reduction.patch - -# Copy back the old SVN directory. -mv ../tmp-pcre-svn .svn - - -cat << EOF - -Update completed. You now should check that everything is working. -Remember to update the regex syntax doc with the new features -(docs/reference/glib/regex-syntax.sgml) and to run the tests. -EOF - diff --git a/gmodule/gmodule-dl.c b/gmodule/gmodule-dl.c index bb2df6836..c1408212a 100644 --- a/gmodule/gmodule-dl.c +++ b/gmodule/gmodule-dl.c @@ -28,6 +28,7 @@ #include "config.h" #include <dlfcn.h> +#include <glib.h> /* Perl includes <nlist.h> and <link.h> instead of <dlfcn.h> on some systems? */ @@ -73,11 +74,46 @@ #endif /* RTLD_GLOBAL */ -/* --- functions --- */ -static gchar* +/* According to POSIX.1-2001, dlerror() is not necessarily thread-safe + * (see https://pubs.opengroup.org/onlinepubs/009695399/), and so must be + * called within the same locked section as the dlopen()/dlsym() call which + * may have caused an error. + * + * However, some libc implementations, such as glibc, implement dlerror() using + * thread-local storage, so are thread-safe. As of early 2021: + * - glibc is thread-safe: https://github.com/bminor/glibc/blob/HEAD/dlfcn/libc_dlerror_result.c + * - uclibc-ng is not thread-safe: https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git/tree/ldso/libdl/libdl.c?id=132decd2a043d0ccf799f42bf89f3ae0c11e95d5#n1075 + * - Other libc implementations have not been checked, and no problems have + * been reported with them in 10 years, so default to assuming that they + * don’t need additional thread-safety from GLib + */ +#if defined(__UCLIBC__) +G_LOCK_DEFINE_STATIC (errors); +#else +#define DLERROR_IS_THREADSAFE 1 +#endif + +static void +lock_dlerror (void) +{ +#ifndef DLERROR_IS_THREADSAFE + G_LOCK (errors); +#endif +} + +static void +unlock_dlerror (void) +{ +#ifndef DLERROR_IS_THREADSAFE + G_UNLOCK (errors); +#endif +} + +/* This should be called with lock_dlerror() held */ +static const gchar * fetch_dlerror (gboolean replace_null) { - gchar *msg = dlerror (); + const gchar *msg = dlerror (); /* make sure we always return an error message != NULL, if * expected to do so. */ @@ -95,10 +131,12 @@ _g_module_open (const gchar *file_name, { gpointer handle; + lock_dlerror (); handle = dlopen (file_name, (bind_local ? 0 : RTLD_GLOBAL) | (bind_lazy ? RTLD_LAZY : RTLD_NOW)); if (!handle) g_module_set_error (fetch_dlerror (TRUE)); + unlock_dlerror (); return handle; } @@ -119,6 +157,7 @@ _g_module_self (void) * always returns 'undefined symbol'. Only if RTLD_DEFAULT or * NULL is given, dlsym returns an appropriate pointer. */ + lock_dlerror (); #if defined(__BIONIC__) handle = RTLD_DEFAULT; #else @@ -126,6 +165,7 @@ _g_module_self (void) #endif if (!handle) g_module_set_error (fetch_dlerror (TRUE)); + unlock_dlerror (); return handle; } @@ -137,8 +177,10 @@ _g_module_close (gpointer handle) if (handle != RTLD_DEFAULT) #endif { + lock_dlerror (); if (dlclose (handle) != 0) - g_module_set_error (fetch_dlerror (TRUE)); + g_module_set_error (fetch_dlerror (TRUE)); + unlock_dlerror (); } } @@ -147,13 +189,15 @@ _g_module_symbol (gpointer handle, const gchar *symbol_name) { gpointer p; - gchar *msg; + const gchar *msg; + lock_dlerror (); fetch_dlerror (FALSE); p = dlsym (handle, symbol_name); msg = fetch_dlerror (FALSE); if (msg) g_module_set_error (msg); + unlock_dlerror (); return p; } diff --git a/gobject/gboxed.c b/gobject/gboxed.c index 194251383..ae48df566 100644 --- a/gobject/gboxed.c +++ b/gobject/gboxed.c @@ -175,6 +175,7 @@ G_DEFINE_BOXED_TYPE (GChecksum, g_checksum, g_checksum_copy, g_checksum_free) G_DEFINE_BOXED_TYPE (GUri, g_uri, g_uri_ref, g_uri_unref) G_DEFINE_BOXED_TYPE (GOptionGroup, g_option_group, g_option_group_ref, g_option_group_unref) +G_DEFINE_BOXED_TYPE (GPatternSpec, g_pattern_spec, g_pattern_spec_copy, g_pattern_spec_free); /* This one can't use G_DEFINE_BOXED_TYPE (GStrv, g_strv, g_strdupv, g_strfreev) */ GType diff --git a/gobject/glib-types.h b/gobject/glib-types.h index cdccdaab4..808284622 100644 --- a/gobject/glib-types.h +++ b/gobject/glib-types.h @@ -315,6 +315,15 @@ typedef gsize GType; */ #define G_TYPE_TREE (g_tree_get_type ()) +/** + * G_TYPE_PATTERN_SPEC: + * + * The #GType for #GPatternSpec. + * + * Since: 2.70 + */ +#define G_TYPE_PATTERN_SPEC (g_pattern_spec_get_type ()) + GLIB_AVAILABLE_IN_ALL GType g_date_get_type (void) G_GNUC_CONST; GLIB_AVAILABLE_IN_ALL @@ -375,6 +384,8 @@ GLIB_AVAILABLE_IN_2_66 GType g_uri_get_type (void) G_GNUC_CONST; GLIB_AVAILABLE_IN_2_68 GType g_tree_get_type (void) G_GNUC_CONST; +GLIB_AVAILABLE_IN_2_70 +GType g_pattern_spec_get_type (void) G_GNUC_CONST; GLIB_DEPRECATED_FOR('G_TYPE_VARIANT') GType g_variant_get_gtype (void) G_GNUC_CONST; diff --git a/gobject/gobject.c b/gobject/gobject.c index 750a7d120..a88682360 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -3186,6 +3186,62 @@ gpointer } /** + * g_object_take_ref: (skip) + * @object: (type GObject.Object): a #GObject + * + * If @object is floating, sink it. Otherwise, do nothing. + * + * In other words, this function will convert a floating reference (if + * present) into a full reference. + * + * Typically you want to use g_object_ref_sink() in order to + * automatically do the correct thing with respect to floating or + * non-floating references, but there is one specific scenario where + * this function is helpful. + * + * The situation where this function is helpful is when creating an API + * that allows the user to provide a callback function that returns a + * GObject. We certainly want to allow the user the flexibility to + * return a non-floating reference from this callback (for the case + * where the object that is being returned already exists). + * + * At the same time, the API style of some popular GObject-based + * libraries (such as Gtk) make it likely that for newly-created GObject + * instances, the user can be saved some typing if they are allowed to + * return a floating reference. + * + * Using this function on the return value of the user's callback allows + * the user to do whichever is more convenient for them. The caller will + * alway receives exactly one full reference to the value: either the + * one that was returned in the first place, or a floating reference + * that has been converted to a full reference. + * + * This function has an odd interaction when combined with + * g_object_ref_sink() running at the same time in another thread on + * the same #GObject instance. If g_object_ref_sink() runs first then + * the result will be that the floating reference is converted to a hard + * reference. If g_object_take_ref() runs first then the result will be + * that the floating reference is converted to a hard reference and an + * additional reference on top of that one is added. It is best to avoid + * this situation. + * + * Since: 2.70 + * + * Returns: (type GObject.Object) (transfer full): @object + */ +gpointer +g_object_take_ref (gpointer _object) +{ + GObject *object = _object; + g_return_val_if_fail (G_IS_OBJECT (object), object); + g_return_val_if_fail (g_atomic_int_get (&object->ref_count) >= 1, object); + + floating_flag_handler (object, -1); + + return object; +} + +/** * g_object_force_floating: * @object: a #GObject * @@ -3319,7 +3375,8 @@ g_object_add_toggle_ref (GObject *object, * @notify: a function to call when this reference is the * last reference to the object, or is no longer * the last reference. - * @data: data to pass to @notify + * @data: (nullable): data to pass to @notify, or %NULL to + * match any toggle refs with the @notify argument. * * Removes a reference added with g_object_add_toggle_ref(). The * reference count of the object is decreased by one. @@ -3345,7 +3402,7 @@ g_object_remove_toggle_ref (GObject *object, for (i = 0; i < tstack->n_toggle_refs; i++) if (tstack->toggle_refs[i].notify == notify && - tstack->toggle_refs[i].data == data) + (tstack->toggle_refs[i].data == data || data == NULL)) { found_one = TRUE; tstack->n_toggle_refs -= 1; diff --git a/gobject/gobject.h b/gobject/gobject.h index 125aed876..86e2b7de1 100644 --- a/gobject/gobject.h +++ b/gobject/gobject.h @@ -28,11 +28,6 @@ #include <gobject/gsignal.h> #include <gobject/gboxed.h> -#if defined(glib_typeof_2_68) && GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68 -/* for glib_typeof */ -#include <type_traits> -#endif - G_BEGIN_DECLS /* --- type macros --- */ @@ -499,6 +494,8 @@ GLIB_AVAILABLE_IN_ALL gboolean g_object_is_floating (gpointer object); GLIB_AVAILABLE_IN_ALL gpointer g_object_ref_sink (gpointer object); +GLIB_AVAILABLE_IN_2_70 +gpointer g_object_take_ref (gpointer object); GLIB_AVAILABLE_IN_ALL gpointer g_object_ref (gpointer object); GLIB_AVAILABLE_IN_ALL @@ -518,7 +515,7 @@ GLIB_AVAILABLE_IN_ALL void g_object_remove_weak_pointer (GObject *object, gpointer *weak_pointer_location); -#if defined(glib_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_56 && (!defined(glib_typeof_2_68) || GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_68) +#if defined(glib_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_56 /* Make reference APIs type safe with macros */ #define g_object_ref(Obj) ((glib_typeof (Obj)) (g_object_ref) (Obj)) #define g_object_ref_sink(Obj) ((glib_typeof (Obj)) (g_object_ref_sink) (Obj)) diff --git a/gobject/gsignal.h b/gobject/gsignal.h index 64aa9d6a8..b027f54c0 100644 --- a/gobject/gsignal.h +++ b/gobject/gsignal.h @@ -87,8 +87,11 @@ typedef gboolean (*GSignalEmissionHook) (GSignalInvocationHint *ihint, * value returned by the last callback. * * Returns: The accumulator function returns whether the signal emission - * should be aborted. Returning %FALSE means to abort the - * current emission and %TRUE is returned for continuation. + * should be aborted. Returning %TRUE will continue with + * the signal emission. Returning %FALSE will abort the current emission. + * Since 2.62, returning %FALSE will skip to the CLEANUP stage. In this case, + * emission will occur as normal in the CLEANUP stage and the handler's + * return value will be accumulated. */ typedef gboolean (*GSignalAccumulator) (GSignalInvocationHint *ihint, GValue *return_accu, diff --git a/gobject/gtype.c b/gobject/gtype.c index 94e23b814..2cdbe7ce4 100644 --- a/gobject/gtype.c +++ b/gobject/gtype.c @@ -1100,7 +1100,8 @@ type_data_make_W (TypeNode *node, vtable = pnode->data->common.value_table; else { - static const GTypeValueTable zero_vtable = { NULL, }; + static const GTypeValueTable zero_vtable = + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; value_table = &zero_vtable; } diff --git a/gobject/gtype.h b/gobject/gtype.h index 621c6514d..5f9766978 100644 --- a/gobject/gtype.h +++ b/gobject/gtype.h @@ -2108,7 +2108,7 @@ type_name##_get_type (void) \ /* Only use this in non-C++ on GCC >= 2.7, except for Darwin/ppc64. * See https://bugzilla.gnome.org/show_bug.cgi?id=647145 */ -#if !defined (__cplusplus) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)) && !(defined (__APPLE__) && defined (__ppc64__)) +#if !defined (__cplusplus) && (G_GNUC_CHECK_VERSION(2, 7)) && !(defined (__APPLE__) && defined (__ppc64__)) #define _G_DEFINE_BOXED_TYPE_BEGIN(TypeName, type_name, copy_func, free_func) \ static GType type_name##_get_type_once (void); \ \ diff --git a/gobject/gvaluetypes.c b/gobject/gvaluetypes.c index 732ea2b08..60d7b6647 100644 --- a/gobject/gvaluetypes.c +++ b/gobject/gvaluetypes.c @@ -1024,7 +1024,7 @@ g_value_get_double (const GValue *value) * @value: a valid #GValue of type %G_TYPE_STRING * @v_string: (nullable): caller-owned string to be duplicated for the #GValue * - * Set the contents of a %G_TYPE_STRING #GValue to @v_string. + * Set the contents of a %G_TYPE_STRING #GValue to a copy of @v_string. */ void g_value_set_string (GValue *value, diff --git a/gobject/tests/binding.c b/gobject/tests/binding.c index 61002f4fb..e63dd1e6e 100644 --- a/gobject/tests/binding.c +++ b/gobject/tests/binding.c @@ -574,8 +574,7 @@ binding_chain (void) BindingSource *c = g_object_new (binding_source_get_type (), NULL); GBinding *binding_1, *binding_2; - g_test_bug_base ("http://bugzilla.gnome.org/"); - g_test_bug ("621782"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=621782"); /* A -> B, B -> C */ binding_1 = g_object_bind_property (a, "foo", b, "foo", G_BINDING_BIDIRECTIONAL); @@ -794,7 +793,7 @@ binding_unbind_multiple (void) GBinding *binding; guint i; - g_test_bug ("1373"); + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1373"); binding = g_object_bind_property (source, "foo", target, "bar", @@ -1081,8 +1080,6 @@ main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("https://gitlab.gnome.org/GNOME/glib/issues/"); - g_test_add_func ("/binding/default", binding_default); g_test_add_func ("/binding/canonicalisation", binding_canonicalisation); g_test_add_func ("/binding/bidirectional", binding_bidirectional); diff --git a/gobject/tests/boxed.c b/gobject/tests/boxed.c index 0c8872a82..f961a2f87 100644 --- a/gobject/tests/boxed.c +++ b/gobject/tests/boxed.c @@ -645,6 +645,29 @@ test_boxed_tree (void) g_value_unset (&value); } +static void +test_boxed_pattern_spec (void) +{ + GPatternSpec *ps, *ps2; + GValue value = G_VALUE_INIT; + + g_value_init (&value, G_TYPE_PATTERN_SPEC); + g_assert_true (G_VALUE_HOLDS_BOXED (&value)); + + ps = g_pattern_spec_new ("*abc*?cde"); + g_value_take_boxed (&value, ps); + + ps2 = g_value_get_boxed (&value); + g_assert_true (ps == ps2); + + ps2 = g_value_dup_boxed (&value); + g_assert_true (ps != ps2); + g_assert_true (g_pattern_spec_equal (ps, ps2)); + g_pattern_spec_free (ps2); + + g_value_unset (&value); +} + int main (int argc, char *argv[]) { @@ -675,6 +698,7 @@ main (int argc, char *argv[]) g_test_add_func ("/boxed/thread", test_boxed_thread); g_test_add_func ("/boxed/checksum", test_boxed_checksum); g_test_add_func ("/boxed/tree", test_boxed_tree); + g_test_add_func ("/boxed/patternspec", test_boxed_pattern_spec); return g_test_run (); } diff --git a/gobject/tests/ifaceproperties.c b/gobject/tests/ifaceproperties.c index 4d0053eea..cb7acf4ec 100644 --- a/gobject/tests/ifaceproperties.c +++ b/gobject/tests/ifaceproperties.c @@ -618,7 +618,7 @@ test_not_overridden (void) if (!g_test_undefined ()) return; - g_test_bug ("637738"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=637738"); g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*Base2Object doesn't implement property 'prop3' from interface 'TestIface'*"); @@ -632,7 +632,6 @@ int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ("/interface/properties/set", test_set); g_test_add_func ("/interface/properties/notify", test_notify); diff --git a/gobject/tests/object.c b/gobject/tests/object.c index 3e85995c2..2519b0034 100644 --- a/gobject/tests/object.c +++ b/gobject/tests/object.c @@ -122,7 +122,7 @@ test_object_constructor_infanticide (void) GObject *obj; int i; - g_test_bug ("661576"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=661576"); for (i = 0; i < 1000; i++) { @@ -142,7 +142,6 @@ int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ("/object/constructor/singleton", test_object_constructor_singleton); g_test_add_func ("/object/constructor/infanticide", test_object_constructor_infanticide); diff --git a/gobject/tests/properties.c b/gobject/tests/properties.c index 297713d5a..3695ee123 100644 --- a/gobject/tests/properties.c +++ b/gobject/tests/properties.c @@ -322,7 +322,7 @@ properties_construct (void) gboolean b; gchar *s; - g_test_bug ("630357"); + g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=630357"); /* more than 16 args triggers a realloc in g_object_new_valist() */ obj = g_object_new (test_object_get_type (), @@ -638,8 +638,6 @@ main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); - g_test_bug_base ("http://bugzilla.gnome.org/"); - g_test_add_func ("/properties/install", properties_install); g_test_add_func ("/properties/notify", properties_notify); g_test_add_func ("/properties/notify-queue", properties_notify_queue); diff --git a/gobject/tests/reference.c b/gobject/tests/reference.c index c6f4d5127..04645e14a 100644 --- a/gobject/tests/reference.c +++ b/gobject/tests/reference.c @@ -322,6 +322,20 @@ test_initially_unowned (void) g_object_ref_sink (obj); g_object_unref (obj); + + obj = g_object_new (G_TYPE_INITIALLY_UNOWNED, NULL); + g_assert_true (g_object_is_floating (obj)); + g_assert_cmpint (obj->ref_count, ==, 1); + + g_object_take_ref (obj); + g_assert_false (g_object_is_floating (obj)); + g_assert_cmpint (obj->ref_count, ==, 1); + + g_object_take_ref (obj); + g_assert_false (g_object_is_floating (obj)); + g_assert_cmpint (obj->ref_count, ==, 1); + + g_object_unref (obj); } static void diff --git a/meson.build b/meson.build index a0223ce5b..1b54fdcae 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('glib', 'c', 'cpp', - version : '2.68.4', + version : '2.69.0', # NOTE: We keep this pinned at 0.49 because that's what Debian 10 ships meson_version : '>= 0.49.2', default_options : [ @@ -14,18 +14,23 @@ cxx = meson.get_compiler('cpp') cc_can_run = not meson.is_cross_build() or meson.has_exe_wrapper() -if cc.get_id() == 'msvc' +if cc.get_argument_syntax() == 'msvc' # Ignore several spurious warnings for things glib does very commonly + # (also for clang-cl) + add_project_arguments('/FImsvc_recommended_pragmas.h',language : 'c') +endif + +if cc.get_id() == 'msvc' # If a warning is completely useless and spammy, use '/wdXXXX' to suppress it # If a warning is harmless but hard to fix, use '/woXXXX' so it's shown once # NOTE: Only add warnings here if you are sure they're spurious add_project_arguments('/wd4035', '/wd4715', '/wd4116', - '/wd4046', '/wd4068', '/wo4090', '/FImsvc_recommended_pragmas.h',language : 'c') + '/wd4046', '/wd4068', '/wo4090',language : 'c') + # Set the input and exec encoding to utf-8, like is the default with GCC + add_project_arguments(cc.get_supported_arguments(['/utf-8']), language: 'c') # Disable SAFESEH with MSVC for plugins and libs that use external deps that # are built with MinGW noseh_link_args = ['/SAFESEH:NO'] - # Set the input and exec encoding to utf-8, like is the default with GCC - add_project_arguments(cc.get_supported_arguments(['/utf-8']), language: 'c') else noseh_link_args = [] # -mms-bitfields vs -fnative-struct ? @@ -1185,6 +1190,15 @@ if cc.links('''#ifndef _GNU_SOURCE glib_conf.set('HAVE_LANGINFO_ABALTMON', 1) endif +# Check for nl_langinfo and _NL_TIME_CODESET +if cc.links('''#include <langinfo.h> + int main (int argc, char ** argv) { + char *codeset = nl_langinfo (_NL_TIME_CODESET); + return 0; + }''', name : 'nl_langinfo and _NL_TIME_CODESET') + glib_conf.set('HAVE_LANGINFO_TIME_CODESET', 1) +endif + # Check if C compiler supports the 'signed' keyword if not cc.compiles('''signed char x;''', name : 'signed') glib_conf.set('signed', '/* NOOP */') @@ -1965,46 +1979,37 @@ else endif endif -if get_option('internal_pcre') - pcre = [] - use_system_pcre = false -else - pcre = dependency('libpcre', version: '>= 8.31', required : false) # Should check for Unicode support, too. FIXME - if not pcre.found() - if cc.get_id() == 'msvc' or cc.get_id() == 'clang-cl' - # MSVC: Search for the PCRE library by the configuration, which corresponds - # to the output of CMake builds of PCRE. Note that debugoptimized - # is really a Release build with .PDB files. - if vs_crt == 'debug' - pcre = cc.find_library('pcred', required : false) - else - pcre = cc.find_library('pcre', required : false) - endif +pcre = dependency('libpcre', version: '>= 8.31', required : false) # Should check for Unicode support, too. FIXME +if not pcre.found() + if cc.get_id() == 'msvc' or cc.get_id() == 'clang-cl' + # MSVC: Search for the PCRE library by the configuration, which corresponds + # to the output of CMake builds of PCRE. Note that debugoptimized + # is really a Release build with .PDB files. + if vs_crt == 'debug' + pcre = cc.find_library('pcred', required : false) + else + pcre = cc.find_library('pcre', required : false) endif endif - use_system_pcre = pcre.found() endif -glib_conf.set('USE_SYSTEM_PCRE', use_system_pcre) - -use_pcre_static_flag = false -if host_system == 'windows' - if not use_system_pcre - use_pcre_static_flag = true - else - pcre_static = cc.links('''#define PCRE_STATIC - #include <pcre.h> - int main() { - void *p = NULL; - pcre_free(p); - return 0; - }''', - dependencies: pcre, - name : 'Windows system PCRE is a static build') - if pcre_static - use_pcre_static_flag = true - endif - endif +# Try again with the fallback +if not pcre.found() + pcre = dependency('libpcre', required : true, fallback : ['libpcre', 'pcre_dep']) + use_pcre_static_flag = true +elif host_system == 'windows' + pcre_static = cc.links('''#define PCRE_STATIC + #include <pcre.h> + int main() { + void *p = NULL; + pcre_free(p); + return 0; + }''', + dependencies: pcre, + name : 'Windows system PCRE is a static build') + use_pcre_static_flag = pcre_static +else + use_pcre_static_flag = false endif libm = cc.find_library('m', required : false) @@ -2038,13 +2043,13 @@ endif # FIXME: glib-gettext.m4 has much more checks to detect broken/uncompatible # implementations. This could be extended if issues are found in some platforms. libintl_deps = [] -if cc.has_function('ngettext') +if cc.has_function('ngettext', args : osx_ldflags) have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset') else # First just find the bare library. libintl = cc.find_library('intl', required : false) # The bare library probably won't link without help if it's static. - if libintl.found() and not cc.has_function('ngettext', dependencies : libintl) + if libintl.found() and not cc.has_function('ngettext', args : osx_ldflags, dependencies : libintl) libintl_iconv = cc.find_library('iconv', required : false) # libintl supports different threading APIs, which may not # require additional flags, but it defaults to using pthreads if @@ -2054,10 +2059,10 @@ else # also defining the macros with the -pthread flag. libintl_pthread = cc.find_library('pthread', required : false) # Try linking with just libiconv. - if libintl_iconv.found() and cc.has_function('ngettext', dependencies : [libintl, libintl_iconv]) + if libintl_iconv.found() and cc.has_function('ngettext', args : osx_ldflags, dependencies : [libintl, libintl_iconv]) libintl_deps += [libintl_iconv] # Then also try linking with pthreads. - elif libintl_iconv.found() and libintl_pthread.found() and cc.has_function('ngettext', dependencies : [libintl, libintl_iconv, libintl_pthread]) + elif libintl_iconv.found() and libintl_pthread.found() and cc.has_function('ngettext', args : osx_ldflags, dependencies : [libintl, libintl_iconv, libintl_pthread]) libintl_deps += [libintl_iconv, libintl_pthread] else libintl = disabler() @@ -2069,7 +2074,7 @@ else have_bind_textdomain_codeset = true # proxy-libintl supports it else libintl_deps = [libintl] + libintl_deps - have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset', + have_bind_textdomain_codeset = cc.has_function('bind_textdomain_codeset', args : osx_ldflags, dependencies : libintl_deps) endif endif diff --git a/meson_options.txt b/meson_options.txt index 072765361..6cd7bc90a 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -34,11 +34,6 @@ option('libmount', value : 'auto', description : 'build with libmount support') -option('internal_pcre', - type : 'boolean', - value : false, - description : 'whether to use internal PCRE') - option('man', type : 'boolean', value : false, diff --git a/msvc_recommended_pragmas.h b/msvc_recommended_pragmas.h index e70698712..051a02ae4 100644 --- a/msvc_recommended_pragmas.h +++ b/msvc_recommended_pragmas.h @@ -1,10 +1,11 @@ #ifndef _MSC_VER -#pragma error "This header is for Microsoft VC only." +#pragma error "This header is for Microsoft VC or clang-cl only." #endif /* _MSC_VER */ /* Make MSVC more pedantic, this is a recommended pragma list * from _Win32_Programming_ by Rector and Newcomer. */ +#ifndef __clang__ #pragma warning(error:4002) /* too many actual parameters for macro */ #pragma warning(error:4003) /* not enough actual parameters for macro */ #pragma warning(1:4010) /* single-line comment contains line-continuation character */ @@ -33,6 +34,7 @@ #pragma warning(disable:4305) /* No truncation from int to char warnings */ #pragma warning(error:4819) /* The file contains a character that cannot be represented in the current code page */ +#endif /* __clang__ */ /* work around Microsoft's premature attempt to deprecate the C-Library */ #define _CRT_SECURE_NO_WARNINGS @@ -14,16 +14,17 @@ msgid "" msgstr "" "Project-Id-Version: glib.HEAD.he\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/glib/issues\n" -"POT-Creation-Date: 2020-08-22 13:31+0000\n" -"PO-Revision-Date: 2020-09-28 23:42+0300\n" -"Last-Translator: Yosef Or Boczko <yoseforb@gmail.com>\n" +"POT-Creation-Date: 2021-03-22 11:48+0000\n" +"PO-Revision-Date: 2021-05-28 22:57+0300\n" +"Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n" "Language-Team: Hebrew <yoseforb@gmail.com>\n" "Language: he\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" -"X-Generator: Gtranslator 3.36.0\n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n==2 ? 1 : n>10 && n%10==0 ? " +"2 : 3);\n" +"X-Generator: Poedit 2.4.3\n" #: gio/gapplication.c:500 msgid "GApplication options" @@ -62,90 +63,90 @@ msgstr "Print version" msgid "Print version information and exit" msgstr "Print version information and exit" -#: gio/gapplication-tool.c:52 +#: gio/gapplication-tool.c:53 msgid "List applications" msgstr "List applications" -#: gio/gapplication-tool.c:53 +#: gio/gapplication-tool.c:54 msgid "List the installed D-Bus activatable applications (by .desktop files)" msgstr "List the installed D-Bus activatable applications (by .desktop files)" -#: gio/gapplication-tool.c:55 +#: gio/gapplication-tool.c:57 msgid "Launch an application" msgstr "Launch an application" -#: gio/gapplication-tool.c:56 +#: gio/gapplication-tool.c:58 msgid "Launch the application (with optional files to open)" msgstr "Launch the application (with optional files to open)" -#: gio/gapplication-tool.c:57 +#: gio/gapplication-tool.c:59 msgid "APPID [FILE…]" msgstr "APPID [FILE…]" -#: gio/gapplication-tool.c:59 +#: gio/gapplication-tool.c:61 msgid "Activate an action" msgstr "Activate an action" -#: gio/gapplication-tool.c:60 +#: gio/gapplication-tool.c:62 msgid "Invoke an action on the application" msgstr "Invoke an action on the application" -#: gio/gapplication-tool.c:61 +#: gio/gapplication-tool.c:63 msgid "APPID ACTION [PARAMETER]" msgstr "APPID ACTION [PARAMETER]" -#: gio/gapplication-tool.c:63 +#: gio/gapplication-tool.c:65 msgid "List available actions" msgstr "List available actions" -#: gio/gapplication-tool.c:64 +#: gio/gapplication-tool.c:66 msgid "List static actions for an application (from .desktop file)" msgstr "List static actions for an application (from .desktop file)" -#: gio/gapplication-tool.c:65 gio/gapplication-tool.c:71 +#: gio/gapplication-tool.c:67 gio/gapplication-tool.c:73 msgid "APPID" msgstr "APPID" -#: gio/gapplication-tool.c:70 gio/gapplication-tool.c:133 gio/gdbus-tool.c:102 +#: gio/gapplication-tool.c:72 gio/gapplication-tool.c:135 gio/gdbus-tool.c:106 #: gio/gio-tool.c:224 msgid "COMMAND" msgstr "COMMAND" -#: gio/gapplication-tool.c:70 +#: gio/gapplication-tool.c:72 msgid "The command to print detailed help for" msgstr "The command to print detailed help for" -#: gio/gapplication-tool.c:71 +#: gio/gapplication-tool.c:73 msgid "Application identifier in D-Bus format (eg: org.example.viewer)" msgstr "Application identifier in D-Bus format (eg: org.example.viewer)" -#: gio/gapplication-tool.c:72 gio/glib-compile-resources.c:738 +#: gio/gapplication-tool.c:74 gio/glib-compile-resources.c:738 #: gio/glib-compile-resources.c:744 gio/glib-compile-resources.c:772 #: gio/gresource-tool.c:500 gio/gresource-tool.c:566 msgid "FILE" msgstr "FILE" -#: gio/gapplication-tool.c:72 +#: gio/gapplication-tool.c:74 msgid "Optional relative or absolute filenames, or URIs to open" msgstr "Optional relative or absolute filenames, or URIs to open" -#: gio/gapplication-tool.c:73 +#: gio/gapplication-tool.c:75 msgid "ACTION" msgstr "ACTION" -#: gio/gapplication-tool.c:73 +#: gio/gapplication-tool.c:75 msgid "The action name to invoke" msgstr "The action name to invoke" -#: gio/gapplication-tool.c:74 +#: gio/gapplication-tool.c:76 msgid "PARAMETER" msgstr "PARAMETER" -#: gio/gapplication-tool.c:74 +#: gio/gapplication-tool.c:76 msgid "Optional parameter to the action invocation, in GVariant format" msgstr "Optional parameter to the action invocation, in GVariant format" -#: gio/gapplication-tool.c:96 gio/gresource-tool.c:531 gio/gsettings-tool.c:659 +#: gio/gapplication-tool.c:98 gio/gresource-tool.c:531 gio/gsettings-tool.c:659 #, c-format msgid "" "Unknown command %s\n" @@ -154,26 +155,26 @@ msgstr "" "Unknown command %s\n" "\n" -#: gio/gapplication-tool.c:101 +#: gio/gapplication-tool.c:103 msgid "Usage:\n" msgstr "Usage:\n" -#: gio/gapplication-tool.c:114 gio/gresource-tool.c:556 +#: gio/gapplication-tool.c:116 gio/gresource-tool.c:556 #: gio/gsettings-tool.c:694 msgid "Arguments:\n" msgstr "Arguments:\n" -#: gio/gapplication-tool.c:133 gio/gio-tool.c:224 +#: gio/gapplication-tool.c:135 gio/gio-tool.c:224 msgid "[ARGS…]" msgstr "[ARGS…]" -#: gio/gapplication-tool.c:134 +#: gio/gapplication-tool.c:136 #, c-format msgid "Commands:\n" msgstr "Commands:\n" #. Translators: do not translate 'help', but please translate 'COMMAND'. -#: gio/gapplication-tool.c:146 +#: gio/gapplication-tool.c:148 #, c-format msgid "" "Use “%s help COMMAND” to get detailed help.\n" @@ -182,7 +183,7 @@ msgstr "" "Use “%s help COMMAND” to get detailed help.\n" "\n" -#: gio/gapplication-tool.c:165 +#: gio/gapplication-tool.c:167 #, c-format msgid "" "%s command requires an application id to directly follow\n" @@ -191,13 +192,13 @@ msgstr "" "%s command requires an application id to directly follow\n" "\n" -#: gio/gapplication-tool.c:171 +#: gio/gapplication-tool.c:173 #, c-format msgid "invalid application id: “%s”\n" msgstr "invalid application id: “%s”\n" #. Translators: %s is replaced with a command name like 'list-actions' -#: gio/gapplication-tool.c:182 +#: gio/gapplication-tool.c:184 #, c-format msgid "" "“%s” takes no arguments\n" @@ -206,21 +207,21 @@ msgstr "" "“%s” takes no arguments\n" "\n" -#: gio/gapplication-tool.c:266 +#: gio/gapplication-tool.c:268 #, c-format msgid "unable to connect to D-Bus: %s\n" msgstr "unable to connect to D-Bus: %s\n" -#: gio/gapplication-tool.c:286 +#: gio/gapplication-tool.c:288 #, c-format msgid "error sending %s message to application: %s\n" msgstr "error sending %s message to application: %s\n" -#: gio/gapplication-tool.c:317 +#: gio/gapplication-tool.c:319 msgid "action name must be given after application id\n" msgstr "action name must be given after application id\n" -#: gio/gapplication-tool.c:325 +#: gio/gapplication-tool.c:327 #, c-format msgid "" "invalid action name: “%s”\n" @@ -229,25 +230,25 @@ msgstr "" "invalid action name: “%s”\n" "action names must consist of only alphanumerics, “-” and “.”\n" -#: gio/gapplication-tool.c:344 +#: gio/gapplication-tool.c:346 #, c-format msgid "error parsing action parameter: %s\n" msgstr "error parsing action parameter: %s\n" -#: gio/gapplication-tool.c:356 +#: gio/gapplication-tool.c:358 msgid "actions accept a maximum of one parameter\n" msgstr "actions accept a maximum of one parameter\n" -#: gio/gapplication-tool.c:411 +#: gio/gapplication-tool.c:413 msgid "list-actions command takes only the application id" msgstr "list-actions command takes only the application id" -#: gio/gapplication-tool.c:421 +#: gio/gapplication-tool.c:423 #, c-format msgid "unable to find desktop file for application %s\n" msgstr "unable to find desktop file for application %s\n" -#: gio/gapplication-tool.c:466 +#: gio/gapplication-tool.c:468 #, c-format msgid "" "unrecognised command: %s\n" @@ -257,8 +258,8 @@ msgstr "" "\n" #: gio/gbufferedinputstream.c:420 gio/gbufferedinputstream.c:498 -#: gio/ginputstream.c:179 gio/ginputstream.c:379 gio/ginputstream.c:617 -#: gio/ginputstream.c:1019 gio/goutputstream.c:223 gio/goutputstream.c:1049 +#: gio/ginputstream.c:179 gio/ginputstream.c:379 gio/ginputstream.c:646 +#: gio/ginputstream.c:1048 gio/goutputstream.c:223 gio/goutputstream.c:1049 #: gio/gpollableinputstream.c:205 gio/gpollableoutputstream.c:277 #, c-format msgid "Too large count value passed to %s" @@ -269,11 +270,11 @@ msgstr "Too large count value passed to %s" msgid "Seek not supported on base stream" msgstr "Seek not supported on base stream" -#: gio/gbufferedinputstream.c:937 +#: gio/gbufferedinputstream.c:938 msgid "Cannot truncate GBufferedInputStream" msgstr "Cannot truncate GBufferedInputStream" -#: gio/gbufferedinputstream.c:982 gio/ginputstream.c:1208 gio/giostream.c:300 +#: gio/gbufferedinputstream.c:983 gio/ginputstream.c:1237 gio/giostream.c:300 #: gio/goutputstream.c:2198 msgid "Stream is already closed" msgstr "Stream is already closed" @@ -282,7 +283,7 @@ msgstr "Stream is already closed" msgid "Truncate not supported on base stream" msgstr "Truncate not supported on base stream" -#: gio/gcancellable.c:319 gio/gdbusconnection.c:1862 gio/gdbusprivate.c:1413 +#: gio/gcancellable.c:319 gio/gdbusconnection.c:1872 gio/gdbusprivate.c:1416 #: gio/gsimpleasyncresult.c:871 gio/gsimpleasyncresult.c:897 #, c-format msgid "Operation was cancelled" @@ -301,25 +302,25 @@ msgid "Not enough space in destination" msgstr "Not enough space in destination" #: gio/gcharsetconverter.c:342 gio/gdatainputstream.c:848 -#: gio/gdatainputstream.c:1261 glib/gconvert.c:448 glib/gconvert.c:878 -#: glib/giochannel.c:1564 glib/giochannel.c:1606 glib/giochannel.c:2461 +#: gio/gdatainputstream.c:1266 glib/gconvert.c:448 glib/gconvert.c:878 +#: glib/giochannel.c:1573 glib/giochannel.c:1615 glib/giochannel.c:2470 #: glib/gutf8.c:875 glib/gutf8.c:1328 msgid "Invalid byte sequence in conversion input" msgstr "Invalid byte sequence in conversion input" #: gio/gcharsetconverter.c:347 glib/gconvert.c:456 glib/gconvert.c:792 -#: glib/giochannel.c:1571 glib/giochannel.c:2473 +#: glib/giochannel.c:1580 glib/giochannel.c:2482 #, c-format msgid "Error during conversion: %s" msgstr "Error during conversion: %s" -#: gio/gcharsetconverter.c:445 gio/gsocket.c:1133 +#: gio/gcharsetconverter.c:445 gio/gsocket.c:1143 msgid "Cancellable initialization not supported" msgstr "Cancellable initialization not supported" # *** This file should not be translated to hebrew, please only copy the english text *** # *** Old hebrew ranslation is commented for backup sake *** -#: gio/gcharsetconverter.c:456 glib/gconvert.c:321 glib/giochannel.c:1392 +#: gio/gcharsetconverter.c:456 glib/gconvert.c:321 glib/giochannel.c:1401 #, c-format msgid "Conversion from character set “%s” to “%s” is not supported" msgstr "Conversion from character set “%s” to “%s” is not supported" @@ -329,7 +330,7 @@ msgstr "Conversion from character set “%s” to “%s” is not supported" msgid "Could not open converter from “%s” to “%s”" msgstr "Could not open converter from “%s” to “%s”" -#: gio/gcontenttype.c:452 +#: gio/gcontenttype.c:454 #, c-format msgid "%s type" msgstr "%s type" @@ -367,17 +368,17 @@ msgstr "Credentials spoofing is not possible on this OS" msgid "Unexpected early end-of-stream" msgstr "Unexpected early end-of-stream" -#: gio/gdbusaddress.c:158 gio/gdbusaddress.c:232 gio/gdbusaddress.c:321 +#: gio/gdbusaddress.c:159 gio/gdbusaddress.c:233 gio/gdbusaddress.c:322 #, c-format msgid "Unsupported key “%s” in address entry “%s”" msgstr "Unsupported key “%s” in address entry “%s”" -#: gio/gdbusaddress.c:171 +#: gio/gdbusaddress.c:172 #, c-format msgid "Meaningless key/value pair combination in address entry “%s”" msgstr "Meaningless key/value pair combination in address entry “%s”" -#: gio/gdbusaddress.c:180 +#: gio/gdbusaddress.c:181 #, c-format msgid "" "Address “%s” is invalid (need exactly one of path, dir, tmpdir, or abstract " @@ -386,28 +387,28 @@ msgstr "" "Address “%s” is invalid (need exactly one of path, dir, tmpdir, or abstract " "keys)" -#: gio/gdbusaddress.c:247 gio/gdbusaddress.c:258 gio/gdbusaddress.c:273 -#: gio/gdbusaddress.c:336 gio/gdbusaddress.c:347 +#: gio/gdbusaddress.c:248 gio/gdbusaddress.c:259 gio/gdbusaddress.c:274 +#: gio/gdbusaddress.c:337 gio/gdbusaddress.c:348 #, c-format msgid "Error in address “%s” — the “%s” attribute is malformed" msgstr "Error in address “%s” — the “%s” attribute is malformed" -#: gio/gdbusaddress.c:417 gio/gdbusaddress.c:681 +#: gio/gdbusaddress.c:418 gio/gdbusaddress.c:682 #, c-format msgid "Unknown or unsupported transport “%s” for address “%s”" msgstr "Unknown or unsupported transport “%s” for address “%s”" -#: gio/gdbusaddress.c:461 +#: gio/gdbusaddress.c:462 #, c-format msgid "Address element “%s” does not contain a colon (:)" msgstr "Address element “%s” does not contain a colon (:)" -#: gio/gdbusaddress.c:470 +#: gio/gdbusaddress.c:471 #, c-format msgid "Transport name in address element “%s” must not be empty" msgstr "Transport name in address element “%s” must not be empty" -#: gio/gdbusaddress.c:491 +#: gio/gdbusaddress.c:492 #, c-format msgid "" "Key/Value pair %d, “%s”, in address element “%s” does not contain an equal " @@ -416,14 +417,14 @@ msgstr "" "Key/Value pair %d, “%s”, in address element “%s” does not contain an equal " "sign" -#: gio/gdbusaddress.c:502 +#: gio/gdbusaddress.c:503 #, c-format msgid "" "Key/Value pair %d, “%s”, in address element “%s” must not have an empty key" msgstr "" "Key/Value pair %d, “%s”, in address element “%s” must not have an empty key" -#: gio/gdbusaddress.c:516 +#: gio/gdbusaddress.c:517 #, c-format msgid "" "Error unescaping key or value in Key/Value pair %d, “%s”, in address element " @@ -432,7 +433,7 @@ msgstr "" "Error unescaping key or value in Key/Value pair %d, “%s”, in address element " "“%s”" -#: gio/gdbusaddress.c:588 +#: gio/gdbusaddress.c:589 #, c-format msgid "" "Error in address “%s” — the unix transport requires exactly one of the keys " @@ -441,75 +442,75 @@ msgstr "" "Error in address “%s” — the unix transport requires exactly one of the keys " "“path” or “abstract” to be set" -#: gio/gdbusaddress.c:624 +#: gio/gdbusaddress.c:625 #, c-format msgid "Error in address “%s” — the host attribute is missing or malformed" msgstr "Error in address “%s” — the host attribute is missing or malformed" -#: gio/gdbusaddress.c:638 +#: gio/gdbusaddress.c:639 #, c-format msgid "Error in address “%s” — the port attribute is missing or malformed" msgstr "Error in address “%s” — the port attribute is missing or malformed" -#: gio/gdbusaddress.c:652 +#: gio/gdbusaddress.c:653 #, c-format msgid "Error in address “%s” — the noncefile attribute is missing or malformed" msgstr "" "Error in address “%s” — the noncefile attribute is missing or malformed" -#: gio/gdbusaddress.c:673 +#: gio/gdbusaddress.c:674 msgid "Error auto-launching: " msgstr "Error auto-launching: " -#: gio/gdbusaddress.c:726 +#: gio/gdbusaddress.c:727 #, c-format msgid "Error opening nonce file “%s”: %s" msgstr "Error opening nonce file “%s”: %s" -#: gio/gdbusaddress.c:745 +#: gio/gdbusaddress.c:746 #, c-format msgid "Error reading from nonce file “%s”: %s" msgstr "Error reading from nonce file “%s”: %s" -#: gio/gdbusaddress.c:754 +#: gio/gdbusaddress.c:755 #, c-format msgid "Error reading from nonce file “%s”, expected 16 bytes, got %d" msgstr "Error reading from nonce file “%s”, expected 16 bytes, got %d" -#: gio/gdbusaddress.c:772 +#: gio/gdbusaddress.c:773 #, c-format msgid "Error writing contents of nonce file “%s” to stream:" msgstr "Error writing contents of nonce file “%s” to stream:" -#: gio/gdbusaddress.c:981 +#: gio/gdbusaddress.c:988 msgid "The given address is empty" msgstr "The given address is empty" -#: gio/gdbusaddress.c:1094 +#: gio/gdbusaddress.c:1101 #, c-format msgid "Cannot spawn a message bus when setuid" msgstr "Cannot spawn a message bus when setuid" -#: gio/gdbusaddress.c:1101 +#: gio/gdbusaddress.c:1108 msgid "Cannot spawn a message bus without a machine-id: " msgstr "Cannot spawn a message bus without a machine-id: " -#: gio/gdbusaddress.c:1108 +#: gio/gdbusaddress.c:1115 #, c-format msgid "Cannot autolaunch D-Bus without X11 $DISPLAY" msgstr "Cannot autolaunch D-Bus without X11 $DISPLAY" -#: gio/gdbusaddress.c:1150 +#: gio/gdbusaddress.c:1157 #, c-format msgid "Error spawning command line “%s”: " msgstr "Error spawning command line “%s”: " -#: gio/gdbusaddress.c:1219 +#: gio/gdbusaddress.c:1226 #, c-format msgid "Cannot determine session bus address (not implemented for this OS)" msgstr "Cannot determine session bus address (not implemented for this OS)" -#: gio/gdbusaddress.c:1357 gio/gdbusconnection.c:7192 +#: gio/gdbusaddress.c:1397 gio/gdbusconnection.c:7241 #, c-format msgid "" "Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment variable " @@ -518,7 +519,7 @@ msgstr "" "Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment variable " "— unknown value “%s”" -#: gio/gdbusaddress.c:1366 gio/gdbusconnection.c:7201 +#: gio/gdbusaddress.c:1406 gio/gdbusconnection.c:7250 msgid "" "Cannot determine bus address because the DBUS_STARTER_BUS_TYPE environment " "variable is not set" @@ -526,7 +527,7 @@ msgstr "" "Cannot determine bus address because the DBUS_STARTER_BUS_TYPE environment " "variable is not set" -#: gio/gdbusaddress.c:1376 +#: gio/gdbusaddress.c:1416 #, c-format msgid "Unknown bus type %d" msgstr "Unknown bus type %d" @@ -546,199 +547,213 @@ msgid "" msgstr "" "Exhausted all available authentication mechanisms (tried: %s) (available: %s)" -#: gio/gdbusauth.c:1167 +#: gio/gdbusauth.c:1170 +msgid "User IDs must be the same for peer and server" +msgstr "User IDs must be the same for peer and server" + +#: gio/gdbusauth.c:1182 msgid "Cancelled via GDBusAuthObserver::authorize-authenticated-peer" msgstr "Cancelled via GDBusAuthObserver::authorize-authenticated-peer" -#: gio/gdbusauthmechanismsha1.c:265 +#: gio/gdbusauthmechanismsha1.c:298 #, c-format msgid "Error when getting information for directory “%s”: %s" msgstr "Error when getting information for directory “%s”: %s" -#: gio/gdbusauthmechanismsha1.c:280 +#: gio/gdbusauthmechanismsha1.c:313 #, c-format msgid "" "Permissions on directory “%s” are malformed. Expected mode 0700, got 0%o" msgstr "" "Permissions on directory “%s” are malformed. Expected mode 0700, got 0%o" -#: gio/gdbusauthmechanismsha1.c:310 +#: gio/gdbusauthmechanismsha1.c:346 gio/gdbusauthmechanismsha1.c:357 #, c-format msgid "Error creating directory “%s”: %s" msgstr "Error creating directory “%s”: %s" -#: gio/gdbusauthmechanismsha1.c:355 +#: gio/gdbusauthmechanismsha1.c:359 gio/gfile.c:1062 gio/gfile.c:1300 +#: gio/gfile.c:1438 gio/gfile.c:1676 gio/gfile.c:1731 gio/gfile.c:1789 +#: gio/gfile.c:1873 gio/gfile.c:1930 gio/gfile.c:1994 gio/gfile.c:2049 +#: gio/gfile.c:3754 gio/gfile.c:3809 gio/gfile.c:4102 gio/gfile.c:4572 +#: gio/gfile.c:4983 gio/gfile.c:5068 gio/gfile.c:5158 gio/gfile.c:5255 +#: gio/gfile.c:5342 gio/gfile.c:5443 gio/gfile.c:8153 gio/gfile.c:8243 +#: gio/gfile.c:8327 gio/win32/gwinhttpfile.c:453 +msgid "Operation not supported" +msgstr "Operation not supported" + +#: gio/gdbusauthmechanismsha1.c:402 #, c-format msgid "Error opening keyring “%s” for reading: " msgstr "Error opening keyring “%s” for reading: " -#: gio/gdbusauthmechanismsha1.c:378 gio/gdbusauthmechanismsha1.c:700 +#: gio/gdbusauthmechanismsha1.c:425 gio/gdbusauthmechanismsha1.c:747 #, c-format msgid "Line %d of the keyring at “%s” with content “%s” is malformed" msgstr "Line %d of the keyring at “%s” with content “%s” is malformed" -#: gio/gdbusauthmechanismsha1.c:392 gio/gdbusauthmechanismsha1.c:714 +#: gio/gdbusauthmechanismsha1.c:439 gio/gdbusauthmechanismsha1.c:761 #, c-format msgid "" "First token of line %d of the keyring at “%s” with content “%s” is malformed" msgstr "" "First token of line %d of the keyring at “%s” with content “%s” is malformed" -#: gio/gdbusauthmechanismsha1.c:406 gio/gdbusauthmechanismsha1.c:728 +#: gio/gdbusauthmechanismsha1.c:453 gio/gdbusauthmechanismsha1.c:775 #, c-format msgid "" "Second token of line %d of the keyring at “%s” with content “%s” is malformed" msgstr "" "Second token of line %d of the keyring at “%s” with content “%s” is malformed" -#: gio/gdbusauthmechanismsha1.c:430 +#: gio/gdbusauthmechanismsha1.c:477 #, c-format msgid "Didn’t find cookie with id %d in the keyring at “%s”" msgstr "Didn’t find cookie with id %d in the keyring at “%s”" -#: gio/gdbusauthmechanismsha1.c:476 +#: gio/gdbusauthmechanismsha1.c:523 #, c-format msgid "Error creating lock file “%s”: %s" msgstr "Error creating lock file “%s”: %s" -#: gio/gdbusauthmechanismsha1.c:540 +#: gio/gdbusauthmechanismsha1.c:587 #, c-format msgid "Error deleting stale lock file “%s”: %s" msgstr "Error deleting stale lock file “%s”: %s" -#: gio/gdbusauthmechanismsha1.c:579 +#: gio/gdbusauthmechanismsha1.c:626 #, c-format msgid "Error closing (unlinked) lock file “%s”: %s" msgstr "Error closing (unlinked) lock file “%s”: %s" -#: gio/gdbusauthmechanismsha1.c:590 +#: gio/gdbusauthmechanismsha1.c:637 #, c-format msgid "Error unlinking lock file “%s”: %s" msgstr "Error unlinking lock file “%s”: %s" -#: gio/gdbusauthmechanismsha1.c:667 +#: gio/gdbusauthmechanismsha1.c:714 #, c-format msgid "Error opening keyring “%s” for writing: " msgstr "Error opening keyring “%s” for writing: " -#: gio/gdbusauthmechanismsha1.c:865 +#: gio/gdbusauthmechanismsha1.c:908 #, c-format msgid "(Additionally, releasing the lock for “%s” also failed: %s) " msgstr "(Additionally, releasing the lock for “%s” also failed: %s) " -#: gio/gdbusconnection.c:595 gio/gdbusconnection.c:2391 +#: gio/gdbusconnection.c:603 gio/gdbusconnection.c:2405 msgid "The connection is closed" msgstr "The connection is closed" -#: gio/gdbusconnection.c:1892 +#: gio/gdbusconnection.c:1902 msgid "Timeout was reached" msgstr "Timeout was reached" -#: gio/gdbusconnection.c:2513 +#: gio/gdbusconnection.c:2528 msgid "" "Unsupported flags encountered when constructing a client-side connection" msgstr "" "Unsupported flags encountered when constructing a client-side connection" -#: gio/gdbusconnection.c:4163 gio/gdbusconnection.c:4510 +#: gio/gdbusconnection.c:4186 gio/gdbusconnection.c:4533 #, c-format msgid "" "No such interface “org.freedesktop.DBus.Properties” on object at path %s" msgstr "" "No such interface “org.freedesktop.DBus.Properties” on object at path %s" -#: gio/gdbusconnection.c:4305 +#: gio/gdbusconnection.c:4328 #, c-format msgid "No such property “%s”" msgstr "No such property “%s”" -#: gio/gdbusconnection.c:4317 +#: gio/gdbusconnection.c:4340 #, c-format msgid "Property “%s” is not readable" msgstr "Property “%s” is not readable" -#: gio/gdbusconnection.c:4328 +#: gio/gdbusconnection.c:4351 #, c-format msgid "Property “%s” is not writable" msgstr "Property “%s” is not writable" -#: gio/gdbusconnection.c:4348 +#: gio/gdbusconnection.c:4371 #, c-format msgid "Error setting property “%s”: Expected type “%s” but got “%s”" msgstr "Error setting property “%s”: Expected type “%s” but got “%s”" -#: gio/gdbusconnection.c:4453 gio/gdbusconnection.c:4661 -#: gio/gdbusconnection.c:6632 +#: gio/gdbusconnection.c:4476 gio/gdbusconnection.c:4684 +#: gio/gdbusconnection.c:6681 #, c-format msgid "No such interface “%s”" msgstr "No such interface “%s”" -#: gio/gdbusconnection.c:4879 gio/gdbusconnection.c:7141 +#: gio/gdbusconnection.c:4902 gio/gdbusconnection.c:7190 #, c-format msgid "No such interface “%s” on object at path %s" msgstr "No such interface “%s” on object at path %s" -#: gio/gdbusconnection.c:4977 +#: gio/gdbusconnection.c:5000 #, c-format msgid "No such method “%s”" msgstr "No such method “%s”" -#: gio/gdbusconnection.c:5008 +#: gio/gdbusconnection.c:5031 #, c-format msgid "Type of message, “%s”, does not match expected type “%s”" msgstr "Type of message, “%s”, does not match expected type “%s”" -#: gio/gdbusconnection.c:5206 +#: gio/gdbusconnection.c:5229 #, c-format msgid "An object is already exported for the interface %s at %s" msgstr "An object is already exported for the interface %s at %s" -#: gio/gdbusconnection.c:5432 +#: gio/gdbusconnection.c:5455 #, c-format msgid "Unable to retrieve property %s.%s" msgstr "Unable to retrieve property %s.%s" -#: gio/gdbusconnection.c:5488 +#: gio/gdbusconnection.c:5511 #, c-format msgid "Unable to set property %s.%s" msgstr "Unable to set property %s.%s" -#: gio/gdbusconnection.c:5666 +#: gio/gdbusconnection.c:5690 #, c-format msgid "Method “%s” returned type “%s”, but expected “%s”" msgstr "Method “%s” returned type “%s”, but expected “%s”" -#: gio/gdbusconnection.c:6743 +#: gio/gdbusconnection.c:6792 #, c-format msgid "Method “%s” on interface “%s” with signature “%s” does not exist" msgstr "Method “%s” on interface “%s” with signature “%s” does not exist" -#: gio/gdbusconnection.c:6864 +#: gio/gdbusconnection.c:6913 #, c-format msgid "A subtree is already exported for %s" msgstr "A subtree is already exported for %s" -#: gio/gdbusmessage.c:1255 +#: gio/gdbusmessage.c:1266 msgid "type is INVALID" msgstr "type is INVALID" -#: gio/gdbusmessage.c:1266 +#: gio/gdbusmessage.c:1277 msgid "METHOD_CALL message: PATH or MEMBER header field is missing" msgstr "METHOD_CALL message: PATH or MEMBER header field is missing" -#: gio/gdbusmessage.c:1277 +#: gio/gdbusmessage.c:1288 msgid "METHOD_RETURN message: REPLY_SERIAL header field is missing" msgstr "METHOD_RETURN message: REPLY_SERIAL header field is missing" -#: gio/gdbusmessage.c:1289 +#: gio/gdbusmessage.c:1300 msgid "ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing" msgstr "ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing" -#: gio/gdbusmessage.c:1302 +#: gio/gdbusmessage.c:1313 msgid "SIGNAL message: PATH, INTERFACE or MEMBER header field is missing" msgstr "SIGNAL message: PATH, INTERFACE or MEMBER header field is missing" -#: gio/gdbusmessage.c:1310 +#: gio/gdbusmessage.c:1321 msgid "" "SIGNAL message: The PATH header field is using the reserved value /org/" "freedesktop/DBus/Local" @@ -746,7 +761,7 @@ msgstr "" "SIGNAL message: The PATH header field is using the reserved value /org/" "freedesktop/DBus/Local" -#: gio/gdbusmessage.c:1318 +#: gio/gdbusmessage.c:1329 msgid "" "SIGNAL message: The INTERFACE header field is using the reserved value org." "freedesktop.DBus.Local" @@ -754,19 +769,21 @@ msgstr "" "SIGNAL message: The INTERFACE header field is using the reserved value org." "freedesktop.DBus.Local" -#: gio/gdbusmessage.c:1366 gio/gdbusmessage.c:1426 +#: gio/gdbusmessage.c:1377 gio/gdbusmessage.c:1437 #, c-format msgid "Wanted to read %lu byte but only got %lu" msgid_plural "Wanted to read %lu bytes but only got %lu" -msgstr[0] "Wanted to read %lu byte but only got %lu" -msgstr[1] "Wanted to read %lu bytes but only got %lu" +msgstr[0] "Wanted to read %lu byte but only got %lu" +msgstr[1] "Wanted to read %lu bytes but only got %lu" +msgstr[2] "Wanted to read %lu bytes but only got %lu" +msgstr[3] "Wanted to read %lu bytes but only got %lu" -#: gio/gdbusmessage.c:1380 +#: gio/gdbusmessage.c:1391 #, c-format msgid "Expected NUL byte after the string “%s” but found byte %d" msgstr "Expected NUL byte after the string “%s” but found byte %d" -#: gio/gdbusmessage.c:1399 +#: gio/gdbusmessage.c:1410 #, c-format msgid "" "Expected valid UTF-8 string but found invalid bytes at byte offset %d " @@ -775,21 +792,21 @@ msgstr "" "Expected valid UTF-8 string but found invalid bytes at byte offset %d " "(length of string is %d). The valid UTF-8 string up until that point was “%s”" -#: gio/gdbusmessage.c:1463 gio/gdbusmessage.c:1711 gio/gdbusmessage.c:1900 +#: gio/gdbusmessage.c:1474 gio/gdbusmessage.c:1722 gio/gdbusmessage.c:1911 msgid "Value nested too deeply" msgstr "Value nested too deeply" -#: gio/gdbusmessage.c:1609 +#: gio/gdbusmessage.c:1620 #, c-format msgid "Parsed value “%s” is not a valid D-Bus object path" msgstr "Parsed value “%s” is not a valid D-Bus object path" -#: gio/gdbusmessage.c:1631 +#: gio/gdbusmessage.c:1642 #, c-format msgid "Parsed value “%s” is not a valid D-Bus signature" msgstr "Parsed value “%s” is not a valid D-Bus signature" -#: gio/gdbusmessage.c:1678 +#: gio/gdbusmessage.c:1689 #, c-format msgid "" "Encountered array of length %u byte. Maximum length is 2<<26 bytes (64 MiB)." @@ -799,8 +816,12 @@ msgstr[0] "" "Encountered array of length %u byte. Maximum length is 2<<26 bytes (64 MiB)." msgstr[1] "" "Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB)." +msgstr[2] "" +"Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB)." +msgstr[3] "" +"Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB)." -#: gio/gdbusmessage.c:1698 +#: gio/gdbusmessage.c:1709 #, c-format msgid "" "Encountered array of type “a%c”, expected to have a length a multiple of %u " @@ -809,19 +830,19 @@ msgstr "" "Encountered array of type “a%c”, expected to have a length a multiple of %u " "bytes, but found to be %u bytes in length" -#: gio/gdbusmessage.c:1884 +#: gio/gdbusmessage.c:1895 #, c-format msgid "Parsed value “%s” for variant is not a valid D-Bus signature" msgstr "Parsed value “%s” for variant is not a valid D-Bus signature" -#: gio/gdbusmessage.c:1925 +#: gio/gdbusmessage.c:1936 #, c-format msgid "" "Error deserializing GVariant with type string “%s” from the D-Bus wire format" msgstr "" "Error deserializing GVariant with type string “%s” from the D-Bus wire format" -#: gio/gdbusmessage.c:2110 +#: gio/gdbusmessage.c:2121 #, c-format msgid "" "Invalid endianness value. Expected 0x6c (“l”) or 0x42 (“B”) but found value " @@ -830,60 +851,62 @@ msgstr "" "Invalid endianness value. Expected 0x6c (“l”) or 0x42 (“B”) but found value " "0x%02x" -#: gio/gdbusmessage.c:2123 +#: gio/gdbusmessage.c:2134 #, c-format msgid "Invalid major protocol version. Expected 1 but found %d" msgstr "Invalid major protocol version. Expected 1 but found %d" -#: gio/gdbusmessage.c:2177 gio/gdbusmessage.c:2773 +#: gio/gdbusmessage.c:2188 gio/gdbusmessage.c:2784 msgid "Signature header found but is not of type signature" msgstr "Signature header found but is not of type signature" -#: gio/gdbusmessage.c:2189 +#: gio/gdbusmessage.c:2200 #, c-format msgid "Signature header with signature “%s” found but message body is empty" msgstr "Signature header with signature “%s” found but message body is empty" -#: gio/gdbusmessage.c:2204 +#: gio/gdbusmessage.c:2215 #, c-format msgid "Parsed value “%s” is not a valid D-Bus signature (for body)" msgstr "Parsed value “%s” is not a valid D-Bus signature (for body)" -#: gio/gdbusmessage.c:2236 +#: gio/gdbusmessage.c:2247 #, c-format msgid "No signature header in message but the message body is %u byte" msgid_plural "No signature header in message but the message body is %u bytes" -msgstr[0] "No signature header in message but the message body is %u byte" -msgstr[1] "No signature header in message but the message body is %u bytes" +msgstr[0] "No signature header in message but the message body is %u byte" +msgstr[1] "No signature header in message but the message body is %u bytes" +msgstr[2] "No signature header in message but the message body is %u byte" +msgstr[3] "No signature header in message but the message body is %u byte" -#: gio/gdbusmessage.c:2246 +#: gio/gdbusmessage.c:2257 msgid "Cannot deserialize message: " msgstr "Cannot deserialize message: " -#: gio/gdbusmessage.c:2590 +#: gio/gdbusmessage.c:2601 #, c-format msgid "" "Error serializing GVariant with type string “%s” to the D-Bus wire format" msgstr "" "Error serializing GVariant with type string “%s” to the D-Bus wire format" -#: gio/gdbusmessage.c:2727 +#: gio/gdbusmessage.c:2738 #, c-format msgid "" "Number of file descriptors in message (%d) differs from header field (%d)" msgstr "" "Number of file descriptors in message (%d) differs from header field (%d)" -#: gio/gdbusmessage.c:2735 +#: gio/gdbusmessage.c:2746 msgid "Cannot serialize message: " msgstr "Cannot serialize message: " -#: gio/gdbusmessage.c:2788 +#: gio/gdbusmessage.c:2799 #, c-format msgid "Message body has signature “%s” but there is no signature header" msgstr "Message body has signature “%s” but there is no signature header" -#: gio/gdbusmessage.c:2798 +#: gio/gdbusmessage.c:2809 #, c-format msgid "" "Message body has type signature “%s” but signature in the header field is " @@ -892,38 +915,41 @@ msgstr "" "Message body has type signature “%s” but signature in the header field is " "“%s”" -#: gio/gdbusmessage.c:2814 +#: gio/gdbusmessage.c:2825 #, c-format msgid "Message body is empty but signature in the header field is “(%s)”" msgstr "Message body is empty but signature in the header field is “(%s)”" -#: gio/gdbusmessage.c:3367 +#: gio/gdbusmessage.c:3378 #, c-format msgid "Error return with body of type “%s”" msgstr "Error return with body of type “%s”" -#: gio/gdbusmessage.c:3375 +#: gio/gdbusmessage.c:3386 msgid "Error return with empty body" msgstr "Error return with empty body" -#: gio/gdbusprivate.c:2244 +#: gio/gdbusprivate.c:2246 #, c-format msgid "(Type any character to close this window)\n" msgstr "(Type any character to close this window)\n" -#: gio/gdbusprivate.c:2418 +#: gio/gdbusprivate.c:2420 #, c-format msgid "Session dbus not running, and autolaunch failed" msgstr "Session dbus not running, and autolaunch failed" -#: gio/gdbusprivate.c:2441 +#: gio/gdbusprivate.c:2443 #, c-format msgid "Unable to get Hardware profile: %s" msgstr "Unable to get Hardware profile: %s" -#: gio/gdbusprivate.c:2486 -msgid "Unable to load /var/lib/dbus/machine-id or /etc/machine-id: " -msgstr "Unable to load /var/lib/dbus/machine-id or /etc/machine-id: " +#. Translators: Both placeholders are file paths +#: gio/gdbusprivate.c:2494 +#, c-format +#| msgid "Unable to trash file %s: %s" +msgid "Unable to load %s or %s: " +msgstr "Unable to load %s or %s: " #: gio/gdbusproxy.c:1562 #, c-format @@ -944,30 +970,30 @@ msgstr "" "Cannot invoke method; proxy is for the well-known name %s without an owner, " "and proxy was constructed with the G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START flag" -#: gio/gdbusserver.c:755 +#: gio/gdbusserver.c:763 msgid "Abstract namespace not supported" msgstr "Abstract namespace not supported" -#: gio/gdbusserver.c:848 +#: gio/gdbusserver.c:856 msgid "Cannot specify nonce file when creating a server" msgstr "Cannot specify nonce file when creating a server" -#: gio/gdbusserver.c:930 +#: gio/gdbusserver.c:938 #, c-format msgid "Error writing nonce file at “%s”: %s" msgstr "Error writing nonce file at “%s”: %s" -#: gio/gdbusserver.c:1103 +#: gio/gdbusserver.c:1113 #, c-format msgid "The string “%s” is not a valid D-Bus GUID" msgstr "The string “%s” is not a valid D-Bus GUID" -#: gio/gdbusserver.c:1143 +#: gio/gdbusserver.c:1153 #, c-format msgid "Cannot listen on unsupported transport “%s”" msgstr "Cannot listen on unsupported transport “%s”" -#: gio/gdbus-tool.c:107 +#: gio/gdbus-tool.c:111 #, c-format msgid "" "Commands:\n" @@ -990,61 +1016,67 @@ msgstr "" "\n" "Use “%s COMMAND --help” to get help on each command.\n" -#: gio/gdbus-tool.c:197 gio/gdbus-tool.c:264 gio/gdbus-tool.c:336 -#: gio/gdbus-tool.c:360 gio/gdbus-tool.c:850 gio/gdbus-tool.c:1187 -#: gio/gdbus-tool.c:1672 +#: gio/gdbus-tool.c:201 gio/gdbus-tool.c:273 gio/gdbus-tool.c:345 +#: gio/gdbus-tool.c:369 gio/gdbus-tool.c:859 gio/gdbus-tool.c:1236 +#: gio/gdbus-tool.c:1724 #, c-format msgid "Error: %s\n" msgstr "Error: %s\n" -#: gio/gdbus-tool.c:208 gio/gdbus-tool.c:277 gio/gdbus-tool.c:1688 +#: gio/gdbus-tool.c:212 gio/gdbus-tool.c:286 gio/gdbus-tool.c:1740 #, c-format msgid "Error parsing introspection XML: %s\n" msgstr "Error parsing introspection XML: %s\n" -#: gio/gdbus-tool.c:246 +#: gio/gdbus-tool.c:250 #, c-format msgid "Error: %s is not a valid name\n" msgstr "Error: %s is not a valid name\n" -#: gio/gdbus-tool.c:394 +#: gio/gdbus-tool.c:255 gio/gdbus-tool.c:745 gio/gdbus-tool.c:1060 +#: gio/gdbus-tool.c:1890 gio/gdbus-tool.c:2130 +#, c-format +msgid "Error: %s is not a valid object path\n" +msgstr "Error: %s is not a valid object path\n" + +#: gio/gdbus-tool.c:403 msgid "Connect to the system bus" msgstr "Connect to the system bus" -#: gio/gdbus-tool.c:395 +#: gio/gdbus-tool.c:404 msgid "Connect to the session bus" msgstr "Connect to the session bus" -#: gio/gdbus-tool.c:396 +#: gio/gdbus-tool.c:405 msgid "Connect to given D-Bus address" msgstr "Connect to given D-Bus address" -#: gio/gdbus-tool.c:406 +#: gio/gdbus-tool.c:415 msgid "Connection Endpoint Options:" msgstr "Connection Endpoint Options:" -#: gio/gdbus-tool.c:407 +#: gio/gdbus-tool.c:416 msgid "Options specifying the connection endpoint" msgstr "Options specifying the connection endpoint" -#: gio/gdbus-tool.c:430 +#: gio/gdbus-tool.c:439 #, c-format msgid "No connection endpoint specified" msgstr "No connection endpoint specified" -#: gio/gdbus-tool.c:440 +#: gio/gdbus-tool.c:449 #, c-format msgid "Multiple connection endpoints specified" msgstr "Multiple connection endpoints specified" -#: gio/gdbus-tool.c:513 +#: gio/gdbus-tool.c:522 #, c-format msgid "" "Warning: According to introspection data, interface “%s” does not exist\n" msgstr "" "Warning: According to introspection data, interface “%s” does not exist\n" -#: gio/gdbus-tool.c:522 +#: gio/gdbus-tool.c:531 #, c-format msgid "" "Warning: According to introspection data, method “%s” does not exist on " @@ -1053,161 +1085,161 @@ msgstr "" "Warning: According to introspection data, method “%s” does not exist on " "interface “%s”\n" -#: gio/gdbus-tool.c:584 +#: gio/gdbus-tool.c:593 msgid "Optional destination for signal (unique name)" msgstr "Optional destination for signal (unique name)" -#: gio/gdbus-tool.c:585 +#: gio/gdbus-tool.c:594 msgid "Object path to emit signal on" msgstr "Object path to emit signal on" -#: gio/gdbus-tool.c:586 +#: gio/gdbus-tool.c:595 msgid "Signal and interface name" msgstr "Signal and interface name" -#: gio/gdbus-tool.c:619 +#: gio/gdbus-tool.c:628 msgid "Emit a signal." msgstr "Emit a signal." -#: gio/gdbus-tool.c:674 gio/gdbus-tool.c:981 gio/gdbus-tool.c:1775 -#: gio/gdbus-tool.c:2007 gio/gdbus-tool.c:2227 +#: gio/gdbus-tool.c:683 gio/gdbus-tool.c:997 gio/gdbus-tool.c:1827 +#: gio/gdbus-tool.c:2059 gio/gdbus-tool.c:2279 #, c-format msgid "Error connecting: %s\n" msgstr "Error connecting: %s\n" -#: gio/gdbus-tool.c:694 +#: gio/gdbus-tool.c:703 #, c-format msgid "Error: %s is not a valid unique bus name.\n" msgstr "Error: %s is not a valid unique bus name.\n" -#: gio/gdbus-tool.c:713 gio/gdbus-tool.c:1024 gio/gdbus-tool.c:1818 +#: gio/gdbus-tool.c:722 gio/gdbus-tool.c:1040 gio/gdbus-tool.c:1870 msgid "Error: Object path is not specified\n" msgstr "Error: Object path is not specified\n" -#: gio/gdbus-tool.c:736 gio/gdbus-tool.c:1044 gio/gdbus-tool.c:1838 -#: gio/gdbus-tool.c:2078 -#, c-format -msgid "Error: %s is not a valid object path\n" -msgstr "Error: %s is not a valid object path\n" - -#: gio/gdbus-tool.c:756 +#: gio/gdbus-tool.c:765 msgid "Error: Signal name is not specified\n" msgstr "Error: Signal name is not specified\n" -#: gio/gdbus-tool.c:770 +#: gio/gdbus-tool.c:779 #, c-format msgid "Error: Signal name “%s” is invalid\n" msgstr "Error: Signal name “%s” is invalid\n" -#: gio/gdbus-tool.c:782 +#: gio/gdbus-tool.c:791 #, c-format msgid "Error: %s is not a valid interface name\n" msgstr "Error: %s is not a valid interface name\n" -#: gio/gdbus-tool.c:788 +#: gio/gdbus-tool.c:797 #, c-format msgid "Error: %s is not a valid member name\n" msgstr "Error: %s is not a valid member name\n" #. Use the original non-"parse-me-harder" error -#: gio/gdbus-tool.c:825 gio/gdbus-tool.c:1156 +#: gio/gdbus-tool.c:834 gio/gdbus-tool.c:1172 #, c-format msgid "Error parsing parameter %d: %s\n" msgstr "Error parsing parameter %d: %s\n" -#: gio/gdbus-tool.c:857 +#: gio/gdbus-tool.c:866 #, c-format msgid "Error flushing connection: %s\n" msgstr "Error flushing connection: %s\n" -#: gio/gdbus-tool.c:884 +#: gio/gdbus-tool.c:893 msgid "Destination name to invoke method on" msgstr "Destination name to invoke method on" -#: gio/gdbus-tool.c:885 +#: gio/gdbus-tool.c:894 msgid "Object path to invoke method on" msgstr "Object path to invoke method on" -#: gio/gdbus-tool.c:886 +#: gio/gdbus-tool.c:895 msgid "Method and interface name" msgstr "Method and interface name" -#: gio/gdbus-tool.c:887 +#: gio/gdbus-tool.c:896 msgid "Timeout in seconds" msgstr "Timeout in seconds" -#: gio/gdbus-tool.c:926 +#: gio/gdbus-tool.c:942 msgid "Invoke a method on a remote object." msgstr "Invoke a method on a remote object." -#: gio/gdbus-tool.c:998 gio/gdbus-tool.c:1792 gio/gdbus-tool.c:2032 +#: gio/gdbus-tool.c:1014 gio/gdbus-tool.c:1844 gio/gdbus-tool.c:2084 msgid "Error: Destination is not specified\n" msgstr "Error: Destination is not specified\n" -#: gio/gdbus-tool.c:1009 gio/gdbus-tool.c:1809 gio/gdbus-tool.c:2043 +#: gio/gdbus-tool.c:1025 gio/gdbus-tool.c:1861 gio/gdbus-tool.c:2095 #, c-format msgid "Error: %s is not a valid bus name\n" msgstr "Error: %s is not a valid bus name\n" -#: gio/gdbus-tool.c:1059 +#: gio/gdbus-tool.c:1075 msgid "Error: Method name is not specified\n" msgstr "Error: Method name is not specified\n" -#: gio/gdbus-tool.c:1070 +#: gio/gdbus-tool.c:1086 #, c-format msgid "Error: Method name “%s” is invalid\n" msgstr "Error: Method name “%s” is invalid\n" -#: gio/gdbus-tool.c:1148 +#: gio/gdbus-tool.c:1164 #, c-format msgid "Error parsing parameter %d of type “%s”: %s\n" msgstr "Error parsing parameter %d of type “%s”: %s\n" -#: gio/gdbus-tool.c:1634 +#: gio/gdbus-tool.c:1190 +#, c-format +#| msgid "Error reading from handle: %s" +msgid "Error adding handle %d: %s\n" +msgstr "Error adding handle %d: %s\n" + +#: gio/gdbus-tool.c:1686 msgid "Destination name to introspect" msgstr "Destination name to introspect" -#: gio/gdbus-tool.c:1635 +#: gio/gdbus-tool.c:1687 msgid "Object path to introspect" msgstr "Object path to introspect" -#: gio/gdbus-tool.c:1636 +#: gio/gdbus-tool.c:1688 msgid "Print XML" msgstr "Print XML" -#: gio/gdbus-tool.c:1637 +#: gio/gdbus-tool.c:1689 msgid "Introspect children" msgstr "Introspect children" -#: gio/gdbus-tool.c:1638 +#: gio/gdbus-tool.c:1690 msgid "Only print properties" msgstr "Only print properties" -#: gio/gdbus-tool.c:1727 +#: gio/gdbus-tool.c:1779 msgid "Introspect a remote object." msgstr "Introspect a remote object." -#: gio/gdbus-tool.c:1933 +#: gio/gdbus-tool.c:1985 msgid "Destination name to monitor" msgstr "Destination name to monitor" -#: gio/gdbus-tool.c:1934 +#: gio/gdbus-tool.c:1986 msgid "Object path to monitor" msgstr "Object path to monitor" -#: gio/gdbus-tool.c:1959 +#: gio/gdbus-tool.c:2011 msgid "Monitor a remote object." -msgstr "corrupted object" +msgstr "Monitor a remote object." -#: gio/gdbus-tool.c:2017 +#: gio/gdbus-tool.c:2069 msgid "Error: can’t monitor a non-message-bus connection\n" msgstr "Error: can’t monitor a non-message-bus connection\n" -#: gio/gdbus-tool.c:2141 +#: gio/gdbus-tool.c:2193 msgid "Service to activate before waiting for the other one (well-known name)" msgstr "Service to activate before waiting for the other one (well-known name)" -#: gio/gdbus-tool.c:2144 +#: gio/gdbus-tool.c:2196 msgid "" "Timeout to wait for before exiting with an error (seconds); 0 for no timeout " "(default)" @@ -1215,63 +1247,63 @@ msgstr "" "Timeout to wait for before exiting with an error (seconds); 0 for no timeout " "(default)" -#: gio/gdbus-tool.c:2192 +#: gio/gdbus-tool.c:2244 msgid "[OPTION…] BUS-NAME" msgstr "[OPTION…] BUS-NAME" -#: gio/gdbus-tool.c:2193 +#: gio/gdbus-tool.c:2245 msgid "Wait for a bus name to appear." msgstr "Wait for a bus name to appear." -#: gio/gdbus-tool.c:2269 +#: gio/gdbus-tool.c:2321 msgid "Error: A service to activate for must be specified.\n" msgstr "Error: A service to activate for must be specified.\n" -#: gio/gdbus-tool.c:2274 +#: gio/gdbus-tool.c:2326 msgid "Error: A service to wait for must be specified.\n" msgstr "Error: A service to wait for must be specified.\n" -#: gio/gdbus-tool.c:2279 +#: gio/gdbus-tool.c:2331 msgid "Error: Too many arguments.\n" msgstr "Error: Too many arguments.\n" -#: gio/gdbus-tool.c:2287 gio/gdbus-tool.c:2294 +#: gio/gdbus-tool.c:2339 gio/gdbus-tool.c:2346 #, c-format msgid "Error: %s is not a valid well-known bus name.\n" msgstr "Error: %s is not a valid well-known bus name.\n" -#: gio/gdesktopappinfo.c:2073 gio/gdesktopappinfo.c:4893 +#: gio/gdesktopappinfo.c:2106 gio/gdesktopappinfo.c:4932 msgid "Unnamed" msgstr "Unnamed" -#: gio/gdesktopappinfo.c:2483 +#: gio/gdesktopappinfo.c:2516 msgid "Desktop file didn’t specify Exec field" msgstr "Desktop file didn’t specify Exec field" -#: gio/gdesktopappinfo.c:2763 +#: gio/gdesktopappinfo.c:2801 msgid "Unable to find terminal required for application" msgstr "Unable to find terminal required for application" -#: gio/gdesktopappinfo.c:3414 +#: gio/gdesktopappinfo.c:3452 #, c-format msgid "Can’t create user application configuration folder %s: %s" msgstr "Can’t create user application configuration folder %s: %s" -#: gio/gdesktopappinfo.c:3418 +#: gio/gdesktopappinfo.c:3456 #, c-format msgid "Can’t create user MIME configuration folder %s: %s" msgstr "Can’t create user MIME configuration folder %s: %s" -#: gio/gdesktopappinfo.c:3660 gio/gdesktopappinfo.c:3684 +#: gio/gdesktopappinfo.c:3698 gio/gdesktopappinfo.c:3722 msgid "Application information lacks an identifier" msgstr "Application information lacks an identifier" -#: gio/gdesktopappinfo.c:3920 +#: gio/gdesktopappinfo.c:3958 #, c-format msgid "Can’t create user desktop file %s" msgstr "Can’t create user desktop file %s" -#: gio/gdesktopappinfo.c:4056 +#: gio/gdesktopappinfo.c:4094 #, c-format msgid "Custom definition for %s" msgstr "Custom definition for %s" @@ -1336,87 +1368,77 @@ msgstr "Malformed number of tokens (%d) in GEmblemedIcon encoding" msgid "Expected a GEmblem for GEmblemedIcon" msgstr "Expected a GEmblem for GEmblemedIcon" -#: gio/gfile.c:1044 gio/gfile.c:1282 gio/gfile.c:1420 gio/gfile.c:1658 -#: gio/gfile.c:1713 gio/gfile.c:1771 gio/gfile.c:1855 gio/gfile.c:1912 -#: gio/gfile.c:1976 gio/gfile.c:2031 gio/gfile.c:3722 gio/gfile.c:3777 -#: gio/gfile.c:4070 gio/gfile.c:4540 gio/gfile.c:4951 gio/gfile.c:5036 -#: gio/gfile.c:5126 gio/gfile.c:5223 gio/gfile.c:5310 gio/gfile.c:5411 -#: gio/gfile.c:8121 gio/gfile.c:8211 gio/gfile.c:8295 -#: gio/win32/gwinhttpfile.c:437 -msgid "Operation not supported" -msgstr "Operation not supported" - #. Translators: This is an error message when #. * trying to find the enclosing (user visible) #. * mount of a file, but none exists. #. -#: gio/gfile.c:1543 +#: gio/gfile.c:1561 msgid "Containing mount does not exist" msgstr "Containing mount does not exist" -#: gio/gfile.c:2590 gio/glocalfile.c:2430 +#: gio/gfile.c:2608 gio/glocalfile.c:2472 msgid "Can’t copy over directory" msgstr "Can’t copy over directory" -#: gio/gfile.c:2650 +#: gio/gfile.c:2668 msgid "Can’t copy directory over directory" msgstr "Can’t copy directory over directory" -#: gio/gfile.c:2658 +#: gio/gfile.c:2676 msgid "Target file exists" msgstr "Target file exists" -#: gio/gfile.c:2677 +#: gio/gfile.c:2695 msgid "Can’t recursively copy directory" msgstr "Can’t recursively copy directory" -#: gio/gfile.c:2952 +#: gio/gfile.c:2996 msgid "Splice not supported" msgstr "Symbolic links not supported" -#: gio/gfile.c:2956 gio/gfile.c:3001 +#: gio/gfile.c:3000 #, c-format msgid "Error splicing file: %s" msgstr "Error opening file: %s" -#: gio/gfile.c:3117 +#: gio/gfile.c:3152 msgid "Copy (reflink/clone) between mounts is not supported" msgstr "Copy (reflink/clone) between mounts is not supported" -#: gio/gfile.c:3121 +#: gio/gfile.c:3156 msgid "Copy (reflink/clone) is not supported or invalid" msgstr "Copy (reflink/clone) is not supported or invalid" -#: gio/gfile.c:3126 +#: gio/gfile.c:3161 msgid "Copy (reflink/clone) is not supported or didn’t work" msgstr "Copy (reflink/clone) is not supported or didn’t work" -#: gio/gfile.c:3190 +#: gio/gfile.c:3226 msgid "Can’t copy special file" msgstr "Can’t copy special file" -#: gio/gfile.c:4003 +#: gio/gfile.c:4035 msgid "Invalid symlink value given" msgstr "Invalid symlink value given" -#: gio/gfile.c:4013 glib/gfileutils.c:2349 +#: gio/gfile.c:4045 glib/gfileutils.c:2354 msgid "Symbolic links not supported" msgstr "Symbolic links not supported" -#: gio/gfile.c:4181 +#: gio/gfile.c:4213 msgid "Trash not supported" msgstr "Trash not supported" -#: gio/gfile.c:4293 +#: gio/gfile.c:4325 #, c-format msgid "File names cannot contain “%c”" msgstr "File names cannot contain “%c”" -#: gio/gfile.c:6774 gio/gvolume.c:364 +#: gio/gfile.c:6806 gio/gvolume.c:364 msgid "volume doesn’t implement mount" msgstr "volume doesn’t implement mount" -#: gio/gfile.c:6888 gio/gfile.c:6936 +#: gio/gfile.c:6920 gio/gfile.c:6968 msgid "No application is registered as handling this file" msgstr "No application is registered as handling this file" @@ -1433,12 +1455,12 @@ msgstr "File enumerator has outstanding operation" msgid "File enumerator is already closed" msgstr "File enumerator is already closed" -#: gio/gfileicon.c:236 +#: gio/gfileicon.c:250 #, c-format msgid "Can’t handle version %d of GFileIcon encoding" msgstr "Can’t handle version %d of GFileIcon encoding" -#: gio/gfileicon.c:246 +#: gio/gfileicon.c:260 msgid "Malformed input data for GFileIcon" msgstr "Malformed input data for GFileIcon" @@ -1487,7 +1509,12 @@ msgstr "HTTP proxy authentication required" msgid "HTTP proxy connection failed: %i" msgstr "HTTP proxy connection failed: %i" -#: gio/ghttpproxy.c:269 +#: gio/ghttpproxy.c:266 +#| msgid "HTTP proxy connection failed: %i" +msgid "HTTP proxy response too big" +msgstr "HTTP proxy response too big" + +#: gio/ghttpproxy.c:283 msgid "HTTP proxy server closed connection unexpectedly." msgstr "HTTP proxy server closed connection unexpectedly." @@ -1562,7 +1589,7 @@ msgstr "Input stream doesn’t implement read" #. Translators: This is an error you get if there is #. * already an operation running against this stream when #. * you try to start one -#: gio/ginputstream.c:1218 gio/giostream.c:310 gio/goutputstream.c:2208 +#: gio/ginputstream.c:1247 gio/giostream.c:310 gio/goutputstream.c:2208 msgid "Stream has outstanding operation" msgstr "Stream has outstanding operation" @@ -1603,58 +1630,63 @@ msgid "Show information about locations" msgstr "Show information about locations" #: gio/gio-tool.c:232 +#| msgid "List static actions for an application (from .desktop file)" +msgid "Launch an application from a desktop file" +msgstr "Launch an application from a desktop file" + +#: gio/gio-tool.c:233 msgid "List the contents of locations" msgstr "List the contents of locations" -#: gio/gio-tool.c:233 +#: gio/gio-tool.c:234 msgid "Get or set the handler for a mimetype" msgstr "Get or set the handler for a mimetype" -#: gio/gio-tool.c:234 +#: gio/gio-tool.c:235 msgid "Create directories" msgstr "Create directories" -#: gio/gio-tool.c:235 +#: gio/gio-tool.c:236 msgid "Monitor files and directories for changes" msgstr "Monitor files and directories for changes" -#: gio/gio-tool.c:236 +#: gio/gio-tool.c:237 msgid "Mount or unmount the locations" msgstr "Mount or unmount the locations" -#: gio/gio-tool.c:237 +#: gio/gio-tool.c:238 msgid "Move one or more files" msgstr "Move one or more files" -#: gio/gio-tool.c:238 +#: gio/gio-tool.c:239 msgid "Open files with the default application" msgstr "Open files with the default application" -#: gio/gio-tool.c:239 +#: gio/gio-tool.c:240 msgid "Rename a file" msgstr "Rename a file" -#: gio/gio-tool.c:240 +#: gio/gio-tool.c:241 msgid "Delete one or more files" msgstr "Delete one or more files" -#: gio/gio-tool.c:241 +#: gio/gio-tool.c:242 msgid "Read from standard input and save" msgstr "Read from standard input and save" -#: gio/gio-tool.c:242 +#: gio/gio-tool.c:243 msgid "Set a file attribute" msgstr "Set a file attribute" -#: gio/gio-tool.c:243 +#: gio/gio-tool.c:244 msgid "Move files or directories to the trash" msgstr "Move files or directories to the trash" -#: gio/gio-tool.c:244 +#: gio/gio-tool.c:245 msgid "Lists the contents of locations in a tree" msgstr "Lists the contents of locations in a tree" -#: gio/gio-tool.c:246 +#: gio/gio-tool.c:247 #, c-format msgid "Use %s to get detailed help.\n" msgstr "Use %s to get detailed help.\n" @@ -1664,12 +1696,12 @@ msgid "Error writing to stdout" msgstr "Error writing to stdout" #. Translators: commandline placeholder -#: gio/gio-tool-cat.c:133 gio/gio-tool-info.c:333 gio/gio-tool-list.c:172 +#: gio/gio-tool-cat.c:133 gio/gio-tool-info.c:340 gio/gio-tool-list.c:172 #: gio/gio-tool-mkdir.c:48 gio/gio-tool-monitor.c:37 gio/gio-tool-monitor.c:39 #: gio/gio-tool-monitor.c:41 gio/gio-tool-monitor.c:43 -#: gio/gio-tool-monitor.c:203 gio/gio-tool-mount.c:1199 gio/gio-tool-open.c:70 +#: gio/gio-tool-monitor.c:204 gio/gio-tool-mount.c:1199 gio/gio-tool-open.c:70 #: gio/gio-tool-remove.c:48 gio/gio-tool-rename.c:45 gio/gio-tool-set.c:89 -#: gio/gio-tool-trash.c:81 gio/gio-tool-tree.c:239 +#: gio/gio-tool-trash.c:220 gio/gio-tool-tree.c:239 msgid "LOCATION" msgstr "LOCATION" @@ -1687,9 +1719,9 @@ msgstr "" "locations instead of local files: for example, you can use something\n" "like smb://server/resource/file.txt as location." -#: gio/gio-tool-cat.c:162 gio/gio-tool-info.c:364 gio/gio-tool-mkdir.c:76 -#: gio/gio-tool-monitor.c:228 gio/gio-tool-mount.c:1250 gio/gio-tool-open.c:96 -#: gio/gio-tool-remove.c:72 gio/gio-tool-trash.c:136 +#: gio/gio-tool-cat.c:162 gio/gio-tool-info.c:371 gio/gio-tool-mkdir.c:76 +#: gio/gio-tool-monitor.c:229 gio/gio-tool-mount.c:1250 gio/gio-tool-open.c:96 +#: gio/gio-tool-remove.c:72 gio/gio-tool-trash.c:303 msgid "No locations given" msgstr "No locations given" @@ -1824,24 +1856,24 @@ msgstr "uri: %s\n" msgid "local path: %s\n" msgstr "local path: %s\n" -#: gio/gio-tool-info.c:199 +#: gio/gio-tool-info.c:205 #, c-format msgid "unix mount: %s%s %s %s %s\n" msgstr "unix mount: %s%s %s %s %s\n" -#: gio/gio-tool-info.c:279 +#: gio/gio-tool-info.c:286 msgid "Settable attributes:\n" msgstr "Settable attributes:\n" -#: gio/gio-tool-info.c:303 +#: gio/gio-tool-info.c:310 msgid "Writable attribute namespaces:\n" msgstr "Writable attribute namespaces:\n" -#: gio/gio-tool-info.c:338 +#: gio/gio-tool-info.c:345 msgid "Show information about locations." msgstr "Show information about locations." -#: gio/gio-tool-info.c:340 +#: gio/gio-tool-info.c:347 msgid "" "gio info is similar to the traditional ls utility, but using GIO\n" "locations instead of local files: for example, you can use something\n" @@ -1855,6 +1887,47 @@ msgstr "" "be specified with their GIO name, e.g. standard::icon, or just by\n" "namespace, e.g. unix, or by “*”, which matches all attributes" +#. Translators: commandline placeholder +#: gio/gio-tool-launch.c:54 +msgid "DESKTOP-FILE [FILE-ARG …]" +msgstr "DESKTOP-FILE [FILE-ARG …]" + +#: gio/gio-tool-launch.c:57 +msgid "" +"Launch an application from a desktop file, passing optional filename " +"arguments to it." +msgstr "" +"Launch an application from a desktop file, passing optional filename " +"arguments to it." + +#: gio/gio-tool-launch.c:77 +#| msgid "No files given" +msgid "No desktop file given" +msgstr "No desktop file given" + +#: gio/gio-tool-launch.c:85 +#| msgid "There is no GCredentials support for your platform" +msgid "The launch command is not currently supported on this platform" +msgstr "The launch command is not currently supported on this platform" + +#: gio/gio-tool-launch.c:98 +#, c-format +#| msgid "Unable to trash file %s: %s" +msgid "Unable to load ‘%s‘: %s" +msgstr "Unable to load ‘%s‘: %s" + +#: gio/gio-tool-launch.c:107 +#, c-format +#| msgid "Failed to load info for handler “%s”" +msgid "Unable to load application information for ‘%s‘" +msgstr "Unable to load application information for ‘%s‘" + +#: gio/gio-tool-launch.c:119 +#, c-format +#| msgid "Default application for “%s”: %s\n" +msgid "Unable to launch application ‘%s’: %s" +msgstr "Unable to launch application ‘%s’: %s" + #: gio/gio-tool-list.c:37 gio/gio-tool-tree.c:32 msgid "Show hidden files" msgstr "Show hidden files" @@ -1992,7 +2065,7 @@ msgstr "Report moves and renames as simple deleted/created events" msgid "Watch for mount events" msgstr "Watch for mount events" -#: gio/gio-tool-monitor.c:208 +#: gio/gio-tool-monitor.c:209 msgid "Monitor files or directories for changes." msgstr "Monitor files or directories for changes." @@ -2116,7 +2189,7 @@ msgstr "" "Open files with the default application that\n" "is registered to handle files of this type." -#: gio/gio-tool-remove.c:31 gio/gio-tool-trash.c:31 +#: gio/gio-tool-remove.c:31 gio/gio-tool-trash.c:33 msgid "Ignore nonexistent files, never prompt" msgstr "Ignore nonexistent files, never prompt" @@ -2229,13 +2302,54 @@ msgstr "Value not specified" msgid "Invalid attribute type “%s”" msgstr "Invalid attribute type “%s”" -#: gio/gio-tool-trash.c:32 +#: gio/gio-tool-trash.c:34 msgid "Empty the trash" msgstr "Empty the trash" -#: gio/gio-tool-trash.c:86 -msgid "Move files or directories to the trash." -msgstr "Move files or directories to the trash." +#: gio/gio-tool-trash.c:35 +#| msgid "List the contents of the locations." +msgid "List files in the trash with their original locations" +msgstr "List files in the trash with their original locations" + +#: gio/gio-tool-trash.c:36 +msgid "" +"Restore a file from trash to its original location (possibly recreating the " +"directory)" +msgstr "" +"Restore a file from trash to its original location (possibly recreating the " +"directory)" + +#: gio/gio-tool-trash.c:106 +#| msgid "Unable to find terminal required for application" +msgid "Unable to find original path" +msgstr "Unable to find original path" + +#: gio/gio-tool-trash.c:123 +#| msgid "Unable to create socket: %s" +msgid "Unable to recreate original location: " +msgstr "Unable to recreate original location: " + +#: gio/gio-tool-trash.c:136 +#| msgid "unable to find desktop file for application %s\n" +msgid "Unable to move file to its original location: " +msgstr "Unable to move file to its original location: " + +#: gio/gio-tool-trash.c:225 +#| msgid "Move files or directories to the trash." +msgid "Move/Restore files or directories to the trash." +msgstr "Move/Restore files or directories to the trash." + +#: gio/gio-tool-trash.c:227 +msgid "" +"Note: for --restore switch, if the original location of the trashed file \n" +"already exists, it will not be overwritten unless --force is set." +msgstr "" +"Note: for --restore switch, if the original location of the trashed file \n" +"already exists, it will not be overwritten unless --force is set." + +#: gio/gio-tool-trash.c:258 +msgid "Location given doesn't start with trash:///" +msgstr "Location given doesn't start with trash:///" #: gio/gio-tool-tree.c:33 msgid "Follow symbolic links, mounts and shortcuts" @@ -2853,7 +2967,7 @@ msgstr "No schema files found: doing nothing." msgid "No schema files found: removed existing output file." msgstr "No schema files found: removed existing output file." -#: gio/glocalfile.c:549 gio/win32/gwinhttpfile.c:420 +#: gio/glocalfile.c:549 gio/win32/gwinhttpfile.c:436 #, c-format msgid "Invalid filename %s" msgstr "Invalid filename %s" @@ -2885,8 +2999,8 @@ msgstr "Error renaming file %s: %s" msgid "Can’t rename file, filename already exists" msgstr "Can’t rename file, filename already exists" -#: gio/glocalfile.c:1182 gio/glocalfile.c:2324 gio/glocalfile.c:2352 -#: gio/glocalfile.c:2491 gio/glocalfileoutputstream.c:650 +#: gio/glocalfile.c:1182 gio/glocalfile.c:2366 gio/glocalfile.c:2394 +#: gio/glocalfile.c:2533 gio/glocalfileoutputstream.c:656 msgid "Invalid filename" msgstr "Invalid filename" @@ -2900,91 +3014,93 @@ msgstr "Error opening file %s: %s" msgid "Error removing file %s: %s" msgstr "Error removing file %s: %s" -#: gio/glocalfile.c:1969 +#: gio/glocalfile.c:1980 gio/glocalfile.c:1991 #, c-format msgid "Error trashing file %s: %s" msgstr "Error trashing file %s: %s" -#: gio/glocalfile.c:2010 +#: gio/glocalfile.c:2029 #, c-format -msgid "Unable to create trash dir %s: %s" -msgstr "Unable to create trash dir %s: %s" +#| msgid "Unable to create trash dir %s: %s" +msgid "Unable to create trash directory %s: %s" +msgstr "Unable to create trash directory %s: %s" -#: gio/glocalfile.c:2030 +#: gio/glocalfile.c:2050 #, c-format msgid "Unable to find toplevel directory to trash %s" msgstr "Unable to find toplevel directory to trash %s" -#: gio/glocalfile.c:2038 +#: gio/glocalfile.c:2058 #, c-format msgid "Trashing on system internal mounts is not supported" msgstr "Trashing on system internal mounts is not supported" -#: gio/glocalfile.c:2118 gio/glocalfile.c:2138 +#: gio/glocalfile.c:2141 gio/glocalfile.c:2169 #, c-format -msgid "Unable to find or create trash directory for %s" -msgstr "Unable to find or create trash directory for %s" +#| msgid "Unable to find or create trash directory for %s" +msgid "Unable to find or create trash directory %s to trash %s" +msgstr "Unable to find or create trash directory %s to trash %s" -#: gio/glocalfile.c:2173 +#: gio/glocalfile.c:2215 #, c-format msgid "Unable to create trashing info file for %s: %s" msgstr "Unable to create trashing info file for %s: %s" -#: gio/glocalfile.c:2235 +#: gio/glocalfile.c:2277 #, c-format msgid "Unable to trash file %s across filesystem boundaries" msgstr "Unable to trash file %s across filesystem boundaries" -#: gio/glocalfile.c:2239 gio/glocalfile.c:2295 +#: gio/glocalfile.c:2281 gio/glocalfile.c:2337 #, c-format msgid "Unable to trash file %s: %s" msgstr "Unable to trash file %s: %s" -#: gio/glocalfile.c:2301 +#: gio/glocalfile.c:2343 #, c-format msgid "Unable to trash file %s" msgstr "Unable to trash file %s" -#: gio/glocalfile.c:2327 +#: gio/glocalfile.c:2369 #, c-format msgid "Error creating directory %s: %s" msgstr "Error creating directory %s: %s" -#: gio/glocalfile.c:2356 +#: gio/glocalfile.c:2398 #, c-format msgid "Filesystem does not support symbolic links" msgstr "Filesystem does not support symbolic links" -#: gio/glocalfile.c:2359 +#: gio/glocalfile.c:2401 #, c-format msgid "Error making symbolic link %s: %s" msgstr "Error making symbolic link %s: %s" -#: gio/glocalfile.c:2402 gio/glocalfile.c:2437 gio/glocalfile.c:2494 +#: gio/glocalfile.c:2444 gio/glocalfile.c:2479 gio/glocalfile.c:2536 #, c-format msgid "Error moving file %s: %s" msgstr "Error moving file %s: %s" -#: gio/glocalfile.c:2425 +#: gio/glocalfile.c:2467 msgid "Can’t move directory over directory" msgstr "Can’t move directory over directory" -#: gio/glocalfile.c:2451 gio/glocalfileoutputstream.c:1039 -#: gio/glocalfileoutputstream.c:1053 gio/glocalfileoutputstream.c:1068 -#: gio/glocalfileoutputstream.c:1085 gio/glocalfileoutputstream.c:1099 +#: gio/glocalfile.c:2493 gio/glocalfileoutputstream.c:1079 +#: gio/glocalfileoutputstream.c:1093 gio/glocalfileoutputstream.c:1108 +#: gio/glocalfileoutputstream.c:1125 gio/glocalfileoutputstream.c:1139 msgid "Backup file creation failed" msgstr "Backup file creation failed" -#: gio/glocalfile.c:2470 +#: gio/glocalfile.c:2512 #, c-format msgid "Error removing target file: %s" msgstr "Error removing target file: %s" -#: gio/glocalfile.c:2484 +#: gio/glocalfile.c:2526 msgid "Move between mounts not supported" msgstr "Move between mounts not supported" -#: gio/glocalfile.c:2658 +#: gio/glocalfile.c:2700 #, c-format msgid "Could not determine the disk usage of %s: %s" msgstr "Could not determine the disk usage of %s: %s" @@ -3006,189 +3122,185 @@ msgstr "Invalid extended attribute name" msgid "Error setting extended attribute “%s”: %s" msgstr "Error setting extended attribute “%s”: %s" -#: gio/glocalfileinfo.c:1663 +#: gio/glocalfileinfo.c:1709 gio/win32/gwinhttpfile.c:191 msgid " (invalid encoding)" msgstr " (invalid encoding)" -#: gio/glocalfileinfo.c:1822 gio/glocalfileoutputstream.c:915 +#: gio/glocalfileinfo.c:1868 gio/glocalfileoutputstream.c:943 #, c-format msgid "Error when getting information for file “%s”: %s" msgstr "Error when getting information for file “%s”: %s" -#: gio/glocalfileinfo.c:2088 +#: gio/glocalfileinfo.c:2134 #, c-format msgid "Error when getting information for file descriptor: %s" msgstr "Error when getting information for file descriptor: %s" -#: gio/glocalfileinfo.c:2133 +#: gio/glocalfileinfo.c:2179 msgid "Invalid attribute type (uint32 expected)" msgstr "Invalid attribute type (uint32 expected)" -#: gio/glocalfileinfo.c:2151 +#: gio/glocalfileinfo.c:2197 msgid "Invalid attribute type (uint64 expected)" msgstr "Invalid attribute type (uint64 expected)" -#: gio/glocalfileinfo.c:2170 gio/glocalfileinfo.c:2189 +#: gio/glocalfileinfo.c:2216 gio/glocalfileinfo.c:2235 msgid "Invalid attribute type (byte string expected)" msgstr "Invalid attribute type (byte string expected)" -#: gio/glocalfileinfo.c:2236 +#: gio/glocalfileinfo.c:2282 msgid "Cannot set permissions on symlinks" msgstr "Cannot set permissions on symlinks" -#: gio/glocalfileinfo.c:2252 +#: gio/glocalfileinfo.c:2298 #, c-format msgid "Error setting permissions: %s" msgstr "Error setting permissions: %s" -#: gio/glocalfileinfo.c:2303 +#: gio/glocalfileinfo.c:2349 #, c-format msgid "Error setting owner: %s" msgstr "Error setting owner: %s" -#: gio/glocalfileinfo.c:2326 +#: gio/glocalfileinfo.c:2372 msgid "symlink must be non-NULL" msgstr "symlink must be non-NULL" -#: gio/glocalfileinfo.c:2336 gio/glocalfileinfo.c:2355 -#: gio/glocalfileinfo.c:2366 +#: gio/glocalfileinfo.c:2382 gio/glocalfileinfo.c:2401 +#: gio/glocalfileinfo.c:2412 #, c-format msgid "Error setting symlink: %s" msgstr "Error setting symlink: %s" -#: gio/glocalfileinfo.c:2345 +#: gio/glocalfileinfo.c:2391 msgid "Error setting symlink: file is not a symlink" msgstr "Error setting symlink: file is not a symlink" -#: gio/glocalfileinfo.c:2417 +#: gio/glocalfileinfo.c:2463 #, c-format msgid "Extra nanoseconds %d for UNIX timestamp %lld are negative" msgstr "Extra nanoseconds %d for UNIX timestamp %lld are negative" -#: gio/glocalfileinfo.c:2426 +#: gio/glocalfileinfo.c:2472 #, c-format msgid "Extra nanoseconds %d for UNIX timestamp %lld reach 1 second" msgstr "Extra nanoseconds %d for UNIX timestamp %lld reach 1 second" -#: gio/glocalfileinfo.c:2436 +#: gio/glocalfileinfo.c:2482 #, c-format msgid "UNIX timestamp %lld does not fit into 64 bits" msgstr "UNIX timestamp %lld does not fit into 64 bits" -#: gio/glocalfileinfo.c:2447 +#: gio/glocalfileinfo.c:2493 #, c-format msgid "UNIX timestamp %lld is outside of the range supported by Windows" msgstr "UNIX timestamp %lld is outside of the range supported by Windows" -#: gio/glocalfileinfo.c:2511 +#: gio/glocalfileinfo.c:2557 #, c-format -#| msgid "Value “%s” cannot be interpreted as a number." msgid "File name “%s” cannot be converted to UTF-16" msgstr "File name “%s” cannot be converted to UTF-16" -#: gio/glocalfileinfo.c:2530 +#: gio/glocalfileinfo.c:2576 #, c-format -#| msgid "Value “%s” cannot be interpreted as a number." msgid "File “%s” cannot be opened: Windows Error %lu" msgstr "File “%s” cannot be opened: Windows Error %lu" -#: gio/glocalfileinfo.c:2543 +#: gio/glocalfileinfo.c:2589 #, c-format -#| msgid "Error setting modification or access time: %s" msgid "Error setting modification or access time for file “%s”: %lu" msgstr "Error setting modification or access time for file “%s”: %lu" -#: gio/glocalfileinfo.c:2644 +#: gio/glocalfileinfo.c:2690 #, c-format msgid "Error setting modification or access time: %s" msgstr "Error setting modification or access time: %s" # c-format -#: gio/glocalfileinfo.c:2667 +#: gio/glocalfileinfo.c:2713 msgid "SELinux context must be non-NULL" msgstr "SELinux context must be non-NULL" -#: gio/glocalfileinfo.c:2682 +#: gio/glocalfileinfo.c:2720 +msgid "SELinux is not enabled on this system" +msgstr "SELinux is not enabled on this system" + +#: gio/glocalfileinfo.c:2730 #, c-format msgid "Error setting SELinux context: %s" msgstr "Error setting SELinux context: %s" -#: gio/glocalfileinfo.c:2689 -msgid "SELinux is not enabled on this system" -msgstr "SELinux is not enabled on this system" - -#: gio/glocalfileinfo.c:2781 +#: gio/glocalfileinfo.c:2823 #, c-format msgid "Setting attribute %s not supported" msgstr "Setting attribute %s not supported" -#: gio/glocalfileinputstream.c:168 gio/glocalfileoutputstream.c:795 +#: gio/glocalfileinputstream.c:163 gio/glocalfileoutputstream.c:801 #, c-format msgid "Error reading from file: %s" msgstr "Error reading from file: %s" -#: gio/glocalfileinputstream.c:199 gio/glocalfileinputstream.c:211 -#: gio/glocalfileinputstream.c:225 gio/glocalfileinputstream.c:333 -#: gio/glocalfileoutputstream.c:557 gio/glocalfileoutputstream.c:1117 -#, c-format -msgid "Error seeking in file: %s" -msgstr "Error seeking in file: %s" - -#: gio/glocalfileinputstream.c:255 gio/glocalfileoutputstream.c:347 -#: gio/glocalfileoutputstream.c:441 +#: gio/glocalfileinputstream.c:194 gio/glocalfileoutputstream.c:353 +#: gio/glocalfileoutputstream.c:447 #, c-format msgid "Error closing file: %s" msgstr "Error closing file: %s" -#: gio/glocalfilemonitor.c:865 +#: gio/glocalfileinputstream.c:272 gio/glocalfileoutputstream.c:563 +#: gio/glocalfileoutputstream.c:1157 +#, c-format +msgid "Error seeking in file: %s" +msgstr "Error seeking in file: %s" + +#: gio/glocalfilemonitor.c:866 msgid "Unable to find default local file monitor type" msgstr "Unable to find default local file monitor type" -#: gio/glocalfileoutputstream.c:214 gio/glocalfileoutputstream.c:292 -#: gio/glocalfileoutputstream.c:328 gio/glocalfileoutputstream.c:816 +#: gio/glocalfileoutputstream.c:220 gio/glocalfileoutputstream.c:298 +#: gio/glocalfileoutputstream.c:334 gio/glocalfileoutputstream.c:822 #, c-format msgid "Error writing to file: %s" msgstr "Error writing to file: %s" -#: gio/glocalfileoutputstream.c:374 +#: gio/glocalfileoutputstream.c:380 #, c-format msgid "Error removing old backup link: %s" msgstr "Error removing old backup link: %s" -#: gio/glocalfileoutputstream.c:388 gio/glocalfileoutputstream.c:401 +#: gio/glocalfileoutputstream.c:394 gio/glocalfileoutputstream.c:407 #, c-format msgid "Error creating backup copy: %s" msgstr "Error creating backup copy: %s" -#: gio/glocalfileoutputstream.c:419 +#: gio/glocalfileoutputstream.c:425 #, c-format msgid "Error renaming temporary file: %s" msgstr "Error renaming temporary file: %s" -#: gio/glocalfileoutputstream.c:603 gio/glocalfileoutputstream.c:1168 +#: gio/glocalfileoutputstream.c:609 gio/glocalfileoutputstream.c:1208 #, c-format msgid "Error truncating file: %s" msgstr "Error truncating file: %s" -#: gio/glocalfileoutputstream.c:656 gio/glocalfileoutputstream.c:894 -#: gio/glocalfileoutputstream.c:1149 gio/gsubprocess.c:380 +#: gio/glocalfileoutputstream.c:662 gio/glocalfileoutputstream.c:907 +#: gio/glocalfileoutputstream.c:1189 gio/gsubprocess.c:226 #, c-format msgid "Error opening file “%s”: %s" msgstr "Error opening file “%s”: %s" -#: gio/glocalfileoutputstream.c:928 +#: gio/glocalfileoutputstream.c:957 msgid "Target file is a directory" msgstr "Target file is a directory" -#: gio/glocalfileoutputstream.c:933 +#: gio/glocalfileoutputstream.c:971 msgid "Target file is not a regular file" msgstr "Target file is not a regular file" -#: gio/glocalfileoutputstream.c:945 +#: gio/glocalfileoutputstream.c:984 msgid "The file was externally modified" msgstr "The file was externally modified" -#: gio/glocalfileoutputstream.c:1133 +#: gio/glocalfileoutputstream.c:1173 #, c-format msgid "Error removing old file: %s" msgstr "Error removing old file: %s" @@ -3343,15 +3455,15 @@ msgstr "%s not implemented" msgid "Invalid domain" msgstr "Invalid domain" -#: gio/gresource.c:672 gio/gresource.c:931 gio/gresource.c:970 -#: gio/gresource.c:1094 gio/gresource.c:1166 gio/gresource.c:1239 -#: gio/gresource.c:1320 gio/gresourcefile.c:476 gio/gresourcefile.c:599 +#: gio/gresource.c:681 gio/gresource.c:943 gio/gresource.c:983 +#: gio/gresource.c:1107 gio/gresource.c:1179 gio/gresource.c:1253 +#: gio/gresource.c:1334 gio/gresourcefile.c:476 gio/gresourcefile.c:599 #: gio/gresourcefile.c:736 #, c-format msgid "The resource at “%s” does not exist" msgstr "The resource at “%s” does not exist" -#: gio/gresource.c:837 +#: gio/gresource.c:848 #, c-format msgid "The resource at “%s” failed to decompress" msgstr "The resource at “%s” failed to decompress" @@ -3726,7 +3838,7 @@ msgstr "Invalid socket, initialization failed due to: %s" msgid "Socket is already closed" msgstr "Socket is already closed" -#: gio/gsocket.c:443 gio/gsocket.c:3180 gio/gsocket.c:4403 gio/gsocket.c:4461 +#: gio/gsocket.c:443 gio/gsocket.c:3190 gio/gsocket.c:4420 gio/gsocket.c:4478 msgid "Socket I/O timed out" msgstr "Socket I/O timed out" @@ -3735,176 +3847,182 @@ msgstr "Socket I/O timed out" msgid "creating GSocket from fd: %s" msgstr "creating GSocket from fd: %s" -#: gio/gsocket.c:607 gio/gsocket.c:661 gio/gsocket.c:668 +#: gio/gsocket.c:607 gio/gsocket.c:671 gio/gsocket.c:678 #, c-format msgid "Unable to create socket: %s" msgstr "Unable to create socket: %s" -#: gio/gsocket.c:661 +#: gio/gsocket.c:671 msgid "Unknown family was specified" msgstr "Unknown family was specified" -#: gio/gsocket.c:668 +#: gio/gsocket.c:678 msgid "Unknown protocol was specified" msgstr "Unknown protocol was specified" -#: gio/gsocket.c:1159 +#: gio/gsocket.c:1169 #, c-format msgid "Cannot use datagram operations on a non-datagram socket." msgstr "Cannot use datagram operations on a non-datagram socket." -#: gio/gsocket.c:1176 +#: gio/gsocket.c:1186 #, c-format msgid "Cannot use datagram operations on a socket with a timeout set." msgstr "Cannot use datagram operations on a socket with a timeout set." -#: gio/gsocket.c:1983 +#: gio/gsocket.c:1993 #, c-format msgid "could not get local address: %s" msgstr "could not get local address: %s" -#: gio/gsocket.c:2029 +#: gio/gsocket.c:2039 #, c-format msgid "could not get remote address: %s" msgstr "could not get remote address: %s" -#: gio/gsocket.c:2095 +#: gio/gsocket.c:2105 #, c-format msgid "could not listen: %s" msgstr "could not listen: %s" -#: gio/gsocket.c:2199 +#: gio/gsocket.c:2209 #, c-format msgid "Error binding to address %s: %s" msgstr "Error binding to address %s: %s" -#: gio/gsocket.c:2375 gio/gsocket.c:2412 gio/gsocket.c:2522 gio/gsocket.c:2547 -#: gio/gsocket.c:2610 gio/gsocket.c:2668 gio/gsocket.c:2686 +#: gio/gsocket.c:2385 gio/gsocket.c:2422 gio/gsocket.c:2532 gio/gsocket.c:2557 +#: gio/gsocket.c:2620 gio/gsocket.c:2678 gio/gsocket.c:2696 #, c-format msgid "Error joining multicast group: %s" msgstr "Error joining multicast group: %s" -#: gio/gsocket.c:2376 gio/gsocket.c:2413 gio/gsocket.c:2523 gio/gsocket.c:2548 -#: gio/gsocket.c:2611 gio/gsocket.c:2669 gio/gsocket.c:2687 +#: gio/gsocket.c:2386 gio/gsocket.c:2423 gio/gsocket.c:2533 gio/gsocket.c:2558 +#: gio/gsocket.c:2621 gio/gsocket.c:2679 gio/gsocket.c:2697 #, c-format msgid "Error leaving multicast group: %s" msgstr "Error leaving multicast group: %s" -#: gio/gsocket.c:2377 +#: gio/gsocket.c:2387 msgid "No support for source-specific multicast" msgstr "No support for source-specific multicast" -#: gio/gsocket.c:2524 +#: gio/gsocket.c:2534 msgid "Unsupported socket family" msgstr "Unsupported socket family" -#: gio/gsocket.c:2549 +#: gio/gsocket.c:2559 msgid "source-specific not an IPv4 address" msgstr "source-specific not an IPv4 address" -#: gio/gsocket.c:2573 +#: gio/gsocket.c:2583 #, c-format msgid "Interface name too long" msgstr "Interface name too long" -#: gio/gsocket.c:2586 gio/gsocket.c:2636 +#: gio/gsocket.c:2596 gio/gsocket.c:2646 #, c-format msgid "Interface not found: %s" msgstr "Interface not found: %s" -#: gio/gsocket.c:2612 +#: gio/gsocket.c:2622 msgid "No support for IPv4 source-specific multicast" msgstr "No support for IPv4 source-specific multicast" -#: gio/gsocket.c:2670 +#: gio/gsocket.c:2680 msgid "No support for IPv6 source-specific multicast" msgstr "No support for IPv6 source-specific multicast" -#: gio/gsocket.c:2879 +#: gio/gsocket.c:2889 #, c-format msgid "Error accepting connection: %s" msgstr "Error accepting connection: %s" -#: gio/gsocket.c:3005 +#: gio/gsocket.c:3015 msgid "Connection in progress" msgstr "Connection in progress" -#: gio/gsocket.c:3056 +#: gio/gsocket.c:3066 msgid "Unable to get pending error: " msgstr "Unable to get pending error: " -#: gio/gsocket.c:3245 +#: gio/gsocket.c:3255 #, c-format msgid "Error receiving data: %s" msgstr "Error receiving data: %s" -#: gio/gsocket.c:3442 +#: gio/gsocket.c:3452 #, c-format msgid "Error sending data: %s" msgstr "Error sending data: %s" -#: gio/gsocket.c:3629 +#: gio/gsocket.c:3639 #, c-format msgid "Unable to shutdown socket: %s" msgstr "Unable to shutdown socket: %s" -#: gio/gsocket.c:3710 +#: gio/gsocket.c:3720 #, c-format msgid "Error closing socket: %s" msgstr "Error closing socket: %s" -#: gio/gsocket.c:4396 +#: gio/gsocket.c:4413 #, c-format msgid "Waiting for socket condition: %s" msgstr "Waiting for socket condition: %s" -#: gio/gsocket.c:4774 gio/gsocket.c:4776 gio/gsocket.c:4923 gio/gsocket.c:5008 -#: gio/gsocket.c:5186 gio/gsocket.c:5226 gio/gsocket.c:5228 +#: gio/gsocket.c:4804 gio/gsocket.c:4820 gio/gsocket.c:4833 +#, c-format +#| msgid "Error sending message: %s" +msgid "Unable to send message: %s" +msgstr "Unable to send message: %s" + +#: gio/gsocket.c:4805 gio/gsocket.c:4821 gio/gsocket.c:4834 +msgid "Message vectors too large" +msgstr "Message vectors too large" + +#: gio/gsocket.c:4850 gio/gsocket.c:4852 gio/gsocket.c:4999 gio/gsocket.c:5084 +#: gio/gsocket.c:5262 gio/gsocket.c:5302 gio/gsocket.c:5304 #, c-format msgid "Error sending message: %s" msgstr "Error sending message: %s" -#: gio/gsocket.c:4950 +#: gio/gsocket.c:5026 msgid "GSocketControlMessage not supported on Windows" msgstr "GSocketControlMessage not supported on Windows" -#: gio/gsocket.c:5419 gio/gsocket.c:5492 gio/gsocket.c:5718 +#: gio/gsocket.c:5495 gio/gsocket.c:5571 gio/gsocket.c:5797 #, c-format msgid "Error receiving message: %s" msgstr "Error receiving message: %s" -#: gio/gsocket.c:5990 gio/gsocket.c:6038 +#: gio/gsocket.c:6070 gio/gsocket.c:6081 gio/gsocket.c:6127 #, c-format msgid "Unable to read socket credentials: %s" msgstr "Unable to read socket credentials: %s" -#: gio/gsocket.c:6047 +#: gio/gsocket.c:6136 msgid "g_socket_get_credentials not implemented for this OS" msgstr "g_socket_get_credentials not implemented for this OS" -#: gio/gsocketclient.c:182 +#: gio/gsocketclient.c:191 #, c-format msgid "Could not connect to proxy server %s: " msgstr "Could not connect to proxy server %s: " -#: gio/gsocketclient.c:196 +#: gio/gsocketclient.c:205 #, c-format msgid "Could not connect to %s: " msgstr "Could not connect to %s: " -#: gio/gsocketclient.c:198 +#: gio/gsocketclient.c:207 msgid "Could not connect: " msgstr "Could not connect: " -#: gio/gsocketclient.c:1037 gio/gsocketclient.c:1866 -msgid "Unknown error on connect" -msgstr "Unknown error on connect" - -#: gio/gsocketclient.c:1091 gio/gsocketclient.c:1668 +#: gio/gsocketclient.c:1162 gio/gsocketclient.c:1749 msgid "Proxying over a non-TCP connection is not supported." msgstr "Proxying over a non-TCP connection is not supported." -#: gio/gsocketclient.c:1120 gio/gsocketclient.c:1698 +#: gio/gsocketclient.c:1194 gio/gsocketclient.c:1778 #, c-format msgid "Proxy protocol “%s” is not supported." msgstr "Proxy protocol “%s” is not supported." @@ -4035,26 +4153,30 @@ msgstr "Temporarily unable to resolve “%s”" msgid "Error resolving “%s”" msgstr "Error resolving “%s”" -#: gio/gtlscertificate.c:243 +#: gio/gtlscertificate.c:298 msgid "No PEM-encoded private key found" msgstr "No PEM-encoded private key found" -#: gio/gtlscertificate.c:253 +#: gio/gtlscertificate.c:308 msgid "Cannot decrypt PEM-encoded private key" msgstr "Cannot decrypt PEM-encoded private key" -#: gio/gtlscertificate.c:264 +#: gio/gtlscertificate.c:319 msgid "Could not parse PEM-encoded private key" msgstr "Could not parse PEM-encoded private key" -#: gio/gtlscertificate.c:291 +#: gio/gtlscertificate.c:346 msgid "No PEM-encoded certificate found" msgstr "No PEM-encoded certificate found" -#: gio/gtlscertificate.c:300 +#: gio/gtlscertificate.c:355 msgid "Could not parse PEM-encoded certificate" msgstr "Could not parse PEM-encoded certificate" +#: gio/gtlscertificate.c:710 +msgid "This GTlsBackend does not support creating PKCS #11 certificates" +msgstr "This GTlsBackend does not support creating PKCS #11 certificates" + #: gio/gtlspassword.c:111 msgid "" "This is the last chance to enter the password correctly before your access " @@ -4081,8 +4203,10 @@ msgstr "The password entered is incorrect." #, c-format msgid "Expecting 1 control message, got %d" msgid_plural "Expecting 1 control message, got %d" -msgstr[0] "Expecting 1 control message, got %d" -msgstr[1] "Expecting 1 control message, got %d" +msgstr[0] "Expecting 1 control message, got %d" +msgstr[1] "Expecting 1 control message, got %d" +msgstr[2] "Expecting 1 control message, got %d" +msgstr[3] "Expecting 1 control message, got %d" #: gio/gunixconnection.c:182 gio/gunixconnection.c:591 msgid "Unexpected type of ancillary data" @@ -4092,8 +4216,18 @@ msgstr "Unexpected type of ancillary data" #, c-format msgid "Expecting one fd, but got %d\n" msgid_plural "Expecting one fd, but got %d\n" -msgstr[0] "Expecting one fd, but got %d\n" -msgstr[1] "Expecting one fd, but got %d\n" +msgstr[0] "" +"Expecting one fd, but got %d\n" +"\n" +msgstr[1] "" +"Expecting one fd, but got %d\n" +"\n" +msgstr[2] "" +"Expecting one fd, but got %d\n" +"\n" +msgstr[3] "" +"Expecting one fd, but got %d\n" +"\n" #: gio/gunixconnection.c:219 msgid "Received invalid fd" @@ -4101,7 +4235,7 @@ msgstr "Received invalid fd" #: gio/gunixconnection.c:363 msgid "Error sending credentials: " -msgstr "Error sending data: %s" +msgstr "Error sending credentials: " #: gio/gunixconnection.c:520 #, c-format @@ -4129,24 +4263,24 @@ msgstr "Not expecting control message, but got %d" msgid "Error while disabling SO_PASSCRED: %s" msgstr "Error while disabling SO_PASSCRED: %s" -#: gio/gunixinputstream.c:362 gio/gunixinputstream.c:383 +#: gio/gunixinputstream.c:357 gio/gunixinputstream.c:378 #, c-format msgid "Error reading from file descriptor: %s" msgstr "Error reading from file descriptor: %s" -#: gio/gunixinputstream.c:416 gio/gunixoutputstream.c:525 +#: gio/gunixinputstream.c:411 gio/gunixoutputstream.c:520 #: gio/gwin32inputstream.c:217 gio/gwin32outputstream.c:204 #, c-format msgid "Error closing file descriptor: %s" msgstr "Error closing file descriptor: %s" -#: gio/gunixmounts.c:2755 gio/gunixmounts.c:2808 +#: gio/gunixmounts.c:2780 gio/gunixmounts.c:2833 msgid "Filesystem root" msgstr "Filesystem root" -#: gio/gunixoutputstream.c:362 gio/gunixoutputstream.c:382 -#: gio/gunixoutputstream.c:469 gio/gunixoutputstream.c:489 -#: gio/gunixoutputstream.c:635 +#: gio/gunixoutputstream.c:357 gio/gunixoutputstream.c:377 +#: gio/gunixoutputstream.c:464 gio/gunixoutputstream.c:484 +#: gio/gunixoutputstream.c:630 #, c-format msgid "Error writing to file descriptor: %s" msgstr "Error writing to file descriptor: %s" @@ -4183,7 +4317,7 @@ msgstr "Error writing to file: %s" #: gio/gzlibcompressor.c:394 gio/gzlibdecompressor.c:347 msgid "Not enough memory" -msgstr "out of memory" +msgstr "Not enough memory" #: gio/gzlibcompressor.c:401 gio/gzlibdecompressor.c:354 #, c-format @@ -4350,25 +4484,25 @@ msgid "The pathname “%s” is not an absolute path" msgstr "The pathname “%s” is not an absolute path" #. Translators: this is the preferred format for expressing the date and the time -#: glib/gdatetime.c:220 +#: glib/gdatetime.c:226 msgctxt "GDateTime" msgid "%a %b %e %H:%M:%S %Y" msgstr "%Z %H:%M:%S %Y %b %d %a" #. Translators: this is the preferred format for expressing the date -#: glib/gdatetime.c:223 +#: glib/gdatetime.c:229 msgctxt "GDateTime" msgid "%m/%d/%y" msgstr "%d/%m/%y" #. Translators: this is the preferred format for expressing the time -#: glib/gdatetime.c:226 +#: glib/gdatetime.c:232 msgctxt "GDateTime" msgid "%H:%M:%S" msgstr "%H:%M:%S" #. Translators: this is the preferred format for expressing 12 hour time -#: glib/gdatetime.c:229 +#: glib/gdatetime.c:235 msgctxt "GDateTime" msgid "%I:%M:%S %p" msgstr "%I:%M:%S %P" @@ -4389,62 +4523,62 @@ msgstr "%I:%M:%S %P" #. * non-European) there is no difference between the standalone and #. * complete date form. #. -#: glib/gdatetime.c:268 +#: glib/gdatetime.c:274 msgctxt "full month name" msgid "January" msgstr "ינואר" -#: glib/gdatetime.c:270 +#: glib/gdatetime.c:276 msgctxt "full month name" msgid "February" msgstr "פברואר" -#: glib/gdatetime.c:272 +#: glib/gdatetime.c:278 msgctxt "full month name" msgid "March" msgstr "מרץ" -#: glib/gdatetime.c:274 +#: glib/gdatetime.c:280 msgctxt "full month name" msgid "April" msgstr "אפריל" -#: glib/gdatetime.c:276 +#: glib/gdatetime.c:282 msgctxt "full month name" msgid "May" msgstr "מאי" -#: glib/gdatetime.c:278 +#: glib/gdatetime.c:284 msgctxt "full month name" msgid "June" msgstr "יוני" -#: glib/gdatetime.c:280 +#: glib/gdatetime.c:286 msgctxt "full month name" msgid "July" msgstr "יולי" -#: glib/gdatetime.c:282 +#: glib/gdatetime.c:288 msgctxt "full month name" msgid "August" msgstr "אוגוסט" -#: glib/gdatetime.c:284 +#: glib/gdatetime.c:290 msgctxt "full month name" msgid "September" msgstr "ספטמבר" -#: glib/gdatetime.c:286 +#: glib/gdatetime.c:292 msgctxt "full month name" msgid "October" msgstr "אוקטובר" -#: glib/gdatetime.c:288 +#: glib/gdatetime.c:294 msgctxt "full month name" msgid "November" msgstr "נובמבר" -#: glib/gdatetime.c:290 +#: glib/gdatetime.c:296 msgctxt "full month name" msgid "December" msgstr "דצמבר" @@ -4466,132 +4600,132 @@ msgstr "דצמבר" #. * other platform. Here are abbreviated month names in a form #. * appropriate when they are used standalone. #. -#: glib/gdatetime.c:322 +#: glib/gdatetime.c:328 msgctxt "abbreviated month name" msgid "Jan" msgstr "ינו" -#: glib/gdatetime.c:324 +#: glib/gdatetime.c:330 msgctxt "abbreviated month name" msgid "Feb" msgstr "פבר" -#: glib/gdatetime.c:326 +#: glib/gdatetime.c:332 msgctxt "abbreviated month name" msgid "Mar" msgstr "מרץ" -#: glib/gdatetime.c:328 +#: glib/gdatetime.c:334 msgctxt "abbreviated month name" msgid "Apr" msgstr "אפר" -#: glib/gdatetime.c:330 +#: glib/gdatetime.c:336 msgctxt "abbreviated month name" msgid "May" msgstr "מאי" -#: glib/gdatetime.c:332 +#: glib/gdatetime.c:338 msgctxt "abbreviated month name" msgid "Jun" msgstr "יונ" -#: glib/gdatetime.c:334 +#: glib/gdatetime.c:340 msgctxt "abbreviated month name" msgid "Jul" msgstr "יול" -#: glib/gdatetime.c:336 +#: glib/gdatetime.c:342 msgctxt "abbreviated month name" msgid "Aug" msgstr "אוג" -#: glib/gdatetime.c:338 +#: glib/gdatetime.c:344 msgctxt "abbreviated month name" msgid "Sep" msgstr "ספט" -#: glib/gdatetime.c:340 +#: glib/gdatetime.c:346 msgctxt "abbreviated month name" msgid "Oct" msgstr "אוק" -#: glib/gdatetime.c:342 +#: glib/gdatetime.c:348 msgctxt "abbreviated month name" msgid "Nov" msgstr "נוב" -#: glib/gdatetime.c:344 +#: glib/gdatetime.c:350 msgctxt "abbreviated month name" msgid "Dec" msgstr "דצמ" -#: glib/gdatetime.c:359 +#: glib/gdatetime.c:365 msgctxt "full weekday name" msgid "Monday" msgstr "יום שני" -#: glib/gdatetime.c:361 +#: glib/gdatetime.c:367 msgctxt "full weekday name" msgid "Tuesday" msgstr "יום שלישי" -#: glib/gdatetime.c:363 +#: glib/gdatetime.c:369 msgctxt "full weekday name" msgid "Wednesday" msgstr "יום רביעי" -#: glib/gdatetime.c:365 +#: glib/gdatetime.c:371 msgctxt "full weekday name" msgid "Thursday" msgstr "יום חמישי" -#: glib/gdatetime.c:367 +#: glib/gdatetime.c:373 msgctxt "full weekday name" msgid "Friday" msgstr "יום שישי" -#: glib/gdatetime.c:369 +#: glib/gdatetime.c:375 msgctxt "full weekday name" msgid "Saturday" msgstr "שבת" -#: glib/gdatetime.c:371 +#: glib/gdatetime.c:377 msgctxt "full weekday name" msgid "Sunday" msgstr "יום ראשון" -#: glib/gdatetime.c:386 +#: glib/gdatetime.c:392 msgctxt "abbreviated weekday name" msgid "Mon" msgstr "ב׳" -#: glib/gdatetime.c:388 +#: glib/gdatetime.c:394 msgctxt "abbreviated weekday name" msgid "Tue" msgstr "ג׳" -#: glib/gdatetime.c:390 +#: glib/gdatetime.c:396 msgctxt "abbreviated weekday name" msgid "Wed" msgstr "ד׳" -#: glib/gdatetime.c:392 +#: glib/gdatetime.c:398 msgctxt "abbreviated weekday name" msgid "Thu" msgstr "ה" -#: glib/gdatetime.c:394 +#: glib/gdatetime.c:400 msgctxt "abbreviated weekday name" msgid "Fri" msgstr "ו׳" -#: glib/gdatetime.c:396 +#: glib/gdatetime.c:402 msgctxt "abbreviated weekday name" msgid "Sat" msgstr "ש׳" -#: glib/gdatetime.c:398 +#: glib/gdatetime.c:404 msgctxt "abbreviated weekday name" msgid "Sun" msgstr "א׳" @@ -4613,62 +4747,62 @@ msgstr "א׳" #. * (western European, non-European) there is no difference between the #. * standalone and complete date form. #. -#: glib/gdatetime.c:462 +#: glib/gdatetime.c:468 msgctxt "full month name with day" msgid "January" msgstr "ינואר" -#: glib/gdatetime.c:464 +#: glib/gdatetime.c:470 msgctxt "full month name with day" msgid "February" msgstr "פברואר" -#: glib/gdatetime.c:466 +#: glib/gdatetime.c:472 msgctxt "full month name with day" msgid "March" msgstr "מרץ" -#: glib/gdatetime.c:468 +#: glib/gdatetime.c:474 msgctxt "full month name with day" msgid "April" msgstr "אפריל" -#: glib/gdatetime.c:470 +#: glib/gdatetime.c:476 msgctxt "full month name with day" msgid "May" msgstr "מאי" -#: glib/gdatetime.c:472 +#: glib/gdatetime.c:478 msgctxt "full month name with day" msgid "June" msgstr "יוני" -#: glib/gdatetime.c:474 +#: glib/gdatetime.c:480 msgctxt "full month name with day" msgid "July" msgstr "יולי" -#: glib/gdatetime.c:476 +#: glib/gdatetime.c:482 msgctxt "full month name with day" msgid "August" msgstr "אוגוסט" -#: glib/gdatetime.c:478 +#: glib/gdatetime.c:484 msgctxt "full month name with day" msgid "September" msgstr "ספטמבר" -#: glib/gdatetime.c:480 +#: glib/gdatetime.c:486 msgctxt "full month name with day" msgid "October" msgstr "אוקטובר" -#: glib/gdatetime.c:482 +#: glib/gdatetime.c:488 msgctxt "full month name with day" msgid "November" msgstr "נובמבר" -#: glib/gdatetime.c:484 +#: glib/gdatetime.c:490 msgctxt "full month name with day" msgid "December" msgstr "דצמבר" @@ -4690,74 +4824,74 @@ msgstr "דצמבר" #. * month names almost ready to copy and paste here. In other systems #. * due to a bug the result is incorrect in some languages. #. -#: glib/gdatetime.c:549 +#: glib/gdatetime.c:555 msgctxt "abbreviated month name with day" msgid "Jan" msgstr "ינו" -#: glib/gdatetime.c:551 +#: glib/gdatetime.c:557 msgctxt "abbreviated month name with day" msgid "Feb" msgstr "פבר" -#: glib/gdatetime.c:553 +#: glib/gdatetime.c:559 msgctxt "abbreviated month name with day" msgid "Mar" msgstr "מרץ" -#: glib/gdatetime.c:555 +#: glib/gdatetime.c:561 msgctxt "abbreviated month name with day" msgid "Apr" msgstr "אפר" -#: glib/gdatetime.c:557 +#: glib/gdatetime.c:563 msgctxt "abbreviated month name with day" msgid "May" msgstr "מאי" -#: glib/gdatetime.c:559 +#: glib/gdatetime.c:565 msgctxt "abbreviated month name with day" msgid "Jun" msgstr "יונ" -#: glib/gdatetime.c:561 +#: glib/gdatetime.c:567 msgctxt "abbreviated month name with day" msgid "Jul" msgstr "יול" -#: glib/gdatetime.c:563 +#: glib/gdatetime.c:569 msgctxt "abbreviated month name with day" msgid "Aug" msgstr "אוג" -#: glib/gdatetime.c:565 +#: glib/gdatetime.c:571 msgctxt "abbreviated month name with day" msgid "Sep" msgstr "ספט" -#: glib/gdatetime.c:567 +#: glib/gdatetime.c:573 msgctxt "abbreviated month name with day" msgid "Oct" msgstr "אוק" -#: glib/gdatetime.c:569 +#: glib/gdatetime.c:575 msgctxt "abbreviated month name with day" msgid "Nov" msgstr "נוב" -#: glib/gdatetime.c:571 +#: glib/gdatetime.c:577 msgctxt "abbreviated month name with day" msgid "Dec" msgstr "דצמ" #. Translators: 'before midday' indicator -#: glib/gdatetime.c:588 +#: glib/gdatetime.c:594 msgctxt "GDateTime" msgid "AM" msgstr "AM" #. Translators: 'after midday' indicator -#: glib/gdatetime.c:591 +#: glib/gdatetime.c:597 msgctxt "GDateTime" msgid "PM" msgstr "PM" @@ -4771,8 +4905,10 @@ msgstr "Error opening directory “%s”: %s" #, c-format msgid "Could not allocate %lu byte to read file “%s”" msgid_plural "Could not allocate %lu bytes to read file “%s”" -msgstr[0] "Could not allocate %lu bytes to read file “%s”" -msgstr[1] "Could not allocate %lu bytes to read file \"%s\"" +msgstr[0] "Could not allocate %lu byte to read file “%s”" +msgstr[1] "Could not allocate %lu bytes to read file “%s”" +msgstr[2] "Could not allocate %lu bytes to read file “%s”" +msgstr[3] "Could not allocate %lu bytes to read file “%s”" #: glib/gfileutils.c:754 #, c-format @@ -4789,79 +4925,79 @@ msgstr "File “%s” is too large" msgid "Failed to read from file “%s”: %s" msgstr "Failed to read from file “%s”: %s" -#: glib/gfileutils.c:902 glib/gfileutils.c:974 glib/gfileutils.c:1466 +#: glib/gfileutils.c:904 glib/gfileutils.c:979 glib/gfileutils.c:1468 #, c-format msgid "Failed to open file “%s”: %s" msgstr "Failed to open file “%s”: %s" -#: glib/gfileutils.c:914 +#: glib/gfileutils.c:917 #, c-format msgid "Failed to get attributes of file “%s”: fstat() failed: %s" msgstr "Failed to get attributes of file “%s”: fstat() failed: %s" -#: glib/gfileutils.c:944 +#: glib/gfileutils.c:948 #, c-format msgid "Failed to open file “%s”: fdopen() failed: %s" msgstr "Failed to open file “%s”: fdopen() failed: %s" -#: glib/gfileutils.c:1044 +#: glib/gfileutils.c:1049 #, c-format msgid "Failed to rename file “%s” to “%s”: g_rename() failed: %s" msgstr "Failed to rename file “%s” to “%s”: g_rename() failed: %s" -#: glib/gfileutils.c:1169 +#: glib/gfileutils.c:1175 #, c-format msgid "Failed to write file “%s”: write() failed: %s" msgstr "Failed to write file “%s”: write() failed: %s" -#: glib/gfileutils.c:1189 +#: glib/gfileutils.c:1196 #, c-format msgid "Failed to write file “%s”: fsync() failed: %s" msgstr "Failed to write file “%s”: fsync() failed: %s" -#: glib/gfileutils.c:1357 glib/gfileutils.c:1769 +#: glib/gfileutils.c:1357 glib/gfileutils.c:1772 #, c-format msgid "Failed to create file “%s”: %s" msgstr "Failed to create file “%s”: %s" -#: glib/gfileutils.c:1401 +#: glib/gfileutils.c:1402 #, c-format msgid "Existing file “%s” could not be removed: g_unlink() failed: %s" msgstr "Existing file “%s” could not be removed: g_unlink() failed: %s" -#: glib/gfileutils.c:1735 +#: glib/gfileutils.c:1737 #, c-format msgid "Template “%s” invalid, should not contain a “%s”" msgstr "Template “%s” invalid, should not contain a “%s”" -#: glib/gfileutils.c:1748 +#: glib/gfileutils.c:1750 #, c-format msgid "Template “%s” doesn’t contain XXXXXX" msgstr "Template “%s” doesn’t contain XXXXXX" -#: glib/gfileutils.c:2306 glib/gfileutils.c:2334 +#: glib/gfileutils.c:2310 glib/gfileutils.c:2339 #, c-format msgid "Failed to read the symbolic link “%s”: %s" msgstr "Failed to read the symbolic link “%s”: %s" -#: glib/giochannel.c:1396 +#: glib/giochannel.c:1405 #, c-format msgid "Could not open converter from “%s” to “%s”: %s" msgstr "Could not open converter from “%s” to “%s”: %s" -#: glib/giochannel.c:1749 +#: glib/giochannel.c:1758 msgid "Can’t do a raw read in g_io_channel_read_line_string" msgstr "Can’t do a raw read in g_io_channel_read_line_string" -#: glib/giochannel.c:1796 glib/giochannel.c:2054 glib/giochannel.c:2141 +#: glib/giochannel.c:1805 glib/giochannel.c:2063 glib/giochannel.c:2150 msgid "Leftover unconverted data in read buffer" msgstr "Left over unconverted data in read buffer" -#: glib/giochannel.c:1877 glib/giochannel.c:1954 +#: glib/giochannel.c:1886 glib/giochannel.c:1963 msgid "Channel terminates in a partial character" msgstr "Channel terminates in a partial character" -#: glib/giochannel.c:1940 +#: glib/giochannel.c:1949 msgid "Can’t do a raw read in g_io_channel_read_to_end" msgstr "Can’t do a raw read in g_io_channel_read_to_end" @@ -4873,57 +5009,57 @@ msgstr "Valid key file could not be found in search dirs" msgid "Not a regular file" msgstr "Not a regular file" -#: glib/gkeyfile.c:1275 +#: glib/gkeyfile.c:1281 #, c-format msgid "" "Key file contains line “%s” which is not a key-value pair, group, or comment" msgstr "" "Key file contains line “%s” which is not a key-value pair, group, or comment" -#: glib/gkeyfile.c:1332 +#: glib/gkeyfile.c:1338 #, c-format msgid "Invalid group name: %s" msgstr "Invalid group name: %s" -#: glib/gkeyfile.c:1354 +#: glib/gkeyfile.c:1360 msgid "Key file does not start with a group" msgstr "Key file does not start with a group" -#: glib/gkeyfile.c:1380 +#: glib/gkeyfile.c:1386 #, c-format msgid "Invalid key name: %s" msgstr "Invalid key name: %s" -#: glib/gkeyfile.c:1407 +#: glib/gkeyfile.c:1413 #, c-format msgid "Key file contains unsupported encoding “%s”" msgstr "Key file contains unsupported encoding “%s”" -#: glib/gkeyfile.c:1650 glib/gkeyfile.c:1823 glib/gkeyfile.c:3276 -#: glib/gkeyfile.c:3340 glib/gkeyfile.c:3470 glib/gkeyfile.c:3602 -#: glib/gkeyfile.c:3748 glib/gkeyfile.c:3977 glib/gkeyfile.c:4044 +#: glib/gkeyfile.c:1662 glib/gkeyfile.c:1835 glib/gkeyfile.c:3288 +#: glib/gkeyfile.c:3352 glib/gkeyfile.c:3482 glib/gkeyfile.c:3614 +#: glib/gkeyfile.c:3760 glib/gkeyfile.c:3995 glib/gkeyfile.c:4062 #, c-format msgid "Key file does not have group “%s”" msgstr "Key file does not have group “%s”" -#: glib/gkeyfile.c:1778 +#: glib/gkeyfile.c:1790 #, c-format msgid "Key file does not have key “%s” in group “%s”" msgstr "Key file does not have key “%s” in group “%s”" -#: glib/gkeyfile.c:1940 glib/gkeyfile.c:2056 +#: glib/gkeyfile.c:1952 glib/gkeyfile.c:2068 #, c-format msgid "Key file contains key “%s” with value “%s” which is not UTF-8" msgstr "Key file contains key “%s” with value “%s” which is not UTF-8" -#: glib/gkeyfile.c:1960 glib/gkeyfile.c:2076 glib/gkeyfile.c:2518 +#: glib/gkeyfile.c:1972 glib/gkeyfile.c:2088 glib/gkeyfile.c:2530 #, c-format msgid "" "Key file contains key “%s” which has a value that cannot be interpreted." msgstr "" "Key file contains key “%s” which has a value that cannot be interpreted." -#: glib/gkeyfile.c:2736 glib/gkeyfile.c:3105 +#: glib/gkeyfile.c:2748 glib/gkeyfile.c:3117 #, c-format msgid "" "Key file contains key “%s” in group “%s” which has a value that cannot be " @@ -4932,36 +5068,36 @@ msgstr "" "Key file contains key “%s” in group “%s” which has a value that cannot be " "interpreted." -#: glib/gkeyfile.c:2814 glib/gkeyfile.c:2891 +#: glib/gkeyfile.c:2826 glib/gkeyfile.c:2903 #, c-format msgid "Key “%s” in group “%s” has value “%s” where %s was expected" msgstr "Key “%s” in group “%s” has value “%s” where %s was expected" -#: glib/gkeyfile.c:4284 +#: glib/gkeyfile.c:4305 msgid "Key file contains escape character at end of line" msgstr "Key file contains escape character at end of line" -#: glib/gkeyfile.c:4306 +#: glib/gkeyfile.c:4327 #, c-format msgid "Key file contains invalid escape sequence “%s”" msgstr "Key file contains invalid escape sequence “%s”" -#: glib/gkeyfile.c:4450 +#: glib/gkeyfile.c:4471 #, c-format msgid "Value “%s” cannot be interpreted as a number." msgstr "Value “%s” cannot be interpreted as a number." -#: glib/gkeyfile.c:4464 +#: glib/gkeyfile.c:4485 #, c-format msgid "Integer value “%s” out of range" msgstr "Integer value “%s” out of range" -#: glib/gkeyfile.c:4497 +#: glib/gkeyfile.c:4518 #, c-format msgid "Value “%s” cannot be interpreted as a float number." msgstr "Value “%s” cannot be interpreted as a float number." -#: glib/gkeyfile.c:4536 +#: glib/gkeyfile.c:4557 #, c-format msgid "Value “%s” cannot be interpreted as a boolean." msgstr "Value “%s” cannot be interpreted as a boolean." @@ -5246,12 +5382,12 @@ msgstr "Double value “%s” for %s out of range" msgid "Error parsing option %s" msgstr "Error parsing option %s" -#: glib/goption.c:1570 glib/goption.c:1683 +#: glib/goption.c:1561 glib/goption.c:1674 #, c-format msgid "Missing argument for %s" msgstr "Missing·argument·for·%s" -#: glib/goption.c:2194 +#: glib/goption.c:2185 #, c-format msgid "Unknown option %s" msgstr "Unknown option %s" @@ -5645,82 +5781,82 @@ msgstr "Text ended before matching quote was found for %c. (The text was “%s msgid "Text was empty (or contained only whitespace)" msgstr "Text was empty (or contained only whitespace)" -#: glib/gspawn.c:323 +#: glib/gspawn.c:308 #, c-format msgid "Failed to read data from child process (%s)" msgstr "Failed to read data from child process (%s)" -#: glib/gspawn.c:468 +#: glib/gspawn.c:455 #, c-format msgid "Unexpected error in reading data from a child process (%s)" msgstr "Unexpected error in reading data from a child process (%s)" -#: glib/gspawn.c:553 +#: glib/gspawn.c:540 #, c-format msgid "Unexpected error in waitpid() (%s)" msgstr "Unexpected error in waitpid() (%s)" -#: glib/gspawn.c:1061 glib/gspawn-win32.c:1329 +#: glib/gspawn.c:1144 glib/gspawn-win32.c:1383 #, c-format msgid "Child process exited with code %ld" msgstr "Child process exited with code %ld" -#: glib/gspawn.c:1069 +#: glib/gspawn.c:1152 #, c-format msgid "Child process killed by signal %ld" msgstr "Child process killed by signal %ld" -#: glib/gspawn.c:1076 +#: glib/gspawn.c:1159 #, c-format msgid "Child process stopped by signal %ld" msgstr "Child process stopped by signal %ld" -#: glib/gspawn.c:1083 +#: glib/gspawn.c:1166 #, c-format msgid "Child process exited abnormally" msgstr "Child process exited abnormally" -#: glib/gspawn.c:1532 glib/gspawn-win32.c:350 glib/gspawn-win32.c:358 +#: glib/gspawn.c:1757 glib/gspawn-win32.c:350 glib/gspawn-win32.c:358 #, c-format msgid "Failed to read from child pipe (%s)" msgstr "Failed to read from child pipe (%s)" -#: glib/gspawn.c:1788 +#: glib/gspawn.c:2059 #, c-format msgid "Failed to spawn child process “%s” (%s)" msgstr "Failed to spawn child process “%s” (%s)" -#: glib/gspawn.c:1871 +#: glib/gspawn.c:2176 #, c-format msgid "Failed to fork (%s)" msgstr "Failed to fork (%s)" -#: glib/gspawn.c:2026 glib/gspawn-win32.c:381 +#: glib/gspawn.c:2336 glib/gspawn-win32.c:381 #, c-format msgid "Failed to change to directory “%s” (%s)" msgstr "Failed to change to directory “%s” (%s)" -#: glib/gspawn.c:2036 +#: glib/gspawn.c:2346 #, c-format msgid "Failed to execute child process “%s” (%s)" msgstr "Failed to execute child process “%s” (%s)" -#: glib/gspawn.c:2046 +#: glib/gspawn.c:2356 #, c-format msgid "Failed to redirect output or input of child process (%s)" msgstr "Failed to redirect output or input of child process (%s)" -#: glib/gspawn.c:2055 +#: glib/gspawn.c:2365 #, c-format msgid "Failed to fork child process (%s)" msgstr "Failed to fork child process (%s)" -#: glib/gspawn.c:2063 +#: glib/gspawn.c:2373 #, c-format msgid "Unknown error executing child process “%s”" msgstr "Unknown error executing child process “%s”" -#: glib/gspawn.c:2087 +#: glib/gspawn.c:2397 #, c-format msgid "Failed to read enough data from child pid pipe (%s)" msgstr "Failed to read enough data from child pid pipe (%s)" @@ -5744,27 +5880,27 @@ msgstr "Failed to execute child process (%s)" msgid "Invalid program name: %s" msgstr "Invalid program name: %s" -#: glib/gspawn-win32.c:471 glib/gspawn-win32.c:725 +#: glib/gspawn-win32.c:471 glib/gspawn-win32.c:757 #, c-format msgid "Invalid string in argument vector at %d: %s" msgstr "Invalid string in argument vector at %d: %s" -#: glib/gspawn-win32.c:482 glib/gspawn-win32.c:740 +#: glib/gspawn-win32.c:482 glib/gspawn-win32.c:772 #, c-format msgid "Invalid string in environment: %s" msgstr "Invalid string in environment: %s" -#: glib/gspawn-win32.c:721 +#: glib/gspawn-win32.c:753 #, c-format msgid "Invalid working directory: %s" msgstr "Invalid working directory: %s" -#: glib/gspawn-win32.c:783 +#: glib/gspawn-win32.c:815 #, c-format msgid "Failed to execute helper program (%s)" msgstr "Failed to execute helper program (%s)" -#: glib/gspawn-win32.c:1056 +#: glib/gspawn-win32.c:1042 msgid "" "Unexpected error in g_io_channel_win32_poll() reading data from a child " "process" @@ -5772,77 +5908,79 @@ msgstr "" "Unexpected error in g_io_channel_win32_poll() reading data from a child " "process" -#: glib/gstrfuncs.c:3303 glib/gstrfuncs.c:3405 +#: glib/gstrfuncs.c:3338 glib/gstrfuncs.c:3440 msgid "Empty string is not a number" msgstr "Empty string is not a number" -#: glib/gstrfuncs.c:3327 +#: glib/gstrfuncs.c:3362 #, c-format msgid "“%s” is not a signed number" msgstr "“%s” is not a signed number" -#: glib/gstrfuncs.c:3337 glib/gstrfuncs.c:3441 +#: glib/gstrfuncs.c:3372 glib/gstrfuncs.c:3476 #, c-format msgid "Number “%s” is out of bounds [%s, %s]" msgstr "Number “%s” is out of bounds [%s, %s]" -#: glib/gstrfuncs.c:3431 +#: glib/gstrfuncs.c:3466 #, c-format msgid "“%s” is not an unsigned number" msgstr "“%s” is not an unsigned number" -#: glib/guri.c:313 +#: glib/guri.c:315 #, no-c-format -#| msgid " (invalid encoding)" msgid "Invalid %-encoding in URI" msgstr "Invalid %-encoding in URI" -#: glib/guri.c:330 +#: glib/guri.c:332 msgid "Illegal character in URI" msgstr "Illegal character in URI" -#: glib/guri.c:359 +#: glib/guri.c:366 msgid "Non-UTF-8 characters in URI" msgstr "Non-UTF-8 characters in URI" -#: glib/guri.c:462 +#: glib/guri.c:546 #, c-format msgid "Invalid IPv6 address ‘%.*s’ in URI" msgstr "Invalid IPv6 address ‘%.*s’ in URI" -#: glib/guri.c:524 +#: glib/guri.c:601 #, c-format msgid "Illegal encoded IP address ‘%.*s’ in URI" msgstr "Illegal encoded IP address ‘%.*s’ in URI" -#: glib/guri.c:558 glib/guri.c:570 +#: glib/guri.c:613 +#, c-format +#| msgid "Illegal encoded IP address ‘%.*s’ in URI" +msgid "Illegal internationalized hostname ‘%.*s’ in URI" +msgstr "Illegal internationalized hostname ‘%.*s’ in URI" + +#: glib/guri.c:645 glib/guri.c:657 #, c-format -#| msgid "Could not parse “%s” as IP address mask" msgid "Could not parse port ‘%.*s’ in URI" msgstr "Could not parse port ‘%.*s’ in URI" -#: glib/guri.c:577 +#: glib/guri.c:664 #, c-format -#| msgid "Double value “%s” for %s out of range" msgid "Port ‘%.*s’ in URI is out of range" msgstr "Port ‘%.*s’ in URI is out of range" -#: glib/guri.c:1055 glib/guri.c:1119 +#: glib/guri.c:1224 glib/guri.c:1288 #, c-format -#| msgid "The pathname “%s” is not an absolute path" msgid "URI ‘%s’ is not an absolute URI" msgstr "URI ‘%s’ is not an absolute URI" -#: glib/guri.c:1061 +#: glib/guri.c:1230 #, c-format msgid "URI ‘%s’ has no host component" msgstr "URI ‘%s’ has no host component" -#: glib/guri.c:1263 +#: glib/guri.c:1435 msgid "URI is not absolute, and no base URI was provided" msgstr "URI is not absolute, and no base URI was provided" -#: glib/guri.c:2019 +#: glib/guri.c:2209 msgid "Missing ‘=’ and parameter value" msgstr "Missing ‘=’ and parameter value" @@ -5864,596 +6002,218 @@ msgid "Character out of range for UTF-16" msgstr "Character out of range for UTF-16" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2756 +#: glib/gutils.c:2767 #, c-format msgid "%.1f kB" msgstr "%.1f ק״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2758 +#: glib/gutils.c:2769 #, c-format msgid "%.1f MB" msgstr "%.1f מ״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2760 +#: glib/gutils.c:2771 #, c-format msgid "%.1f GB" msgstr "%.1f ג״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2762 +#: glib/gutils.c:2773 #, c-format msgid "%.1f TB" msgstr "%.1f ט״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2764 +#: glib/gutils.c:2775 #, c-format msgid "%.1f PB" msgstr "%.1f פ״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2766 +#: glib/gutils.c:2777 #, c-format msgid "%.1f EB" msgstr "%.1f א״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2770 +#: glib/gutils.c:2781 #, c-format msgid "%.1f KiB" msgstr "%.1f קי״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2772 +#: glib/gutils.c:2783 #, c-format msgid "%.1f MiB" msgstr "%.1f מבי״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2774 +#: glib/gutils.c:2785 #, c-format msgid "%.1f GiB" msgstr "%.1f גיב״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2776 +#: glib/gutils.c:2787 #, c-format msgid "%.1f TiB" msgstr "%.1f טבי״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2778 +#: glib/gutils.c:2789 #, c-format msgid "%.1f PiB" msgstr "%.1f פבי״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2780 +#: glib/gutils.c:2791 #, c-format msgid "%.1f EiB" msgstr "%.1f אק״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2784 +#: glib/gutils.c:2795 #, c-format msgid "%.1f kb" msgstr "%.1f ק״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2786 +#: glib/gutils.c:2797 #, c-format msgid "%.1f Mb" msgstr "%.1f מ״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2788 +#: glib/gutils.c:2799 #, c-format msgid "%.1f Gb" msgstr "%.1f ג״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2790 +#: glib/gutils.c:2801 #, c-format msgid "%.1f Tb" msgstr "%.1f ט״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2792 +#: glib/gutils.c:2803 #, c-format msgid "%.1f Pb" msgstr "%.1f פ״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2794 +#: glib/gutils.c:2805 #, c-format msgid "%.1f Eb" msgstr "%.1f א״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2798 +#: glib/gutils.c:2809 #, c-format msgid "%.1f Kib" msgstr "%.1f ק״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2800 +#: glib/gutils.c:2811 #, c-format msgid "%.1f Mib" msgstr "%.1f מ״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2802 +#: glib/gutils.c:2813 #, c-format msgid "%.1f Gib" msgstr "%.1f ג״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2804 +#: glib/gutils.c:2815 #, c-format msgid "%.1f Tib" msgstr "%.1f ט״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2806 +#: glib/gutils.c:2817 #, c-format msgid "%.1f Pib" msgstr "%.1f פ״ב" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2808 +#: glib/gutils.c:2819 #, c-format msgid "%.1f Eib" msgstr "%.1f א״ב" -#: glib/gutils.c:2842 glib/gutils.c:2959 +#: glib/gutils.c:2853 glib/gutils.c:2970 #, c-format msgid "%u byte" msgid_plural "%u bytes" msgstr[0] "בית אחד" -msgstr[1] "%u בתים" +msgstr[1] "שני בתים" +msgstr[2] "%u בתים" +msgstr[3] "%u בתים" -#: glib/gutils.c:2846 +#: glib/gutils.c:2857 #, c-format msgid "%u bit" msgid_plural "%u bits" msgstr[0] "סיבית אחת" -msgstr[1] "%u סיביות" +msgstr[1] "שתי סיביות" +msgstr[2] "%u סיביות" +msgstr[3] "%u סיביות" #. Translators: the %s in "%s bytes" will always be replaced by a number. -#: glib/gutils.c:2913 +#: glib/gutils.c:2924 #, c-format msgid "%s byte" msgid_plural "%s bytes" msgstr[0] "בית אחד" -msgstr[1] "%s בתים" +msgstr[1] "שני בתים" +msgstr[2] "%s בתים" +msgstr[3] "%s בתים" #. Translators: the %s in "%s bits" will always be replaced by a number. -#: glib/gutils.c:2918 +#: glib/gutils.c:2929 #, c-format msgid "%s bit" msgid_plural "%s bits" msgstr[0] "סיבית אחת" -msgstr[1] "%s סיביות" +msgstr[1] "שתי סיביות" +msgstr[2] "%s סיביות" +msgstr[3] "%s סיביות" #. Translators: this is from the deprecated function g_format_size_for_display() which uses 'KB' to #. * mean 1024 bytes. I am aware that 'KB' is not correct, but it has been preserved for reasons of #. * compatibility. Users will not see this string unless a program is using this deprecated function. #. * Please translate as literally as possible. #. -#: glib/gutils.c:2972 +#: glib/gutils.c:2983 #, c-format msgid "%.1f KB" msgstr "%.1f ק״ב" -#: glib/gutils.c:2977 +#: glib/gutils.c:2988 #, c-format msgid "%.1f MB" msgstr "%.1f מ״ב" -#: glib/gutils.c:2982 +#: glib/gutils.c:2993 #, c-format msgid "%.1f GB" msgstr "%.1f ג״ב" -#: glib/gutils.c:2987 +#: glib/gutils.c:2998 #, c-format msgid "%.1f TB" msgstr "%.1f ט״ב" -#: glib/gutils.c:2992 +#: glib/gutils.c:3003 #, c-format msgid "%.1f PB" msgstr "%.1f פ״ב" -#: glib/gutils.c:2997 +#: glib/gutils.c:3008 #, c-format msgid "%.1f EB" msgstr "%.1f א״ב" - -#~ msgid "Error in address “%s” — the family attribute is malformed" -#~ msgstr "Error in address “%s” — the family attribute is malformed" - -#~ msgid "No such method '%s'" -#~ msgstr "No such method '%s'" - -#~ msgid "" -#~ "Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment " -#~ "variable - unknown value '%s'" -#~ msgstr "" -#~ "Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment " -#~ "variable - unknown value '%s'" - -#~ msgid "" -#~ "Message has %d file descriptors but the header field indicates %d file " -#~ "descriptors" -#~ msgstr "" -#~ "Message has %d file descriptors but the header field indicates %d file " -#~ "descriptors" - -#~ msgid "[ARGS...]" -#~ msgstr "[ARGS...]" - -#~ msgid "Mounted %s at %s\n" -#~ msgstr "Mounted %s at %s\n" - -#~ msgid "Failed to create temp file: %s" -#~ msgstr "Failed to create temp file: %s" - -#~ msgid "; ignoring override for this key.\n" -#~ msgstr "; ignoring override for this key.\n" - -#~ msgid " and --strict was specified; exiting.\n" -#~ msgstr " and --strict was specified; exiting.\n" - -#~ msgid "Ignoring override for this key.\n" -#~ msgstr "Ignoring override for this key.\n" - -#~ msgid "doing nothing.\n" -#~ msgstr "doing nothing.\n" - -#~ msgid "Error: object path not specified.\n" -#~ msgstr "Error: object path not specified.\n" - -#~ msgid "Error: signal not specified.\n" -#~ msgstr "Error: signal not specified.\n" - -#~ msgid "Error: signal must be the fully-qualified name.\n" -#~ msgstr "Error: signal must be the fully-qualified name.\n" - -#~ msgid "No files given" -#~ msgstr "No files given" - -#~ msgid "Error getting writable attributes: %s\n" -#~ msgstr "Error getting writable attributes: %s\n" - -#~ msgid "Error mounting location: %s\n" -#~ msgstr "Error mounting location: %s\n" - -#~ msgid "Error unmounting mount: %s\n" -#~ msgstr "Error unmounting mount: %s\n" - -#~ msgid "Error finding enclosing mount: %s\n" -#~ msgstr "Error finding enclosing mount: %s\n" - -#~ msgid "Error ejecting mount: %s\n" -#~ msgstr "Error ejecting mount: %s\n" - -#~ msgid "Error mounting %s: %s\n" -#~ msgstr "Error mounting %s: %s\n" - -#~ msgid "No files to open" -#~ msgstr "No files to open" - -#~ msgid "No files to delete" -#~ msgstr "No files to delete" - -#~ msgid "Error setting attribute: %s\n" -#~ msgstr "Error setting attribute: %s\n" - -#~ msgid "No such interface" -#~ msgstr "No such interface" - -#~ msgid "Error creating directory '%s': %s" -#~ msgstr "Error creating directory '%s': %s" - -#~ msgid "Error opening file '%s': %s" -#~ msgstr "Error opening file '%s': %s" - -#~ msgid "Error reading file '%s': %s" -#~ msgstr "Error reading file '%s': %s" - -#~ msgid "No locations gives" -#~ msgstr "No locations gives" - -#~ msgid "Error renaming file: %s" -#~ msgstr "Error renaming file: %s" - -#~ msgid "Can't open directory" -#~ msgstr "Can't open directory" - -#~ msgid "Error opening file: %s" -#~ msgstr "Error opening file: %s" - -#~ msgid "Error creating directory: %s" -#~ msgstr "Error creating directory: %s" - -#~ msgid "association changes not supported on win32" -#~ msgstr "association changes not supported on win32" - -#~ msgid "Association creation not supported on win32" -#~ msgstr "Association creation not supported on win32" - -#~ msgid "Unable to find default local directory monitor type" -#~ msgstr "Unable to find default local directory monitor type" - -#~ msgid "URIs not supported" -#~ msgstr "URIs not supported" - -#~ msgid "Key file does not have key '%s'" -#~ msgstr "Key file does not have key '%s'" - -#~ msgid "" -#~ "Error processing input file with xmllint:\n" -#~ "%s" -#~ msgstr "" -#~ "Error processing input file with xmllint:\n" -#~ "%s" - -#~ msgid "" -#~ "Error processing input file with to-pixdata:\n" -#~ "%s" -#~ msgstr "" -#~ "Error processing input file with to-pixdata:\n" -#~ "%s" - -#~ msgid "Unable to get pending error: %s" -#~ msgstr "Unable to get pending error: %s" - -#~ msgid "Failed to open file '%s' for writing: fdopen() failed: %s" -#~ msgstr "Failed to open file '%s' for writing: fdopen() failed: %s" - -#~ msgid "Failed to write file '%s': fflush() failed: %s" -#~ msgstr "Failed to write file '%s': fflush() failed: %s" - -#~ msgid "Failed to close file '%s': fclose() failed: %s" -#~ msgstr "Failed to close file '%s': fclose() failed: %s" - -#~ msgid "Incomplete data received for '%s'" -#~ msgstr "Incomplete data received for '%s'" - -#~ msgid "" -#~ "Unexpected option length while checking if SO_PASSCRED is enabled for " -#~ "socket. Expected %d bytes, got %d" -#~ msgstr "" -#~ "Unexpected option length while checking if SO_PASSCRED is enabled for " -#~ "socket. Expected %d bytes, got %d" - -#~ msgid "Abnormal program termination spawning command line '%s': %s" -#~ msgstr "Abnormal program termination spawning command line '%s': %s" - -#~ msgid "Command line '%s' exited with non-zero exit status %d: %s" -#~ msgstr "Command line '%s' exited with non-zero exit status %d: %s" - -#~ msgid "workspace limit for empty substrings reached" -#~ msgstr "workspace limit for empty substrings reached" - -#~ msgid "case-changing escapes (\\l, \\L, \\u, \\U) are not allowed here" -#~ msgstr "case-changing escapes (\\l, \\L, \\u, \\U) are not allowed here" - -#~ msgid "repeating a DEFINE group is not allowed" -#~ msgstr "repeating a DEFINE group is not allowed" - -#~ msgid "No service record for '%s'" -#~ msgstr "No service record for '%s'" - -#~ msgid "Error connecting: " -#~ msgstr "Error connecting: " - -#~ msgid "Error connecting: %s" -#~ msgstr "Error connecting: %s" - -#~ msgid "Error reading from unix: %s" -#~ msgstr "Error reading from unix: %s" - -#~ msgid "Error writing to unix: %s" -#~ msgstr "Error writing to unix: %s" - -#~ msgid "File is empty" -#~ msgstr "File is empty" - -#~ msgid "" -#~ "Key file contains key '%s' which has value that cannot be interpreted." -#~ msgstr "" -#~ "Key file contains key '%s' which has value that cannot be interpreted." - -#~ msgid "This option will be removed soon." -#~ msgstr "This option will be removed soon." - -#~ msgid "Error stating file '%s': %s" -#~ msgstr "Error stating file '%s': %s" - -#~ msgid "SOCKSv4 implementation limits username to %i characters" -#~ msgstr "SOCKSv4 implementation limits username to %i characters" - -#~ msgid "SOCKSv4a implementation limits hostname to %i characters" -#~ msgstr "SOCKSv4a implementation limits hostname to %i characters" - -#~ msgctxt "GDateTime" -#~ msgid "am" -#~ msgstr "am" - -#~ msgctxt "GDateTime" -#~ msgid "pm" -#~ msgstr "pm" - -#~ msgid "Failed to set value\n" -#~ msgstr "Failed to set value\n" - -#~ msgid "Type of return value is incorrect, got '%s', expected '%s'" -#~ msgstr "Type of return value is incorrect, got '%s', expected '%s'" - -#~ msgid "" -#~ "Trying to set property %s of type %s but according to the expected " -#~ "interface the type is %s" -#~ msgstr "" -#~ "Trying to set property %s of type %s but according to the expected " -#~ "interface the type is %s" - -#~ msgid "No such schema '%s' specified in override file '%s'" -#~ msgstr "No such schema '%s' specified in override file '%s'" - -#~ msgid "" -#~ "Commands:\n" -#~ " help Show this information\n" -#~ " get Get the value of a key\n" -#~ " set Set the value of a key\n" -#~ " reset Reset the value of a key\n" -#~ " monitor Monitor a key for changes\n" -#~ " writable Check if a key is writable\n" -#~ "\n" -#~ "Use '%s COMMAND --help' to get help for individual commands.\n" -#~ msgstr "" -#~ "Commands:\n" -#~ " help Show this information\n" -#~ " get Get the value of a key\n" -#~ " set Set the value of a key\n" -#~ " reset Reset the value of a key\n" -#~ " monitor Monitor a key for changes\n" -#~ " writable Check if a key is writable\n" -#~ "\n" -#~ "Use '%s COMMAND --help' to get help for individual commands.\n" - -#~ msgid "Specify the path for the schema" -#~ msgstr "Specify the path for the schema" - -#~ msgid "" -#~ "Arguments:\n" -#~ " SCHEMA The id of the schema\n" -#~ " KEY The name of the key\n" -#~ " VALUE The value to set key to, as a serialized GVariant\n" -#~ msgstr "" -#~ "Arguments:\n" -#~ " SCHEMA The id of the schema\n" -#~ " KEY The name of the key\n" -#~ " VALUE The value to set key to, as a serialized GVariant\n" - -#~ msgid "" -#~ "Monitor KEY for changes and print the changed values.\n" -#~ "Monitoring will continue until the process is terminated." -#~ msgstr "" -#~ "Monitor KEY for changes and print the changed values.\n" -#~ "Monitoring will continue until the process is terminated." - -#~ msgid "Error writing first 16 bytes of message to socket: " -#~ msgstr "Error writing first 16 bytes of message to socket: " - -#~ msgid "The nonce-file '%s' was %lu bytes. Expected 16 bytes." -#~ msgstr "The nonce-file '%s' was %lu bytes. Expected 16 bytes." - -#~ msgid "Encountered array of length %" -#~ msgstr "Encountered array of length %" - -#~ msgid "Do not give error for empty directory" -#~ msgstr "Can't move directory over directory" - -#~ msgid "Invalid UTF-8 sequence in input" -#~ msgstr "Invalid sequence in conversion input" - -#~ msgid "Reached maximum data array limit" -#~ msgstr "Reached maximum data array limit" - -#~ msgid "do not hide entries" -#~ msgstr "do not hide entries" - -#~ msgid "" -#~ "Character '%s' is not valid at the start of an entity name; the & " -#~ "character begins an entity; if this ampersand isn't supposed to be an " -#~ "entity, escape it as &" -#~ msgstr "" -#~ "Character '%s' is not valid at the start of an entity name; the & " -#~ "character begins an entity; if this ampersand isn't supposed to be an " -#~ "entity, escape it as &" - -#~ msgid "Character '%s' is not valid inside an entity name" -#~ msgstr "Character '%s' is not valid inside an entity name" - -#~ msgid "Empty character reference; should include a digit such as dž" -#~ msgstr "Empty character reference; should include a digit such as dž" - -#~ msgid "Unfinished entity reference" -#~ msgstr "Unfinished entity reference" - -#~ msgid "Unfinished character reference" -#~ msgstr "Unfinished character reference" - -#~ msgid "Invalid UTF-8 encoded text - overlong sequence" -#~ msgstr "Invalid UTF-8 encoded text - overlong sequence" - -#~ msgid "Invalid UTF-8 encoded text - not a start char" -#~ msgstr "Invalid UTF-8 encoded text - not a start char" - -#~ msgid "file" -#~ msgstr "file" - -#~ msgid "The file containing the icon" -#~ msgstr "The file containing the icon" - -#~ msgid "An array containing the icon names" -#~ msgstr "An array containing the icon names" - -#~ msgid "" -#~ "Whether to use default fallbacks found by shortening the name at '-' " -#~ "characters. Ignores names after the first if multiple names are given." -#~ msgstr "" -#~ "Whether to use default fallbacks found by shortening the name at '-' " -#~ "characters. Ignores names after the first if multiple names are given." - -#~ msgid "File descriptor" -#~ msgstr "File descriptor" - -#~ msgid "The file descriptor to read from" -#~ msgstr "The file descriptor to read from" - -#~ msgid "Close file descriptor" -#~ msgstr "Close file descriptor" - -#~ msgid "Whether to close the file descriptor when the stream is closed" -#~ msgstr "Whether to close the file descriptor when the stream is closed" - -#~ msgid "Can't load just created desktop file" -#~ msgstr "Can't load just created desktop file" - -#~ msgid "Error creating backup link: %s" -#~ msgstr "Error creating backup link: %s" - -#~ msgid "Too large count value passed to g_input_stream_read_async" -#~ msgstr "Too large count value passed to g_input_stream_read_async" - -#~ msgid "Too large count value passed to g_input_stream_skip" -#~ msgstr "Too large count value passed to g_input_stream_skip" - -#~ msgid "Too large count value passed to g_input_stream_skip_async" -#~ msgstr "Too large count value passed to g_input_stream_skip_async" - -#~ msgid "Target file already exists" -#~ msgstr "Target file already exists" - -#~ msgid "Too large count value passed to g_output_stream_write" -#~ msgstr "Too large count value passed to g_output_stream_write" - -#~ msgid "Too large count value passed to g_output_stream_write_async" -#~ msgstr "Too large count value passed to g_output_stream_write_async" - -#~ msgid "Could not change file mode: fork() failed: %s" -#~ msgstr "Could not change file mode: fork() failed: %s" - -#~ msgid "Could not change file mode: chmod() failed: %s" -#~ msgstr "Could not change file mode: chmod() failed: %s" - -#~ msgid "Could not change file mode: Child terminated by signal: %s" -#~ msgstr "Could not change file mode: Child terminated by signal: %s" - -#~ msgid "Could not change file mode: Child terminated abnormally" -#~ msgstr "Could not change file mode: Child terminated abnormally" @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: glib master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/glib/issues\n" -"POT-Creation-Date: 2021-06-24 15:19+0000\n" -"PO-Revision-Date: 2021-07-06 21:57+0200\n" +"POT-Creation-Date: 2021-03-22 11:48+0000\n" +"PO-Revision-Date: 2021-04-29 20:01+0200\n" "Last-Translator: Quentin PAGÈS\n" "Language-Team: Tot en òc (totenoc.eu)\n" "Language: oc\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 3.0\n" +"X-Generator: Poedit 2.4.3\n" "X-Launchpad-Export-Date: 2016-10-11 14:28+0000\n" "X-Project-Style: gnome\n" @@ -170,6 +170,8 @@ msgid "Arguments:\n" msgstr "Paramètres :\n" #: gio/gapplication-tool.c:135 gio/gio-tool.c:224 +#, fuzzy +#| msgid "[ARGS...]" msgid "[ARGS…]" msgstr "[PARAMS...]" @@ -180,12 +182,15 @@ msgstr "Comandas :\n" #. Translators: do not translate 'help', but please translate 'COMMAND'. #: gio/gapplication-tool.c:148 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "Use '%s help COMMAND' to get detailed help.\n" +#| "\n" msgid "" "Use “%s help COMMAND” to get detailed help.\n" "\n" msgstr "" -"Utilizatz « %s help COMANDA » per obténer d’ajuda detalhada.\n" +"Utilizatz « %s help COMANDA » per obténer de l'ajuda detalhada.\n" "\n" #: gio/gapplication-tool.c:167 @@ -198,13 +203,17 @@ msgstr "" "\n" #: gio/gapplication-tool.c:173 -#, c-format +#, fuzzy, c-format +#| msgid "invalid application id: '%s'\n" msgid "invalid application id: “%s”\n" -msgstr "identificant d’aplicacion invalid : « %s »\n" +msgstr "identificant d'aplicacion invalid : « %s »\n" #. Translators: %s is replaced with a command name like 'list-actions' #: gio/gapplication-tool.c:184 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "'%s' takes no arguments\n" +#| "\n" msgid "" "“%s” takes no arguments\n" "\n" @@ -227,13 +236,16 @@ msgid "action name must be given after application id\n" msgstr "un nom d'accion deu èsser indicat aprèp l'identificant d'aplicacion\n" #: gio/gapplication-tool.c:327 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "invalid action name: '%s'\n" +#| "action names must consist of only alphanumerics, '-' and '.'\n" msgid "" "invalid action name: “%s”\n" "action names must consist of only alphanumerics, “-” and “.”\n" msgstr "" -"nom d’accion invalid : « %s »\n" -"los noms d’accions pòdon pas conténer que de caractèrs alfanumerics, « - » e " +"nom d'accion invalid : « %s »\n" +"los noms d'accions pòdon pas conténer que de caractèrs alfanumerics, « - » e " "« . »\n" #: gio/gapplication-tool.c:346 @@ -332,7 +344,8 @@ msgstr "" "La conversion del jòc de caractèrs « %s » cap a « %s » es pas presa en carga" #: gio/gcharsetconverter.c:460 glib/gconvert.c:325 -#, c-format +#, fuzzy, c-format +#| msgid "Could not open converter from '%s' to '%s'" msgid "Could not open converter from “%s” to “%s”" msgstr "Impossible de dobrir lo convertidor de « %s » cap a « %s »" @@ -377,15 +390,17 @@ msgid "Unexpected early end-of-stream" msgstr "Fin precòça de flux inesperada" #: gio/gdbusaddress.c:159 gio/gdbusaddress.c:233 gio/gdbusaddress.c:322 -#, c-format +#, fuzzy, c-format +#| msgid "Unsupported key '%s' in address entry '%s'" msgid "Unsupported key “%s” in address entry “%s”" -msgstr "Clau « %s » pas presa en carga dins l’element d’adreça « %s »" +msgstr "Clau « %s » pas presa en carga dins l'element d'adreça « %s »" #: gio/gdbusaddress.c:172 -#, c-format +#, fuzzy, c-format +#| msgid "Meaningless key/value pair combination in address entry '%s'" msgid "Meaningless key/value pair combination in address entry “%s”" msgstr "" -"Combinason clau/valor sens significacion dins l’element d’adreça « %s »" +"Combinason clau/valor sens significacion dins l'element d'adreça « %s »" #: gio/gdbusaddress.c:181 #, fuzzy, c-format @@ -447,70 +462,84 @@ msgstr "" "de signe egal" #: gio/gdbusaddress.c:517 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "Error unescaping key or value in Key/Value pair %d, '%s', in address " +#| "element '%s'" msgid "" "Error unescaping key or value in Key/Value pair %d, “%s”, in address element " "“%s”" msgstr "" -"Error al moment del desencodatge de la clau o de la valor dins lo parelh " -"clau/valor %d, « %s », dins l’element d’adreça « %s »" +"Error al moment del desencodatge de la clau o de la valor dins lo couple " +"clau/valor %d, « %s », dins l'element d'adreça « %s »" #: gio/gdbusaddress.c:589 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "Error in address '%s' - the unix transport requires exactly one of the " +#| "keys 'path' or 'abstract' to be set" msgid "" "Error in address “%s” — the unix transport requires exactly one of the keys " "“path” or “abstract” to be set" msgstr "" -"Error dins l’adreça « %s » — lo transpòrt Unix requerís que siá exactament " +"Error dins l'adreça « %s » — lo transpòrt Unix requerís que siá exactement " "definida una de las claus « path » o « abstract »" #: gio/gdbusaddress.c:625 -#, c-format +#, fuzzy, c-format +#| msgid "Error in address '%s' - the host attribute is missing or malformed" msgid "Error in address “%s” — the host attribute is missing or malformed" msgstr "" -"Error dins l’adreça « %s » — l’atribut de l’òste es mancant o malformat" +"Error dins l'adreça « %s » — l'atribut de l'òste es mancant o mal format" #: gio/gdbusaddress.c:639 -#, c-format +#, fuzzy, c-format +#| msgid "Error in address '%s' - the port attribute is missing or malformed" msgid "Error in address “%s” — the port attribute is missing or malformed" -msgstr "Error dins l’adreça « %s » — l’atribut del pòrt es mancant o malformat" +msgstr "" +"Error dins l'adreça « %s » — l'atribut del pòrt es mancant o mal format" #: gio/gdbusaddress.c:653 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "Error in address '%s' - the noncefile attribute is missing or malformed" msgid "Error in address “%s” — the noncefile attribute is missing or malformed" msgstr "" -"Error dins l’adreça « %s » — l’atribut del fichièr amb denominacion unica es " -"mancant o malformat" +"Error dins l'adreça « %s » — l'atribut del fichièr de denominacion unica es " +"mancant o mal format" #: gio/gdbusaddress.c:674 msgid "Error auto-launching: " msgstr "Error d'aviada automatica : " #: gio/gdbusaddress.c:727 -#, c-format +#, fuzzy, c-format +#| msgid "Error opening nonce file '%s': %s" msgid "Error opening nonce file “%s”: %s" msgstr "" -"Error al moment de la dobertura del fichièr amb denominacion unica « %s » : " -"%s" +"Error al moment de la dobertura del fichièr de denominacion unica « %s » : %s" #: gio/gdbusaddress.c:746 -#, c-format +#, fuzzy, c-format +#| msgid "Error reading from nonce file '%s': %s" msgid "Error reading from nonce file “%s”: %s" -msgstr "Error de lectura del fichièr amb denominacion unica « %s » : %s" +msgstr "Error de lectura del fichièr de denominacion unica « %s » : %s" #: gio/gdbusaddress.c:755 -#, c-format +#, fuzzy, c-format +#| msgid "Error reading from nonce file '%s', expected 16 bytes, got %d" msgid "Error reading from nonce file “%s”, expected 16 bytes, got %d" msgstr "" -"Error de lectura del fichièr amb denominacion unica « %s », 16 octets " +"Error de lectura del fichièr de denominacion unica « %s », 16 octets " "esperats, %d recebuts" #: gio/gdbusaddress.c:773 -#, c-format +#, fuzzy, c-format +#| msgid "Error writing contents of nonce file '%s' to stream:" msgid "Error writing contents of nonce file “%s” to stream:" msgstr "" -"Error d’escritura del contengut del fichièr amb denominacion unica « %s » " -"sul flux :" +"Error d'escritura del contengut del fichièr a numerotacion unica « %s » sul " +"flux :" #: gio/gdbusaddress.c:988 msgid "The given address is empty" @@ -535,7 +564,8 @@ msgid "Cannot autolaunch D-Bus without X11 $DISPLAY" msgstr "Impossible d'aviar automaticament D-Bus sens $DISPLAY X11" #: gio/gdbusaddress.c:1157 -#, c-format +#, fuzzy, c-format +#| msgid "Error spawning command line '%s': " msgid "Error spawning command line “%s”: " msgstr "Error al moment de la generacion de la linha de comanda « %s » : " @@ -547,13 +577,16 @@ msgstr "" "aqueste sistèma operatiu)" #: gio/gdbusaddress.c:1397 gio/gdbusconnection.c:7241 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment " +#| "variable - unknown value '%s'" msgid "" "Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment variable " "— unknown value “%s”" msgstr "" -"Impossible de determinar l’adreça del bus a partir de la variabla " -"d’environament DBUS_STARTER_BUS_TYPE — valor desconeguda « %s »" +"Impossible de determinar l'adreça del bus a partir de la variabla " +"d'environament DBUS_STARTER_BUS_TYPE — valor desconeguda « %s »" #: gio/gdbusaddress.c:1406 gio/gdbusconnection.c:7250 msgid "" @@ -597,10 +630,11 @@ msgid "Cancelled via GDBusAuthObserver::authorize-authenticated-peer" msgstr "Anullat via GDBusAuthObserver::authorize-authenticated-peer" #: gio/gdbusauthmechanismsha1.c:298 -#, c-format +#, fuzzy, c-format +#| msgid "Error when getting information for directory '%s': %s" msgid "Error when getting information for directory “%s”: %s" msgstr "" -"Error al moment de la recuperacion d’informacion sul repertòri « %s » : %s" +"Error al moment de la recuperacion d'informacion sul repertòri « %s » : %s" #: gio/gdbusauthmechanismsha1.c:313 #, fuzzy, c-format @@ -628,7 +662,8 @@ msgid "Operation not supported" msgstr "Operacion pas presa en carga" #: gio/gdbusauthmechanismsha1.c:402 -#, c-format +#, fuzzy, c-format +#| msgid "Error opening keyring '%s' for reading: " msgid "Error opening keyring “%s” for reading: " msgstr "" "Error al moment de la dobertura del trossèl de claus « %s » en lectura : " @@ -672,30 +707,35 @@ msgstr "" "claus de « %s »" #: gio/gdbusauthmechanismsha1.c:523 -#, c-format +#, fuzzy, c-format +#| msgid "Error creating lock file '%s': %s" msgid "Error creating lock file “%s”: %s" msgstr "Error al moment de la creacion del fichièr verrolh « %s » : %s" #: gio/gdbusauthmechanismsha1.c:587 -#, c-format +#, fuzzy, c-format +#| msgid "Error deleting stale lock file '%s': %s" msgid "Error deleting stale lock file “%s”: %s" msgstr "" -"Error al moment de la destruccion de l’ancian fichièr verrolh « %s » : %s" +"Error al moment de la destruccion de l'ancian fichièr verrolh « %s » : %s" #: gio/gdbusauthmechanismsha1.c:626 -#, c-format +#, fuzzy, c-format +#| msgid "Error closing (unlinked) lock file '%s': %s" msgid "Error closing (unlinked) lock file “%s”: %s" msgstr "" -"Error al moment de la tampadura del fichièr verrolh (pas ligat) « %s » : %s" +"Error al moment de la tampadura del fichièr verrolh (non ligat) « %s » : %s" #: gio/gdbusauthmechanismsha1.c:637 -#, c-format +#, fuzzy, c-format +#| msgid "Error unlinking lock file '%s': %s" msgid "Error unlinking lock file “%s”: %s" msgstr "" "Error al moment de la supression del ligam amb lo fichièr verrolh « %s » : %s" #: gio/gdbusauthmechanismsha1.c:714 -#, c-format +#, fuzzy, c-format +#| msgid "Error opening keyring '%s' for writing: " msgid "Error opening keyring “%s” for writing: " msgstr "" "Error al moment de la dobertura del trossèl de claus « %s » en escritura : " @@ -732,22 +772,19 @@ msgstr "" "l'emplaçament %s" #: gio/gdbusconnection.c:4328 -#, fuzzy, c-format -#| msgid "No such property '%s'" +#, c-format msgid "No such property “%s”" msgstr "La proprietat « %s » existís pas" #: gio/gdbusconnection.c:4340 -#, fuzzy, c-format -#| msgid "Property '%s' is not readable" +#, c-format msgid "Property “%s” is not readable" -msgstr "La proprietat « %s » pòt pas èsser legida" +msgstr "La proprietat « %s » se pòt pas legir" #: gio/gdbusconnection.c:4351 -#, fuzzy, c-format -#| msgid "Property '%s' is not writable" +#, c-format msgid "Property “%s” is not writable" -msgstr "La proprietat « %s » pòt pas èsser escrita" +msgstr "La proprietat « %s » se pòt pas escriure" #: gio/gdbusconnection.c:4371 #, fuzzy, c-format @@ -771,7 +808,8 @@ msgid "No such interface “%s” on object at path %s" msgstr "L'interfàcia « %s » existís pas per l'objècte a l'emplaçament %s" #: gio/gdbusconnection.c:5000 -#, c-format +#, fuzzy, c-format +#| msgid "No such method '%s'" msgid "No such method “%s”" msgstr "Lo metòde « %s » existís pas" @@ -797,12 +835,14 @@ msgid "Unable to set property %s.%s" msgstr "Impossible de definir la proprietat %s.%s" #: gio/gdbusconnection.c:5690 -#, c-format +#, fuzzy, c-format +#| msgid "Method '%s' returned type '%s', but expected '%s'" msgid "Method “%s” returned type “%s”, but expected “%s”" msgstr "Lo metòde « %s » a renviat lo tipe « %s », mas « %s » èra esperat" #: gio/gdbusconnection.c:6792 -#, c-format +#, fuzzy, c-format +#| msgid "Method '%s' on interface '%s' with signature '%s' does not exist" msgid "Method “%s” on interface “%s” with signature “%s” does not exist" msgstr "" "Lo metòde « %s » sus l'interfàcia « %s » amb la signatura « %s » existís pas" @@ -856,7 +896,8 @@ msgstr[0] "Lectura de %lu octet demandada, mas solament %lu recebut(s)" msgstr[1] "Lectura de %lu octets demandada, mas solament %lu recebut(s)" #: gio/gdbusmessage.c:1391 -#, c-format +#, fuzzy, c-format +#| msgid "Expected NUL byte after the string '%s' but found byte %d" msgid "Expected NUL byte after the string “%s” but found byte %d" msgstr "" "Octet 00 (NUL) esperat a la fin de la cadena « %s » mas un octet %d es estat " @@ -927,7 +968,10 @@ msgstr "" "D-Bus" #: gio/gdbusmessage.c:1936 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "Error deserializing GVariant with type string '%s' from the D-Bus wire " +#| "format" msgid "" "Error deserializing GVariant with type string “%s” from the D-Bus wire format" msgstr "" @@ -956,7 +1000,8 @@ msgid "Signature header found but is not of type signature" msgstr "" #: gio/gdbusmessage.c:2200 -#, c-format +#, fuzzy, c-format +#| msgid "Signature header with signature '%s' found but message body is empty" msgid "Signature header with signature “%s” found but message body is empty" msgstr "" "Entèsta de signatura trobat amb la signatura « %s », mas lo còs del messatge " @@ -985,7 +1030,9 @@ msgid "Cannot deserialize message: " msgstr "Impossible de deserializar lo messatge : " #: gio/gdbusmessage.c:2601 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "Error serializing GVariant with type string '%s' to the D-Bus wire format" msgid "" "Error serializing GVariant with type string “%s” to the D-Bus wire format" msgstr "" @@ -1098,10 +1145,11 @@ msgstr "" "creacion d'un servidor" #: gio/gdbusserver.c:938 -#, c-format +#, fuzzy, c-format +#| msgid "Error writing nonce file at '%s': %s" msgid "Error writing nonce file at “%s”: %s" msgstr "" -"Error al moment de l’escritura del fichièr amb denominacion unica a « %s » : " +"Error al moment de l'escritura del fichièr de denominacion unica a « %s » : " "%s" #: gio/gdbusserver.c:1113 @@ -1111,9 +1159,10 @@ msgid "The string “%s” is not a valid D-Bus GUID" msgstr "La cadena « %s » es pas un GUID valid de D-Bus" #: gio/gdbusserver.c:1153 -#, c-format +#, fuzzy, c-format +#| msgid "Cannot listen on unsupported transport '%s'" msgid "Cannot listen on unsupported transport “%s”" -msgstr "Impossible d’escotar sul transpòrt « %s » pas pres en carga" +msgstr "Impossible d'escotar sul transpòrt « %s » pas pres en carga" #: gio/gdbus-tool.c:111 #, fuzzy, c-format @@ -1200,21 +1249,26 @@ msgid "Multiple connection endpoints specified" msgstr "Mantun punt terminals de connexion definits" #: gio/gdbus-tool.c:522 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "Warning: According to introspection data, interface '%s' does not exist\n" msgid "" "Warning: According to introspection data, interface “%s” does not exist\n" msgstr "" -"Avertiment : segon las donadas de l’examèn intèrne, l’interfàcia « %s » " +"Avertiment : segon las donadas de l'examèn intèrne, l'interfàcia « %s » " "existís pas\n" #: gio/gdbus-tool.c:531 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "Warning: According to introspection data, method '%s' does not exist on " +#| "interface '%s'\n" msgid "" "Warning: According to introspection data, method “%s” does not exist on " "interface “%s”\n" msgstr "" -"Avertiment : segon las donadas de l’examèn intèrne, lo metòde « %s » existís " -"pas sus l’interfàcia « %s »\n" +"Avertiment : segon las donadas de l'examèn intèrne, lo metòde « %s » existís " +"pas sus l'interfàcia « %s »\n" #: gio/gdbus-tool.c:593 msgid "Optional destination for signal (unique name)" @@ -1248,13 +1302,16 @@ msgid "Error: Object path is not specified\n" msgstr "Error : lo camin per l'objècte es pas precisat\n" #: gio/gdbus-tool.c:765 +#, fuzzy +#| msgid "Error: Method name is not specified\n" msgid "Error: Signal name is not specified\n" -msgstr "Error : lo nom del senhal es pas definit\n" +msgstr "Error : lo nom del metòde es pas definit\n" #: gio/gdbus-tool.c:779 -#, c-format +#, fuzzy, c-format +#| msgid "Error: Method name '%s' is invalid\n" msgid "Error: Signal name “%s” is invalid\n" -msgstr "Error : lo nom de senhal « %s » es pas valid\n" +msgstr "Error : lo nom de metòde « %s » es pas valid\n" #: gio/gdbus-tool.c:791 #, c-format @@ -1311,14 +1368,16 @@ msgid "Error: Method name is not specified\n" msgstr "Error : lo nom del metòde es pas definit\n" #: gio/gdbus-tool.c:1086 -#, c-format +#, fuzzy, c-format +#| msgid "Error: Method name '%s' is invalid\n" msgid "Error: Method name “%s” is invalid\n" msgstr "Error : lo nom de metòde « %s » es pas valid\n" #: gio/gdbus-tool.c:1164 -#, c-format +#, fuzzy, c-format +#| msgid "Error parsing parameter %d of type '%s': %s\n" msgid "Error parsing parameter %d of type “%s”: %s\n" -msgstr "Error d’analisi del paramètre %d de tipe « %s » : %s\n" +msgstr "Error d'analisi del paramètre %d de tipe « %s » : %s\n" #: gio/gdbus-tool.c:1190 #, c-format @@ -1384,12 +1443,16 @@ msgid "Wait for a bus name to appear." msgstr "" #: gio/gdbus-tool.c:2321 +#, fuzzy +#| msgid "Error: object path not specified.\n" msgid "Error: A service to activate for must be specified.\n" -msgstr "Error : un servici d'activar deu èsser indicat.\n" +msgstr "Error : lo camin per l'objècte es pas precisat.\n" #: gio/gdbus-tool.c:2326 +#, fuzzy +#| msgid "Error: object path not specified.\n" msgid "Error: A service to wait for must be specified.\n" -msgstr "Error : un servici d'esperar deu èsser indicat.\n" +msgstr "Error : lo camin per l'objècte es pas precisat.\n" #: gio/gdbus-tool.c:2331 #, fuzzy @@ -1398,9 +1461,10 @@ msgid "Error: Too many arguments.\n" msgstr "Tròp d'arguments" #: gio/gdbus-tool.c:2339 gio/gdbus-tool.c:2346 -#, c-format +#, fuzzy, c-format +#| msgid "Error: %s is not a valid bus name\n" msgid "Error: %s is not a valid well-known bus name.\n" -msgstr "Error : %s es pas un nom de bus plan conegut valid\n" +msgstr "Error : %s es pas un nom de bus valid\n" #: gio/gdesktopappinfo.c:2106 gio/gdesktopappinfo.c:4932 msgid "Unnamed" @@ -1419,14 +1483,16 @@ msgid "Unable to find terminal required for application" msgstr "Impossible de trobar lo terminal requesit per l'aplicacion" #: gio/gdesktopappinfo.c:3452 -#, c-format +#, fuzzy, c-format +#| msgid "Can't create user application configuration folder %s: %s" msgid "Can’t create user application configuration folder %s: %s" msgstr "" -"Impossible de crear lo dorsièr de configuracion utilizaire d’aplicacion %s : " +"Impossible de crear lo dorsièr de configuracion utilizaire d'aplicacion %s : " "%s" #: gio/gdesktopappinfo.c:3456 -#, c-format +#, fuzzy, c-format +#| msgid "Can't create user MIME configuration folder %s: %s" msgid "Can’t create user MIME configuration folder %s: %s" msgstr "" "Impossible de crear lo dorsièr de configuracion utilizaire MIME %s : %s" @@ -1436,7 +1502,8 @@ msgid "Application information lacks an identifier" msgstr "Las informacions de l'aplicacion compòrtan pas d'identificant" #: gio/gdesktopappinfo.c:3958 -#, c-format +#, fuzzy, c-format +#| msgid "Can't create user desktop file %s" msgid "Can’t create user desktop file %s" msgstr "Impossible de crear lo fichièr .desktop utilizaire %s" @@ -1446,6 +1513,8 @@ msgid "Custom definition for %s" msgstr "Definicion personnalisée per %s" #: gio/gdrive.c:417 +#, fuzzy +#| msgid "drive doesn't implement eject" msgid "drive doesn’t implement eject" msgstr "lo lector implementa pas l'ejeccion (« eject »)" @@ -1453,20 +1522,28 @@ msgstr "lo lector implementa pas l'ejeccion (« eject »)" #. * message for drive objects that #. * don't implement any of eject or eject_with_operation. #: gio/gdrive.c:495 +#, fuzzy +#| msgid "drive doesn't implement eject or eject_with_operation" msgid "drive doesn’t implement eject or eject_with_operation" msgstr "" "lo lector implementa pas l'ejeccion combinada o pas (« eject » o « " "eject_with_operation »)" #: gio/gdrive.c:571 +#, fuzzy +#| msgid "drive doesn't implement polling for media" msgid "drive doesn’t implement polling for media" msgstr "lo lector implementa pas l'escrutacion del mèdia (« polling »)" #: gio/gdrive.c:778 +#, fuzzy +#| msgid "drive doesn't implement start" msgid "drive doesn’t implement start" msgstr "lo lector implementa pas l'aviada (« start »)" #: gio/gdrive.c:880 +#, fuzzy +#| msgid "drive doesn't implement stop" msgid "drive doesn’t implement stop" msgstr "lo lector implementa pas l'arrèst (« stop »)" @@ -1518,20 +1595,26 @@ msgid "Containing mount does not exist" msgstr "Lo punt de montatge contenidor existís pas" #: gio/gfile.c:2608 gio/glocalfile.c:2472 +#, fuzzy +#| msgid "Can't copy over directory" msgid "Can’t copy over directory" -msgstr "Impossible d’espotir un repertòri" +msgstr "Impossible d'espotir un repertòri" #: gio/gfile.c:2668 +#, fuzzy +#| msgid "Can't copy directory over directory" msgid "Can’t copy directory over directory" -msgstr "Impossible d’espotir un repertòri per un autre repertòri" +msgstr "Impossible d'espotir un repertòri per un autre repertòri" #: gio/gfile.c:2676 msgid "Target file exists" msgstr "Lo fichièr cibla existís" #: gio/gfile.c:2695 +#, fuzzy +#| msgid "Can't recursively copy directory" msgid "Can’t recursively copy directory" -msgstr "Impossible de copiar recursivament un repertòri" +msgstr "Impossible de copier recursivament un repertòri" # http://en.wikipedia.org/wiki/Splice_(system_call) #: gio/gfile.c:2996 @@ -1558,6 +1641,8 @@ msgid "Copy (reflink/clone) is not supported or didn’t work" msgstr "La còpia (reflink/clone) es pas presa en carga o a pas foncionat" #: gio/gfile.c:3226 +#, fuzzy +#| msgid "Can't copy special file" msgid "Can’t copy special file" msgstr "Impossible de copiar lo fichièr especial" @@ -1565,7 +1650,7 @@ msgstr "Impossible de copiar lo fichièr especial" msgid "Invalid symlink value given" msgstr "Valor de ligam simbolic donada invalida" -#: gio/gfile.c:4045 glib/gfileutils.c:2362 +#: gio/gfile.c:4045 glib/gfileutils.c:2354 msgid "Symbolic links not supported" msgstr "Ligams simbolics pas preses en carga" @@ -1574,7 +1659,8 @@ msgid "Trash not supported" msgstr "L'escobilhièr es pas presa en carga" #: gio/gfile.c:4325 -#, c-format +#, fuzzy, c-format +#| msgid "File names cannot contain '%c'" msgid "File names cannot contain “%c”" msgstr "Los noms de fichièrs pòdon pas comportar de « %c »" @@ -1602,7 +1688,8 @@ msgid "File enumerator is already closed" msgstr "L'enumerador de fichièrs es ja tampat" #: gio/gfileicon.c:250 -#, c-format +#, fuzzy, c-format +#| msgid "Can't handle version %d of GFileIcon encoding" msgid "Can’t handle version %d of GFileIcon encoding" msgstr "Impossible de gerir la version %d de l'encodatge de GFileIcon" @@ -1613,6 +1700,8 @@ msgstr "Donadas d'entrada incorrèctas per GFileIcon" #: gio/gfileinputstream.c:149 gio/gfileinputstream.c:394 #: gio/gfileiostream.c:167 gio/gfileoutputstream.c:164 #: gio/gfileoutputstream.c:497 +#, fuzzy +#| msgid "Stream doesn't support query_info" msgid "Stream doesn’t support query_info" msgstr "Lo flux pren pas en carga query_info" @@ -1716,9 +1805,10 @@ msgid "Address has bits set beyond prefix length" msgstr "L'adreça possedís de bits definits al delà de la longor del prefix" #: gio/ginetaddressmask.c:300 -#, c-format +#, fuzzy, c-format +#| msgid "Could not parse '%s' as IP address mask" msgid "Could not parse “%s” as IP address mask" -msgstr "Impossible d’analisar « %s » coma masqueta d’adreça IP" +msgstr "Impossible d'analisar « %s » coma masque d'adreça IP" #: gio/ginetsocketaddress.c:203 gio/ginetsocketaddress.c:220 #: gio/gnativesocketaddress.c:109 gio/gunixsocketaddress.c:220 @@ -1754,8 +1844,10 @@ msgid "Keep with file when moved" msgstr "Conservar amb lo fichièr al moment del desplaçament" #: gio/gio-tool.c:205 +#, fuzzy +#| msgid "'version' takes no arguments" msgid "“version” takes no arguments" -msgstr "« version » accèpta pas cap de paramètre" +msgstr "« %s » accèpta pas cap de paramètre" #: gio/gio-tool.c:207 gio/gio-tool.c:223 glib/goption.c:869 msgid "Usage:" @@ -1782,8 +1874,12 @@ msgid "Show information about locations" msgstr "Afichar l'informacion sus las localizacions" #: gio/gio-tool.c:232 +#, fuzzy +#| msgid "List static actions for an application (from .desktop file)" msgid "Launch an application from a desktop file" -msgstr "Aviar una aplicacion a partir d’un fichièr desktop" +msgstr "" +"Afichar la lista de las accions estaticas d'una aplicacion (a partir del " +"fichièr .desktop)" #: gio/gio-tool.c:233 msgid "List the contents of locations" @@ -1843,8 +1939,10 @@ msgid "Use %s to get detailed help.\n" msgstr "Utilizatz « %s » per obténer d'ajuda detalhada.\n" #: gio/gio-tool-cat.c:87 +#, fuzzy +#| msgid "Error writing to file: %s" msgid "Error writing to stdout" -msgstr "Error al moment de l’escritura cap a stdout" +msgstr "Error al moment de l'escritura del fichièr : %s" #. Translators: commandline placeholder #: gio/gio-tool-cat.c:133 gio/gio-tool-info.c:340 gio/gio-tool-list.c:172 @@ -2027,6 +2125,13 @@ msgid "Show information about locations." msgstr "Afichar d'informacions a prepaus dels emplaçaments." #: gio/gio-tool-info.c:347 +#, fuzzy +#| msgid "" +#| "gio info is similar to the traditional ls utility, but using GIO\n" +#| "locations instead of local files: for example, you can use something\n" +#| "like smb://server/resource/file.txt as location. File attributes can\n" +#| "be specified with their GIO name, e.g. standard::icon, or just by\n" +#| "namespace, e.g. unix, or by '*', which matches all attributes" msgid "" "gio info is similar to the traditional ls utility, but using GIO\n" "locations instead of local files: for example, you can use something\n" @@ -2034,7 +2139,7 @@ msgid "" "be specified with their GIO name, e.g. standard::icon, or just by\n" "namespace, e.g. unix, or by “*”, which matches all attributes" msgstr "" -"gio info fonciona coma l’utilitari tradicional ls, mas en\n" +"gio info fonciona coma l'utilitari tradicional ls, mas en\n" "utilizant d'emplaçaments GIO al luòc de fichièrs locals : per exemple,\n" "se pòt indicar un emplaçament coma smb://servidor/ressorsa/fichièr.txt.\n" "Los atributs de fichièrs pòdon èsser indicats per lor nom GIO (exemple :\n" @@ -2054,7 +2159,7 @@ msgstr "" #: gio/gio-tool-launch.c:77 msgid "No desktop file given" -msgstr "Cap de fichièr de burèu pas indicat" +msgstr "Cap de fichièr pas indicat" #: gio/gio-tool-launch.c:85 #, fuzzy @@ -2086,8 +2191,10 @@ msgid "Use a long listing format" msgstr "Utilizar una mesa en forma de lista espandida" #: gio/gio-tool-list.c:40 +#, fuzzy +#| msgid "display name: %s\n" msgid "Print display names" -msgstr "Afichar los noms d’afichatge" +msgstr "nom d'afichatge : %s\n" #: gio/gio-tool-list.c:41 msgid "Print full URIs" @@ -2138,12 +2245,14 @@ msgid "Must specify a single mimetype, and maybe a handler" msgstr "Un seul tipe MIME deu èsser indicat, e potencialament un gestionari" #: gio/gio-tool-mime.c:116 -#, c-format +#, fuzzy, c-format +#| msgid "No default applications for '%s'\n" msgid "No default applications for “%s”\n" -msgstr "Pas cap d'aplicacion per defaut per « %s »\n" +msgstr "Pas d'aplicacions per defaut per « %s »\n" #: gio/gio-tool-mime.c:122 -#, c-format +#, fuzzy, c-format +#| msgid "Default application for '%s': %s\n" msgid "Default application for “%s”: %s\n" msgstr "Aplicacion per defaut per « %s » : %s\n" @@ -2296,16 +2405,19 @@ msgid "The numeric PIM when unlocking a VeraCrypt volume" msgstr "" #: gio/gio-tool-mount.c:75 +#, fuzzy +#| msgctxt "GDateTime" +#| msgid "PM" msgid "PIM" -msgstr "PIM" +msgstr "PM" #: gio/gio-tool-mount.c:76 msgid "Mount a TCRYPT hidden volume" -msgstr "" +msgstr "Montar un volume amagat TCRYPT" #: gio/gio-tool-mount.c:77 msgid "Mount a TCRYPT system volume" -msgstr "" +msgstr "Montar un volume sistèma TCRYPT" #: gio/gio-tool-mount.c:265 gio/gio-tool-mount.c:297 msgid "Anonymous access denied" @@ -2421,8 +2533,10 @@ msgid "ETAG" msgstr "ETAG" #: gio/gio-tool-save.c:113 +#, fuzzy +#| msgid "Error reading from handle: %s" msgid "Error reading from standard input" -msgstr "Error de lectura a partir de l’entrada estandarda" +msgstr "Error de lectura a partir de l'identificador : %s" #. Translators: The "etag" is a token allowing to verify whether a file has been modified #: gio/gio-tool-save.c:139 @@ -2562,7 +2676,8 @@ msgid "Failed to locate “%s” in current directory" msgstr "La localizacion de « %s » dins lo repertòri actual a fracassat" #: gio/glib-compile-resources.c:290 -#, c-format +#, fuzzy, c-format +#| msgid "Unknown processing option \"%s\"" msgid "Unknown processing option “%s”" msgstr "Opcion de tractament desconeguda « %s »" @@ -2596,10 +2711,16 @@ msgid "Show program version and exit" msgstr "" #: gio/glib-compile-resources.c:738 +#, fuzzy +#| msgid "name of the output file" msgid "Name of the output file" -msgstr "Nom del fichièr de sortida" +msgstr "nom del fichièr de sortida" #: gio/glib-compile-resources.c:739 +#, fuzzy +#| msgid "" +#| "The directories where files are to be read from (default to current " +#| "directory)" msgid "" "The directories to load files referenced in FILE from (default: current " "directory)" @@ -2636,18 +2757,24 @@ msgid "Generate dependency list" msgstr "Generar la lista de las dependéncias" #: gio/glib-compile-resources.c:744 +#, fuzzy +#| msgid "name of the dependency file to generate" msgid "Name of the dependency file to generate" -msgstr "Nom del fichièr de dependéncias de generar" +msgstr "nom del fichièr de las dependéncias de generar" #: gio/glib-compile-resources.c:745 msgid "Include phony targets in the generated dependency file" msgstr "" #: gio/glib-compile-resources.c:746 +#, fuzzy +#| msgid "Don't automatically create and register resource" msgid "Don’t automatically create and register resource" msgstr "Crear pas e enregistrar automaticament la ressorsa" #: gio/glib-compile-resources.c:747 +#, fuzzy +#| msgid "Don't export functions; declare them G_GNUC_INTERNAL" msgid "Don’t export functions; declare them G_GNUC_INTERNAL" msgstr "Exportar pas las foncions ; las declarar G_GNUC_INTERNAL" @@ -2682,19 +2809,22 @@ msgid "nick must be a minimum of 2 characters" msgstr "" #: gio/glib-compile-schemas.c:103 -#, c-format +#, fuzzy, c-format +#| msgid "Invalid symlink value given" msgid "Invalid numeric value" -msgstr "Valor numeric invalida" +msgstr "Valor de ligam simbolic donada invalida" #: gio/glib-compile-schemas.c:111 -#, c-format +#, fuzzy, c-format +#| msgid "<%s id='%s'> already specified" msgid "<value nick='%s'/> already specified" -msgstr "<value nick='%s'/>'> es ja definit" +msgstr "<%s id='%s'> es ja definit" #: gio/glib-compile-schemas.c:119 -#, c-format +#, fuzzy, c-format +#| msgid "<key name='%s'> already specified" msgid "value='%s' already specified" -msgstr "value='%s' es ja estat definit" +msgstr "<key name='%s'> a ja été definit" #: gio/glib-compile-schemas.c:133 #, c-format @@ -2707,9 +2837,10 @@ msgid "<%s> must contain at least one <value>" msgstr "" #: gio/glib-compile-schemas.c:314 -#, c-format +#, fuzzy, c-format +#| msgid "No connection endpoint specified" msgid "<%s> is not contained in the specified range" -msgstr "<%s> es pas contengut dins l’interval definit" +msgstr "Cap de punt terminal de connexion pas definit" #: gio/glib-compile-schemas.c:326 #, c-format @@ -2727,8 +2858,10 @@ msgid "<%s> contains a string not in <choices>" msgstr "" #: gio/glib-compile-schemas.c:372 +#, fuzzy +#| msgid "<key name='%s'> already specified" msgid "<range/> already specified for this key" -msgstr "<range/> es ja estat definit per aquesta clau" +msgstr "<key name='%s'> a ja été definit" #: gio/glib-compile-schemas.c:390 #, c-format @@ -2767,8 +2900,10 @@ msgid "" msgstr "" #: gio/glib-compile-schemas.c:500 +#, fuzzy +#| msgid "<child name='%s'> already specified" msgid "<choices> already specified for this key" -msgstr "<choices> es ja estat definit per aquesta clau" +msgstr "<child name='%s'> es ja estat definit" #: gio/glib-compile-schemas.c:512 #, c-format @@ -2776,9 +2911,10 @@ msgid "<choices> not allowed for keys of type “%s”" msgstr "" #: gio/glib-compile-schemas.c:528 -#, c-format +#, fuzzy, c-format +#| msgid "<child name='%s'> already specified" msgid "<choice value='%s'/> already given" -msgstr "<choice value='%s'> es ja estat definit" +msgstr "<child name='%s'> es ja estat definit" #: gio/glib-compile-schemas.c:543 #, c-format @@ -2786,8 +2922,10 @@ msgid "<choices> must contain at least one <choice>" msgstr "" #: gio/glib-compile-schemas.c:557 +#, fuzzy +#| msgid "<child name='%s'> already specified" msgid "<aliases> already specified for this key" -msgstr "<aliases> es ja estat definit per aquesta clau" +msgstr "<child name='%s'> es ja estat definit" #: gio/glib-compile-schemas.c:561 msgid "" @@ -2808,9 +2946,10 @@ msgid "<alias value='%s'/> given when <choice value='%s'/> was already given" msgstr "" #: gio/glib-compile-schemas.c:594 -#, c-format +#, fuzzy, c-format +#| msgid "<%s id='%s'> already specified" msgid "<alias value='%s'/> already specified" -msgstr "<alias value='%s'/> es ja definit" +msgstr "<%s id='%s'> es ja definit" #: gio/glib-compile-schemas.c:604 #, c-format @@ -2828,39 +2967,48 @@ msgid "<aliases> must contain at least one <alias>" msgstr "" #: gio/glib-compile-schemas.c:797 +#, fuzzy +#| msgid "empty names are not permitted" msgid "Empty names are not permitted" -msgstr "Los noms voids son pas autorizats" +msgstr "los noms voids son pas autorizats" #: gio/glib-compile-schemas.c:807 -#, c-format +#, fuzzy, c-format +#| msgid "invalid name '%s': names must begin with a lowercase letter" msgid "Invalid name “%s”: names must begin with a lowercase letter" -msgstr "Nom « %s » invalid : los noms devon començar per una letra minuscula" +msgstr "nom « %s » invalid : los noms devon començar per una letra minuscula" #: gio/glib-compile-schemas.c:819 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "invalid name '%s': invalid character '%c'; only lowercase letters, " +#| "numbers and hyphen ('-') are permitted." msgid "" "Invalid name “%s”: invalid character “%c”; only lowercase letters, numbers " "and hyphen (“-”) are permitted" msgstr "" "nom « %s » invalid : caractèr « %c » invalid ; sols las minusculas, los " -"nombres e lo jonhent (« - ») son autorizats" +"nombres e lo jonhent (« - ») son autorizats." #: gio/glib-compile-schemas.c:828 -#, c-format +#, fuzzy, c-format +#| msgid "invalid name '%s': two successive hyphens ('--') are not permitted." msgid "Invalid name “%s”: two successive hyphens (“--”) are not permitted" msgstr "" -"nom « %s » invalid : dos jonhents successius (« -- ») son pas autorizats" +"nom « %s » invalid : dos jonhents successius (« -- ») son pas autorizats." #: gio/glib-compile-schemas.c:837 -#, c-format +#, fuzzy, c-format +#| msgid "invalid name '%s': the last character may not be a hyphen ('-')." msgid "Invalid name “%s”: the last character may not be a hyphen (“-”)" msgstr "" -"Nom « %s » invalid : lo darrièr caractèr pòt pas èsser un jonhent (« - »)" +"nom « %s » invalid : lo darrièr caractèr pòt pas èsser un jonhent (« - »)." #: gio/glib-compile-schemas.c:845 -#, c-format +#, fuzzy, c-format +#| msgid "invalid name '%s': maximum length is 1024" msgid "Invalid name “%s”: maximum length is 1024" -msgstr "Nom « %s » invalid : la longor maximala es 1024" +msgstr "nom « %s » invalid : la longor maximala es 1024" #: gio/glib-compile-schemas.c:917 #, c-format @@ -2886,12 +3034,15 @@ msgstr "" "<override> per modificar la valor" #: gio/glib-compile-schemas.c:983 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "exactly one of 'type', 'enum' or 'flags' must be specified as an " +#| "attribute to <key>" msgid "" "Exactly one of “type”, “enum” or “flags” must be specified as an attribute " "to <key>" msgstr "" -"<key> pòt pas recebre qu’un e un sol atribut demest « type », « enum » o « " +"<key> pòt pas recebre qu'un e un sol atribut demest « tipe », « enum » o « " "flags »" #: gio/glib-compile-schemas.c:1002 @@ -2900,9 +3051,10 @@ msgid "<%s id='%s'> not (yet) defined." msgstr "<%s id='%s'> pas (encara) definit." #: gio/glib-compile-schemas.c:1017 -#, c-format +#, fuzzy, c-format +#| msgid "invalid GVariant type string '%s'" msgid "Invalid GVariant type string “%s”" -msgstr "Cadena de tipe GVariant « %s » invalida" +msgstr "cadena de tipe GVariant « %s » invalida" #: gio/glib-compile-schemas.c:1047 #, fuzzy @@ -2911,9 +3063,10 @@ msgid "<override> given but schema isn’t extending anything" msgstr "un <override> es donat mas son esquèma espandís pas res" #: gio/glib-compile-schemas.c:1060 -#, c-format +#, fuzzy, c-format +#| msgid "no <key name='%s'> to override" msgid "No <key name='%s'> to override" -msgstr "Pas cap de <key name='%s'> de remplaçar" +msgstr "pas cap de <key name='%s'> de redefinir" #: gio/glib-compile-schemas.c:1068 #, c-format @@ -2926,12 +3079,14 @@ msgid "<schema id='%s'> already specified" msgstr "<schema id='%s'> ja definit" #: gio/glib-compile-schemas.c:1153 -#, c-format +#, fuzzy, c-format +#| msgid "<schema id='%s'> extends not yet existing schema '%s'" msgid "<schema id='%s'> extends not yet existing schema “%s”" msgstr "<schema id='%s'> espandís l'esquèma « %s » qu'existís pas encara" #: gio/glib-compile-schemas.c:1169 -#, c-format +#, fuzzy, c-format +#| msgid "<schema id='%s'> is list of not yet existing schema '%s'" msgid "<schema id='%s'> is list of not yet existing schema “%s”" msgstr "" "<schema id='%s'> es una lista de l'esquèma « %s » qu'existís pas encara" @@ -2943,9 +3098,10 @@ msgid "Cannot be a list of a schema with a path" msgstr "Un esquèma amb un camin pòt pas conténer de lista" #: gio/glib-compile-schemas.c:1187 -#, c-format +#, fuzzy, c-format +#| msgid "Can not extend a schema with a path" msgid "Cannot extend a schema with a path" -msgstr "Impossible d’espandir un esquèma amb un camin" +msgstr "Impossible d'espandir un esquèma amb un camin" #: gio/glib-compile-schemas.c:1197 #, c-format @@ -2955,13 +3111,16 @@ msgstr "" "<schema id='%s'> es una lista ; espandís <schema id='%s'> qu'es pas una lista" #: gio/glib-compile-schemas.c:1207 -#, c-format +#, fuzzy, c-format +#| msgid "" +#| "<schema id='%s' list-of='%s'> extends <schema id='%s' list-of='%s'> but " +#| "'%s' does not extend '%s'" msgid "" "<schema id='%s' list-of='%s'> extends <schema id='%s' list-of='%s'> but “%s” " "does not extend “%s”" msgstr "" "<schema id='%s' list-of='%s'> espandís <schema id='%s' list-of='%s'> mas « " -"%s » espandís pas « %s »" +"%s » n'étend pas « %s »" #: gio/glib-compile-schemas.c:1224 #, fuzzy, c-format @@ -3002,9 +3161,10 @@ msgid "Element <default> is required in <key>" msgstr "" #: gio/glib-compile-schemas.c:1626 -#, c-format +#, fuzzy, c-format +#| msgid "text may not appear inside <%s>" msgid "Text may not appear inside <%s>" -msgstr "Es possible que lo tèxte aparesca pas a l'interior de <%s>" +msgstr "<%s> pòt pas conténer de tèxte" #: gio/glib-compile-schemas.c:1694 #, c-format @@ -3135,8 +3295,10 @@ msgstr "" "redefinicion « %s » es pas dins la lista de las causida validas" #: gio/glib-compile-schemas.c:2173 +#, fuzzy +#| msgid "where to store the gschemas.compiled file" msgid "Where to store the gschemas.compiled file" -msgstr "Lòc ont enregistrar lo fichièr gschemas.compiled" +msgstr "endreit ont enregistrar lo fichièr gschemas.compiled" #: gio/glib-compile-schemas.c:2174 msgid "Abort on any errors in schemas" @@ -3161,8 +3323,10 @@ msgstr "" "e lo fichièr cache es nomenat gschemas.compiled." #: gio/glib-compile-schemas.c:2226 +#, fuzzy +#| msgid "You should give exactly one directory name\n" msgid "You should give exactly one directory name" -msgstr "Devètz indicar exactament un nom de repertòri" +msgstr "Vos cal indicar un e un sol nom de repertòri\n" #: gio/glib-compile-schemas.c:2269 #, fuzzy @@ -3171,10 +3335,8 @@ msgid "No schema files found: doing nothing." msgstr "Cap de fichièr esquèma pas trobat : " #: gio/glib-compile-schemas.c:2271 -#, fuzzy -#| msgid "removed existing output file.\n" msgid "No schema files found: removed existing output file." -msgstr "fichièr de sortida existent suprimit.\n" +msgstr "" #: gio/glocalfile.c:549 gio/win32/gwinhttpfile.c:436 #, c-format @@ -3197,6 +3359,8 @@ msgid "Containing mount for file %s not found" msgstr "Lo punt de montatge contenidor pel fichièr %s es introbable" #: gio/glocalfile.c:1144 +#, fuzzy +#| msgid "Can't rename root directory" msgid "Can’t rename root directory" msgstr "Impossible de renomenar lo repertòri raiç" @@ -3206,8 +3370,10 @@ msgid "Error renaming file %s: %s" msgstr "Error de renomenatge del fichièr %s : %s" #: gio/glocalfile.c:1169 +#, fuzzy +#| msgid "Can't rename file, filename already exists" msgid "Can’t rename file, filename already exists" -msgstr "Impossible de renomenar lo fichièr, lo nom de fichièr existís ja" +msgstr "Impossible de renomenar lo fichièr perque aqueste nom es ja utilizat" #: gio/glocalfile.c:1182 gio/glocalfile.c:2366 gio/glocalfile.c:2394 #: gio/glocalfile.c:2533 gio/glocalfileoutputstream.c:656 @@ -3297,12 +3463,14 @@ msgid "Error moving file %s: %s" msgstr "Error al moment del desplaçament del fichièr %s : %s" #: gio/glocalfile.c:2467 +#, fuzzy +#| msgid "Can't move directory over directory" msgid "Can’t move directory over directory" msgstr "Impossible de desplaçar un repertòri per dessús un autre" -#: gio/glocalfile.c:2493 gio/glocalfileoutputstream.c:1108 -#: gio/glocalfileoutputstream.c:1122 gio/glocalfileoutputstream.c:1137 -#: gio/glocalfileoutputstream.c:1154 gio/glocalfileoutputstream.c:1168 +#: gio/glocalfile.c:2493 gio/glocalfileoutputstream.c:1079 +#: gio/glocalfileoutputstream.c:1093 gio/glocalfileoutputstream.c:1108 +#: gio/glocalfileoutputstream.c:1125 gio/glocalfileoutputstream.c:1139 msgid "Backup file creation failed" msgstr "La creacion del fichièr de salvament a fracassat" @@ -3333,20 +3501,21 @@ msgid "Invalid extended attribute name" msgstr "Nom d'atribut espandit invalid" #: gio/glocalfileinfo.c:821 -#, c-format +#, fuzzy, c-format +#| msgid "Error setting extended attribute '%s': %s" msgid "Error setting extended attribute “%s”: %s" -msgstr "Error al moment de la definicion de l’atribut espandit « %s » : %s" +msgstr "Error al moment de la definicion de l'atribut espandit « %s » : %s" #: gio/glocalfileinfo.c:1709 gio/win32/gwinhttpfile.c:191 msgid " (invalid encoding)" msgstr " (encodatge invalid)" #: gio/glocalfileinfo.c:1868 gio/glocalfileoutputstream.c:943 -#: gio/glocalfileoutputstream.c:995 -#, c-format +#, fuzzy, c-format +#| msgid "Error when getting information for file '%s': %s" msgid "Error when getting information for file “%s”: %s" msgstr "" -"Error al moment de l’obtencion de las informacions del fichièr « %s » : %s" +"Error al moment de l'obtencion de las informacions del fichièr « %s » : %s" #: gio/glocalfileinfo.c:2134 #, c-format @@ -3428,11 +3597,11 @@ msgid "File “%s” cannot be opened: Windows Error %lu" msgstr "" #: gio/glocalfileinfo.c:2589 -#, c-format +#, fuzzy, c-format +#| msgid "Error setting modification or access time: %s" msgid "Error setting modification or access time for file “%s”: %lu" msgstr "" -"Error al moment de la definicion de l'ora de modificacion o d'accès pel " -"fichièr « %s » : %lu" +"Error al moment de la definicion de l'ora de modificacion o d'accès : %s" #: gio/glocalfileinfo.c:2690 #, c-format @@ -3470,7 +3639,7 @@ msgid "Error closing file: %s" msgstr "Error al moment de la tampadura del fichièr : %s" #: gio/glocalfileinputstream.c:272 gio/glocalfileoutputstream.c:563 -#: gio/glocalfileoutputstream.c:1186 +#: gio/glocalfileoutputstream.c:1157 #, c-format msgid "Error seeking in file: %s" msgstr "Error de posicionament dins lo fichièr : %s" @@ -3500,13 +3669,13 @@ msgstr "Error al moment de la creacion de la còpia de salvament : %s" msgid "Error renaming temporary file: %s" msgstr "Error al moment del cambiament de nom del fichièr temporari : %s" -#: gio/glocalfileoutputstream.c:609 gio/glocalfileoutputstream.c:1237 +#: gio/glocalfileoutputstream.c:609 gio/glocalfileoutputstream.c:1208 #, c-format msgid "Error truncating file: %s" msgstr "Error al moment de la troncadura del fichièr : %s" #: gio/glocalfileoutputstream.c:662 gio/glocalfileoutputstream.c:907 -#: gio/glocalfileoutputstream.c:1218 gio/gsubprocess.c:226 +#: gio/glocalfileoutputstream.c:1189 gio/gsubprocess.c:226 #, c-format msgid "Error opening file “%s”: %s" msgstr "Error al moment de la dobertura del fichièr « %s » : %s" @@ -3519,11 +3688,11 @@ msgstr "Lo fichièr cibla es un repertòri" msgid "Target file is not a regular file" msgstr "Lo fichièr cibla es pas un fichièr estandard" -#: gio/glocalfileoutputstream.c:1013 +#: gio/glocalfileoutputstream.c:984 msgid "The file was externally modified" msgstr "Lo fichièr es estat modificat exteriorament" -#: gio/glocalfileoutputstream.c:1202 +#: gio/glocalfileoutputstream.c:1173 #, c-format msgid "Error removing old file: %s" msgstr "Error a la supression de l'ancian fichièr : %s" @@ -3568,6 +3737,8 @@ msgstr "Posicionament demandat aprèp la fin del flux" #. * message for mount objects that #. * don't implement unmount. #: gio/gmount.c:399 +#, fuzzy +#| msgid "mount doesn't implement \"unmount\"" msgid "mount doesn’t implement “unmount”" msgstr "mount implementa pas lo desmontatge (« unmount »)" @@ -3656,10 +3827,9 @@ msgid "Could not get network status: " msgstr "Impossible d'obténer l'estatut de la ret : " #: gio/gnetworkmonitornm.c:348 -#, fuzzy, c-format -#| msgid "NetworkManager version too old" +#, c-format msgid "NetworkManager not running" -msgstr "La version de NetworkManager es tròp anciana" +msgstr "NetworkManager es pas aviat" #: gio/gnetworkmonitornm.c:359 #, c-format @@ -3688,13 +3858,16 @@ msgstr "Error de resolucion de « %s » : %s" #. Translators: The placeholder is for a function name. #: gio/gresolver.c:455 gio/gresolver.c:615 -#, c-format +#, fuzzy, c-format +#| msgid "Input stream doesn't implement read" msgid "%s not implemented" -msgstr "%s es pas implementat" +msgstr "Lo flux en entrada implementa pas « read »" #: gio/gresolver.c:984 gio/gresolver.c:1036 +#, fuzzy +#| msgid "Invalid filename" msgid "Invalid domain" -msgstr "Domeni invalid" +msgstr "Nom de fichièr invalid" #: gio/gresource.c:681 gio/gresource.c:943 gio/gresource.c:983 #: gio/gresource.c:1107 gio/gresource.c:1179 gio/gresource.c:1253 @@ -3718,6 +3891,8 @@ msgid "The resource at “%s” is not a directory" msgstr "La ressorsa dins « %s » es pas un repertòri" #: gio/gresourcefile.c:940 +#, fuzzy +#| msgid "Input stream doesn't implement seek" msgid "Input stream doesn’t implement seek" msgstr "Lo flux en entrada implementa pas « seek » (lo posicionament)" @@ -3858,8 +4033,7 @@ msgid " PATH A resource path\n" msgstr " CAMIN Un camin de ressorsa\n" #: gio/gsettings-tool.c:49 gio/gsettings-tool.c:70 gio/gsettings-tool.c:906 -#, fuzzy, c-format -#| msgid "No such schema '%s'\n" +#, c-format msgid "No such schema “%s”\n" msgstr "L'esquèma « %s » existís pas\n" @@ -4107,8 +4281,7 @@ msgid "Empty schema name given\n" msgstr "Nom d'esquèma provesit void\n" #: gio/gsettings-tool.c:919 -#, fuzzy, c-format -#| msgid "No such key '%s'\n" +#, c-format msgid "No such key “%s”\n" msgstr "La clau « %s » existís pas\n" @@ -4198,12 +4371,14 @@ msgid "No support for source-specific multicast" msgstr "Pas cap de presa en carga pel multicast especific a la font" #: gio/gsocket.c:2534 +#, fuzzy +#| msgid "Unsupported socket address" msgid "Unsupported socket family" -msgstr "Familha de connector ret pas presa en carga" +msgstr "Adreça de connector ret pas presa en carga" #: gio/gsocket.c:2559 msgid "source-specific not an IPv4 address" -msgstr "source-specific es pas una adreça IPv4" +msgstr "" #: gio/gsocket.c:2583 #, c-format @@ -4265,36 +4440,36 @@ msgstr "Error al moment de la tampadura del connector : %s" msgid "Waiting for socket condition: %s" msgstr "En espèra de l'estat del connector : %s" -#: gio/gsocket.c:4806 gio/gsocket.c:4824 gio/gsocket.c:4837 +#: gio/gsocket.c:4804 gio/gsocket.c:4820 gio/gsocket.c:4833 #, c-format msgid "Unable to send message: %s" msgstr "Impossible d'enviar lo messatge : %s" -#: gio/gsocket.c:4807 gio/gsocket.c:4825 gio/gsocket.c:4838 +#: gio/gsocket.c:4805 gio/gsocket.c:4821 gio/gsocket.c:4834 msgid "Message vectors too large" msgstr "" -#: gio/gsocket.c:4854 gio/gsocket.c:4856 gio/gsocket.c:5003 gio/gsocket.c:5088 -#: gio/gsocket.c:5266 gio/gsocket.c:5306 gio/gsocket.c:5308 +#: gio/gsocket.c:4850 gio/gsocket.c:4852 gio/gsocket.c:4999 gio/gsocket.c:5084 +#: gio/gsocket.c:5262 gio/gsocket.c:5302 gio/gsocket.c:5304 #, c-format msgid "Error sending message: %s" msgstr "Error de mandadís de messatge : %s" -#: gio/gsocket.c:5030 +#: gio/gsocket.c:5026 msgid "GSocketControlMessage not supported on Windows" msgstr "GSocketControlMessage es pas pres en carga per Windows" -#: gio/gsocket.c:5499 gio/gsocket.c:5575 gio/gsocket.c:5801 +#: gio/gsocket.c:5495 gio/gsocket.c:5571 gio/gsocket.c:5797 #, c-format msgid "Error receiving message: %s" msgstr "Error al moment de la recepcion del messatge : %s" -#: gio/gsocket.c:6074 gio/gsocket.c:6085 gio/gsocket.c:6131 +#: gio/gsocket.c:6070 gio/gsocket.c:6081 gio/gsocket.c:6127 #, c-format msgid "Unable to read socket credentials: %s" msgstr "Impossible de legir las donadas d'autentificacion del connector : %s" -#: gio/gsocket.c:6140 +#: gio/gsocket.c:6136 msgid "g_socket_get_credentials not implemented for this OS" msgstr "" "g_socket_get_credentials es pas implementat sus aqueste sistèma operatiu" @@ -4438,15 +4613,17 @@ msgid "No valid addresses were found" msgstr "Cap d'adreça valida es pas estada trobada" #: gio/gthreadedresolver.c:337 -#, c-format +#, fuzzy, c-format +#| msgid "Error reverse-resolving '%s': %s" msgid "Error reverse-resolving “%s”: %s" msgstr "Error de resolucion invèrsa de « %s » : %s" #: gio/gthreadedresolver.c:676 gio/gthreadedresolver.c:755 #: gio/gthreadedresolver.c:853 gio/gthreadedresolver.c:903 -#, c-format +#, fuzzy, c-format +#| msgid "No DNS record of the requested type for '%s'" msgid "No DNS record of the requested type for “%s”" -msgstr "Pas cap d'enregistrament DNS del tipe demandat per « %s »" +msgstr "Cap d'enregistrament DNS del tipe pas demandat per « %s »" #: gio/gthreadedresolver.c:681 gio/gthreadedresolver.c:858 #, fuzzy, c-format @@ -4460,27 +4637,27 @@ msgstr "Impossible temporàriament de resòlvre « %s »" msgid "Error resolving “%s”" msgstr "Error de resolucion de « %s »" -#: gio/gtlscertificate.c:299 +#: gio/gtlscertificate.c:298 msgid "No PEM-encoded private key found" msgstr "Cap de clau privada pas encodada PEM trobada" -#: gio/gtlscertificate.c:309 +#: gio/gtlscertificate.c:308 msgid "Cannot decrypt PEM-encoded private key" msgstr "Impossible de deschifrar la clau privada encodada-PEM" -#: gio/gtlscertificate.c:320 +#: gio/gtlscertificate.c:319 msgid "Could not parse PEM-encoded private key" msgstr "Impossible d'analisar la clau privada encodada-PEM" -#: gio/gtlscertificate.c:347 +#: gio/gtlscertificate.c:346 msgid "No PEM-encoded certificate found" msgstr "Cap de certificat encodat-PEM pas trobat" -#: gio/gtlscertificate.c:356 +#: gio/gtlscertificate.c:355 msgid "Could not parse PEM-encoded certificate" msgstr "Impossible d'analisar lo certificat encodat-PEM" -#: gio/gtlscertificate.c:711 +#: gio/gtlscertificate.c:710 msgid "This GTlsBackend does not support creating PKCS #11 certificates" msgstr "" @@ -4666,9 +4843,10 @@ msgid "Wrong args\n" msgstr "Arguments incorrèctes\n" #: glib/gbookmarkfile.c:768 -#, c-format +#, fuzzy, c-format +#| msgid "Unexpected attribute '%s' for element '%s'" msgid "Unexpected attribute “%s” for element “%s”" -msgstr "Atribut « %s » inesperat per l’element « %s »" +msgstr "Atribut « %s » inesperat per l'element « %s »" #: glib/gbookmarkfile.c:779 glib/gbookmarkfile.c:859 glib/gbookmarkfile.c:869 #: glib/gbookmarkfile.c:982 @@ -4679,15 +4857,17 @@ msgstr "L'atribut « %s » de l'element « %s » es introbable" #: glib/gbookmarkfile.c:1191 glib/gbookmarkfile.c:1256 #: glib/gbookmarkfile.c:1320 glib/gbookmarkfile.c:1330 -#, c-format +#, fuzzy, c-format +#| msgid "Unexpected tag '%s', tag '%s' expected" msgid "Unexpected tag “%s”, tag “%s” expected" msgstr "Balisa « %s » inesperada. La balisa « %s » èra esperada" #: glib/gbookmarkfile.c:1216 glib/gbookmarkfile.c:1230 #: glib/gbookmarkfile.c:1298 glib/gbookmarkfile.c:1344 -#, c-format +#, fuzzy, c-format +#| msgid "Unexpected tag '%s' inside '%s'" msgid "Unexpected tag “%s” inside “%s”" -msgstr "Balisa « %s » inesperada a l’interior de « %s »" +msgstr "Balisa « %s » inesperada a l'interior de « %s »" #: glib/gbookmarkfile.c:1624 #, c-format @@ -4720,19 +4900,22 @@ msgid "No bookmark found for URI “%s”" msgstr "Cap de signet pas trobat per l'URI « %s »" #: glib/gbookmarkfile.c:2409 -#, c-format +#, fuzzy, c-format +#| msgid "No MIME type defined in the bookmark for URI '%s'" msgid "No MIME type defined in the bookmark for URI “%s”" -msgstr "Cap de tipe MIME pas definit dins lo signet per l’URI « %s »" +msgstr "Cap de tipe MIME pas definit dins lo signet per l'URI « %s »" #: glib/gbookmarkfile.c:2494 -#, c-format +#, fuzzy, c-format +#| msgid "No private flag has been defined in bookmark for URI '%s'" msgid "No private flag has been defined in bookmark for URI “%s”" -msgstr "Cap d'indicator privat es pas definit dins lo signet per l’URI « %s »" +msgstr "Cap d'indicator privat es pas definit dins lo signet per l'URI « %s »" #: glib/gbookmarkfile.c:3035 -#, c-format +#, fuzzy, c-format +#| msgid "No groups set in bookmark for URI '%s'" msgid "No groups set in bookmark for URI “%s”" -msgstr "Cap de grop es pas definit dins lo signet per l’URI « %s »" +msgstr "Cap de grop es pas definit dins lo signet per l'URI « %s »" #: glib/gbookmarkfile.c:3503 glib/gbookmarkfile.c:3711 #, fuzzy, c-format @@ -4742,10 +4925,11 @@ msgstr "" "Cap d'aplicacion nomenada « %s » a pas enregistrat un signet per « %s »" #: glib/gbookmarkfile.c:3734 -#, c-format +#, fuzzy, c-format +#| msgid "Failed to expand exec line '%s' with URI '%s'" msgid "Failed to expand exec line “%s” with URI “%s”" msgstr "" -"Fracàs del desvolopament de la linha de comanda « %s » per l’URI « %s »" +"Fracàs del desvolopament de la linha de comanda « %s » per l'URI « %s »" #: glib/gconvert.c:467 #, fuzzy @@ -4759,7 +4943,8 @@ msgid "Partial character sequence at end of input" msgstr "Sequéncia de caractèrs incompleta en fin d'entrada" #: glib/gconvert.c:763 -#, c-format +#, fuzzy, c-format +#| msgid "Cannot convert fallback '%s' to codeset '%s'" msgid "Cannot convert fallback “%s” to codeset “%s”" msgstr "" "Impossible de convertir lo caractèr de replec « %s » dins lo jòc de còdis « " @@ -4790,10 +4975,9 @@ msgid "The local file URI “%s” may not include a “#”" msgstr "L'URI de fichièr local « %s » pòt pas inclure un caractèr « # »" #: glib/gconvert.c:1668 -#, fuzzy, c-format -#| msgid "The URI '%s' is invalid" +#, c-format msgid "The URI “%s” is invalid" -msgstr "L'URI « %s » es pas valid" +msgstr "L’URI « %s » es pas valida" #: glib/gconvert.c:1680 #, fuzzy, c-format @@ -5028,37 +5212,37 @@ msgstr "dimenge" #: glib/gdatetime.c:392 msgctxt "abbreviated weekday name" msgid "Mon" -msgstr "lun." +msgstr "Dl" #: glib/gdatetime.c:394 msgctxt "abbreviated weekday name" msgid "Tue" -msgstr "mar." +msgstr "Dm" #: glib/gdatetime.c:396 msgctxt "abbreviated weekday name" msgid "Wed" -msgstr "mèr." +msgstr "Dc" #: glib/gdatetime.c:398 msgctxt "abbreviated weekday name" msgid "Thu" -msgstr "jòu." +msgstr "Dj" #: glib/gdatetime.c:400 msgctxt "abbreviated weekday name" msgid "Fri" -msgstr "ven." +msgstr "Dv" #: glib/gdatetime.c:402 msgctxt "abbreviated weekday name" msgid "Sat" -msgstr "sab." +msgstr "Ds" #: glib/gdatetime.c:404 msgctxt "abbreviated weekday name" msgid "Sun" -msgstr "dim." +msgstr "Dg" #. Translators: Some languages need different grammatical forms of #. * month names depending on whether they are standalone or in a full @@ -5227,15 +5411,18 @@ msgid "PM" msgstr "PM" #: glib/gdir.c:154 -#, c-format +#, fuzzy, c-format +#| msgid "Error opening directory '%s': %s" msgid "Error opening directory “%s”: %s" msgstr "Error a la dobertura del repertòri « %s » : %s" #: glib/gfileutils.c:737 glib/gfileutils.c:829 -#, c-format +#, fuzzy, c-format +#| msgid "Could not allocate %lu byte to read file \"%s\"" +#| msgid_plural "Could not allocate %lu bytes to read file \"%s\"" msgid "Could not allocate %lu byte to read file “%s”" msgid_plural "Could not allocate %lu bytes to read file “%s”" -msgstr[0] "Impossible d'atribuir %lu octet per legir lo fichièr « %s »" +msgstr[0] "Impossible d'alogar %lu octet per legir lo fichièr « %s »" msgstr[1] "Impossible d'alogar %lu octets per legir lo fichièr « %s »" #: glib/gfileutils.c:754 @@ -5244,8 +5431,7 @@ msgid "Error reading file “%s”: %s" msgstr "Error de lectura del fichièr « %s » : %s" #: glib/gfileutils.c:790 -#, fuzzy, c-format -#| msgid "File \"%s\" is too large" +#, c-format msgid "File “%s” is too large" msgstr "Lo fichièr « %s » es tròp grand" @@ -5255,9 +5441,8 @@ msgstr "Lo fichièr « %s » es tròp grand" msgid "Failed to read from file “%s”: %s" msgstr "La lectura dempuèi lo fichièr « %s » a fracassat : %s" -#: glib/gfileutils.c:904 glib/gfileutils.c:979 glib/gfileutils.c:1476 -#, fuzzy, c-format -#| msgid "Failed to open file '%s': %s" +#: glib/gfileutils.c:904 glib/gfileutils.c:979 glib/gfileutils.c:1468 +#, c-format msgid "Failed to open file “%s”: %s" msgstr "La dobertura del fichièr « %s » a fracassat : %s" @@ -5297,37 +5482,39 @@ msgid "Failed to write file “%s”: fsync() failed: %s" msgstr "" "L'escritura dins lo fichièr « %s » a fracassat : fracàs de fsync() : %s" -#: glib/gfileutils.c:1365 glib/gfileutils.c:1780 -#, fuzzy, c-format -#| msgid "Failed to create file '%s': %s" +#: glib/gfileutils.c:1357 glib/gfileutils.c:1772 +#, c-format msgid "Failed to create file “%s”: %s" msgstr "La creacion del fichièr « %s » a fracassat : %s" -#: glib/gfileutils.c:1410 +#: glib/gfileutils.c:1402 #, fuzzy, c-format #| msgid "Existing file '%s' could not be removed: g_unlink() failed: %s" msgid "Existing file “%s” could not be removed: g_unlink() failed: %s" msgstr "" "Lo fichièr existent « %s » pòt pas èsser suprimit : fracàs de g_unlink() : %s" -#: glib/gfileutils.c:1745 -#, c-format +#: glib/gfileutils.c:1737 +#, fuzzy, c-format +#| msgid "Template '%s' invalid, should not contain a '%s'" msgid "Template “%s” invalid, should not contain a “%s”" msgstr "Lo modèl « %s » es pas valid, deuriá pas conténer un « %s »" -#: glib/gfileutils.c:1758 -#, c-format +#: glib/gfileutils.c:1750 +#, fuzzy, c-format +#| msgid "Template '%s' doesn't contain XXXXXX" msgid "Template “%s” doesn’t contain XXXXXX" msgstr "Lo modèl « %s » conten pas XXXXXX" -#: glib/gfileutils.c:2318 glib/gfileutils.c:2347 +#: glib/gfileutils.c:2310 glib/gfileutils.c:2339 #, fuzzy, c-format #| msgid "Failed to read the symbolic link '%s': %s" msgid "Failed to read the symbolic link “%s”: %s" msgstr "La lectura del ligam simbolic « %s » a fracassat : %s" #: glib/giochannel.c:1405 -#, c-format +#, fuzzy, c-format +#| msgid "Could not open converter from '%s' to '%s': %s" msgid "Could not open converter from “%s” to “%s”: %s" msgstr "Impossible de dobrir lo convertidor de « %s » cap a « %s » : %s" @@ -5352,16 +5539,16 @@ msgstr "La canal s'acaba amb un caractèr parcial" msgid "Can’t do a raw read in g_io_channel_read_to_end" msgstr "Lectura de donadas brutas impossibla dins g_io_channel_read_to_end" -#: glib/gkeyfile.c:790 +#: glib/gkeyfile.c:789 msgid "Valid key file could not be found in search dirs" msgstr "" "Impossible de trobar un fichièr de claus valid dins los repertòris de recèrca" -#: glib/gkeyfile.c:827 +#: glib/gkeyfile.c:826 msgid "Not a regular file" msgstr "Es pas un fichièr estandard" -#: glib/gkeyfile.c:1282 +#: glib/gkeyfile.c:1281 #, fuzzy, c-format #| msgid "" #| "Key file contains line '%s' which is not a key-value pair, group, or " @@ -5372,21 +5559,21 @@ msgstr "" "Lo fichièr de claus conten la linha « %s » qu'es pas ni una para de valors " "de clau, ni un grop, ni un comentari" -#: glib/gkeyfile.c:1339 +#: glib/gkeyfile.c:1338 #, c-format msgid "Invalid group name: %s" msgstr "Nom de grop invalid : %s" -#: glib/gkeyfile.c:1361 +#: glib/gkeyfile.c:1360 msgid "Key file does not start with a group" msgstr "Lo fichièr de claus comença pas per un grop" -#: glib/gkeyfile.c:1387 +#: glib/gkeyfile.c:1386 #, c-format msgid "Invalid key name: %s" msgstr "Nom de clau invalid : %s" -#: glib/gkeyfile.c:1414 +#: glib/gkeyfile.c:1413 #, fuzzy, c-format #| msgid "Key file contains unsupported encoding '%s'" msgid "Key file contains unsupported encoding “%s”" @@ -5394,21 +5581,21 @@ msgstr "" "Lo fichièr de claus conten un encodatge de caractèrs pas preses en carga « " "%s »" -#: glib/gkeyfile.c:1663 glib/gkeyfile.c:1836 glib/gkeyfile.c:3289 -#: glib/gkeyfile.c:3353 glib/gkeyfile.c:3483 glib/gkeyfile.c:3615 -#: glib/gkeyfile.c:3761 glib/gkeyfile.c:3996 glib/gkeyfile.c:4063 +#: glib/gkeyfile.c:1662 glib/gkeyfile.c:1835 glib/gkeyfile.c:3288 +#: glib/gkeyfile.c:3352 glib/gkeyfile.c:3482 glib/gkeyfile.c:3614 +#: glib/gkeyfile.c:3760 glib/gkeyfile.c:3995 glib/gkeyfile.c:4062 #, fuzzy, c-format #| msgid "Key file does not have group '%s'" msgid "Key file does not have group “%s”" msgstr "Lo fichièr de claus a pas de grop « %s »" -#: glib/gkeyfile.c:1791 +#: glib/gkeyfile.c:1790 #, fuzzy, c-format #| msgid "Key file does not have key '%s' in group '%s'" msgid "Key file does not have key “%s” in group “%s”" msgstr "Lo fichièr de claus conten pas de clau « %s » dins lo grop « %s »" -#: glib/gkeyfile.c:1953 glib/gkeyfile.c:2069 +#: glib/gkeyfile.c:1952 glib/gkeyfile.c:2068 #, fuzzy, c-format #| msgid "Key file contains key '%s' with value '%s' which is not UTF-8" msgid "Key file contains key “%s” with value “%s” which is not UTF-8" @@ -5416,7 +5603,7 @@ msgstr "" "Lo fichièr de claus conten la clau « %s » amb la valor « %s » qu'es pas " "encodat en UTF-8" -#: glib/gkeyfile.c:1973 glib/gkeyfile.c:2089 glib/gkeyfile.c:2531 +#: glib/gkeyfile.c:1972 glib/gkeyfile.c:2088 glib/gkeyfile.c:2530 #, fuzzy, c-format #| msgid "" #| "Key file contains key '%s' which has a value that cannot be interpreted." @@ -5426,7 +5613,7 @@ msgstr "" "Lo fichièr de claus conten la clau « %s » qu'una valor n'es impossibla a " "interpretar." -#: glib/gkeyfile.c:2749 glib/gkeyfile.c:3118 +#: glib/gkeyfile.c:2748 glib/gkeyfile.c:3117 #, fuzzy, c-format #| msgid "" #| "Key file contains key '%s' in group '%s' which has a value that cannot be " @@ -5438,7 +5625,7 @@ msgstr "" "Lo fichièr de claus conten la clau « %s » dins lo grop « %s » qu'a una valor " "impossibla a interpretar." -#: glib/gkeyfile.c:2827 glib/gkeyfile.c:2904 +#: glib/gkeyfile.c:2826 glib/gkeyfile.c:2903 #, fuzzy, c-format #| msgid "Key '%s' in group '%s' has value '%s' where %s was expected" msgid "Key “%s” in group “%s” has value “%s” where %s was expected" @@ -5446,36 +5633,36 @@ msgstr "" "La clau « %s » dins lo grop « %s » a una valor « %s » mentre que %s èra " "esperat" -#: glib/gkeyfile.c:4306 +#: glib/gkeyfile.c:4305 msgid "Key file contains escape character at end of line" msgstr "Lo fichièr de claus conten un caractèr d'escapament en fin de linha" -#: glib/gkeyfile.c:4328 +#: glib/gkeyfile.c:4327 #, fuzzy, c-format #| msgid "Key file contains invalid escape sequence '%s'" msgid "Key file contains invalid escape sequence “%s”" msgstr "Lo fichièr de claus conten una sequéncia d'escapament invalida « %s »" -#: glib/gkeyfile.c:4472 +#: glib/gkeyfile.c:4471 #, fuzzy, c-format #| msgid "Value '%s' cannot be interpreted as a number." msgid "Value “%s” cannot be interpreted as a number." msgstr "La valor « %s » pòt pas èsser interpretada coma un nombre." -#: glib/gkeyfile.c:4486 +#: glib/gkeyfile.c:4485 #, fuzzy, c-format #| msgid "Integer value '%s' out of range" msgid "Integer value “%s” out of range" msgstr "La valor entièra « %s » es fòra plaja" -#: glib/gkeyfile.c:4519 +#: glib/gkeyfile.c:4518 #, fuzzy, c-format #| msgid "Value '%s' cannot be interpreted as a float number." msgid "Value “%s” cannot be interpreted as a float number." msgstr "" "La valor « %s » pòt pas èsser interpretada coma un nombre a virgula flotanta." -#: glib/gkeyfile.c:4558 +#: glib/gkeyfile.c:4557 #, fuzzy, c-format #| msgid "Value '%s' cannot be interpreted as a boolean." msgid "Value “%s” cannot be interpreted as a boolean." @@ -5517,7 +5704,8 @@ msgid "“%s” is not a valid name" msgstr "« %s » es pas un nom valid" #: glib/gmarkup.c:489 -#, c-format +#, fuzzy, c-format +#| msgid "'%s' is not a valid name: '%c'" msgid "“%s” is not a valid name: “%c”" msgstr "« %s » es pas un nom valid : « %c »" @@ -5809,9 +5997,10 @@ msgid "Options:" msgstr "Opcions :" #: glib/goption.c:1125 glib/goption.c:1195 -#, c-format +#, fuzzy, c-format +#| msgid "Cannot parse integer value '%s' for %s" msgid "Cannot parse integer value “%s” for %s" -msgstr "Impossible d’analisar la valor entièra « %s » per %s" +msgstr "Impossible d'analisar la valor entièra « %s » per %s" #: glib/goption.c:1135 glib/goption.c:1203 #, fuzzy, c-format @@ -5820,9 +6009,10 @@ msgid "Integer value “%s” for %s out of range" msgstr "La valor entièra « %s » per %s es fòra plaja" #: glib/goption.c:1160 -#, c-format +#, fuzzy, c-format +#| msgid "Cannot parse double value '%s' for %s" msgid "Cannot parse double value “%s” for %s" -msgstr "Impossible d’analisar la valor dobla « %s » per %s" +msgstr "Impossible d'analisar la valor dobla « %s » per %s" #: glib/goption.c:1168 #, fuzzy, c-format @@ -5835,12 +6025,12 @@ msgstr "La valor dobla « %s » per %s es fòra plaja" msgid "Error parsing option %s" msgstr "Error al moment de l'analisi de l'opcion %s" -#: glib/goption.c:1570 glib/goption.c:1683 +#: glib/goption.c:1561 glib/goption.c:1674 #, c-format msgid "Missing argument for %s" msgstr "Argument mancant per %s" -#: glib/goption.c:2194 +#: glib/goption.c:2185 #, c-format msgid "Unknown option %s" msgstr "Opcion desconeguda %s" @@ -6183,14 +6373,18 @@ msgid "Error while compiling regular expression %s at char %d: %s" msgstr "Error a la compilation de l'expression regulara %s al caractèr %d : %s" #: glib/gregex.c:2419 +#, fuzzy +#| msgid "hexadecimal digit or '}' expected" msgid "hexadecimal digit or “}” expected" -msgstr "chifra exadecimala o « } » esperada" +msgstr "chifra exadecimala o « } » esperat" #: glib/gregex.c:2435 msgid "hexadecimal digit expected" msgstr "chifra exadecimala esperat" #: glib/gregex.c:2475 +#, fuzzy +#| msgid "missing '<' in symbolic reference" msgid "missing “<” in symbolic reference" msgstr "« < » mancant dins la referéncia simbolica" @@ -6221,10 +6415,11 @@ msgid "unknown escape sequence" msgstr "sequéncia d'escapament desconeguda" #: glib/gregex.c:2597 -#, c-format +#, fuzzy, c-format +#| msgid "Error while parsing replacement text \"%s\" at char %lu: %s" msgid "Error while parsing replacement text “%s” at char %lu: %s" msgstr "" -"Error al moment de l’analisi del tèxte de substitucion « %s » al caractèr " +"Error al moment de l'analisi del tèxte de substitucion « %s » al caractèr " "%lu : %s" #: glib/gshell.c:94 @@ -6259,89 +6454,91 @@ msgstr "" msgid "Text was empty (or contained only whitespace)" msgstr "Lo tèxte èra void (o conteniá pas que d'espacis)" -#: glib/gspawn.c:318 +#: glib/gspawn.c:308 #, c-format msgid "Failed to read data from child process (%s)" msgstr "La lectura de las donadas dempuèi lo processus filh a fracassat (%s)" -#: glib/gspawn.c:465 -#, c-format +#: glib/gspawn.c:455 +#, fuzzy, c-format +#| msgid "Unexpected error in select() reading data from a child process (%s)" msgid "Unexpected error in reading data from a child process (%s)" msgstr "" "Error inesperada dins select() a la lectura de las donadas dempuèi un " "processus filh (%s)" -#: glib/gspawn.c:550 +#: glib/gspawn.c:540 #, c-format msgid "Unexpected error in waitpid() (%s)" msgstr "Error inesperada dins waitpid() (%s)" -#: glib/gspawn.c:1154 glib/gspawn-win32.c:1383 +#: glib/gspawn.c:1144 glib/gspawn-win32.c:1383 #, c-format msgid "Child process exited with code %ld" msgstr "Lo processus filh s'es acabat amb lo còdi %ld" -#: glib/gspawn.c:1162 +#: glib/gspawn.c:1152 #, c-format msgid "Child process killed by signal %ld" msgstr "Lo processus filh es estat tuat pel senhal %ld" -#: glib/gspawn.c:1169 +#: glib/gspawn.c:1159 #, c-format msgid "Child process stopped by signal %ld" msgstr "Lo processus filh es estat arrestat pel senhal %ld" -#: glib/gspawn.c:1176 +#: glib/gspawn.c:1166 #, c-format msgid "Child process exited abnormally" msgstr "Lo processus filh s'es acabat anormalement" -#: glib/gspawn.c:1767 glib/gspawn-win32.c:350 glib/gspawn-win32.c:358 +#: glib/gspawn.c:1757 glib/gspawn-win32.c:350 glib/gspawn-win32.c:358 #, c-format msgid "Failed to read from child pipe (%s)" msgstr "La lectura dempuèi un tub filh a fracassat (%s)" -#: glib/gspawn.c:2069 +#: glib/gspawn.c:2059 #, fuzzy, c-format #| msgid "Failed to fork child process (%s)" msgid "Failed to spawn child process “%s” (%s)" msgstr "Lo clonatge del processus filh a fracassat (%s)" -#: glib/gspawn.c:2186 +#: glib/gspawn.c:2176 #, c-format msgid "Failed to fork (%s)" msgstr "Lo clonatge a fracassat (%s)" -#: glib/gspawn.c:2346 glib/gspawn-win32.c:381 +#: glib/gspawn.c:2336 glib/gspawn-win32.c:381 #, fuzzy, c-format #| msgid "Failed to change to directory '%s' (%s)" msgid "Failed to change to directory “%s” (%s)" msgstr "Lo cambiament de repertòri « %s » a fracassat (%s)" -#: glib/gspawn.c:2356 +#: glib/gspawn.c:2346 #, fuzzy, c-format #| msgid "Failed to execute child process \"%s\" (%s)" msgid "Failed to execute child process “%s” (%s)" msgstr "L'execucion del processus filh « %s » a fracassat (%s)" -#: glib/gspawn.c:2366 +#: glib/gspawn.c:2356 #, c-format msgid "Failed to redirect output or input of child process (%s)" msgstr "" "La redireccion de la sortida o de l'entrada del processus filh a fracassat " "(%s)" -#: glib/gspawn.c:2375 +#: glib/gspawn.c:2365 #, c-format msgid "Failed to fork child process (%s)" msgstr "Lo clonatge del processus filh a fracassat (%s)" -#: glib/gspawn.c:2383 -#, c-format +#: glib/gspawn.c:2373 +#, fuzzy, c-format +#| msgid "Unknown error executing child process \"%s\"" msgid "Unknown error executing child process “%s”" -msgstr "Error desconeguda a l’execucion del processus filh « %s »" +msgstr "Error desconeguda a l'execucion del processus filh « %s »" -#: glib/gspawn.c:2407 +#: glib/gspawn.c:2397 #, c-format msgid "Failed to read enough data from child pid pipe (%s)" msgstr "" @@ -6398,12 +6595,12 @@ msgstr "" #: glib/gstrfuncs.c:3338 glib/gstrfuncs.c:3440 msgid "Empty string is not a number" -msgstr "Una cadena voida es pas un nombre" +msgstr "" #: glib/gstrfuncs.c:3362 #, c-format msgid "“%s” is not a signed number" -msgstr "« %s » es pas un nombre signat" +msgstr "« %s » es pas un nombre valid" #: glib/gstrfuncs.c:3372 glib/gstrfuncs.c:3476 #, c-format @@ -6411,14 +6608,16 @@ msgid "Number “%s” is out of bounds [%s, %s]" msgstr "" #: glib/gstrfuncs.c:3466 -#, c-format +#, fuzzy, c-format +#| msgid "'%s' is not a valid name" msgid "“%s” is not an unsigned number" -msgstr "« %s » es pas un nombre pas signat" +msgstr "« %s » es pas un nom valid" #: glib/guri.c:315 -#, no-c-format +#, fuzzy, no-c-format +#| msgid " (invalid encoding)" msgid "Invalid %-encoding in URI" -msgstr "%-encoding invalid dins l'URI" +msgstr " (encodatge invalid)" #: glib/guri.c:332 msgid "Illegal character in URI" @@ -6451,22 +6650,21 @@ msgstr "Impossible d’analisar lo pòrt « %.*s » dins l’URI" #: glib/guri.c:664 #, c-format msgid "Port ‘%.*s’ in URI is out of range" -msgstr "Lo pòrt « %.*s » dins l’URI es fòra plaja" +msgstr "" #: glib/guri.c:1224 glib/guri.c:1288 -#, fuzzy, c-format -#| msgid "The URI '%s' is not an absolute URI using the \"file\" scheme" +#, c-format msgid "URI ‘%s’ is not an absolute URI" -msgstr "L'URI « %s » es pas una URI absoluda qu'utiliza lo protocòl « file »" +msgstr "L’URI « %s » es pas una URI absoluta" #: glib/guri.c:1230 #, c-format msgid "URI ‘%s’ has no host component" -msgstr "L’URI « %s » a pas de component òste" +msgstr "" #: glib/guri.c:1435 msgid "URI is not absolute, and no base URI was provided" -msgstr "L'URI es pas absoluda, e cap d'URI de basa es pas estada provesida" +msgstr "" #: glib/guri.c:2209 msgid "Missing ‘=’ and parameter value" @@ -6499,79 +6697,79 @@ msgstr "%.1f ko" #: glib/gutils.c:2769 #, c-format msgid "%.1f MB" -msgstr "%.1f Mo" +msgstr "%.1f Mo" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2771 #, c-format msgid "%.1f GB" -msgstr "%.1f Go" +msgstr "%.1f Go" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2773 #, c-format msgid "%.1f TB" -msgstr "%.1f To" +msgstr "%.1f To" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2775 #, c-format msgid "%.1f PB" -msgstr "%.1f Po" +msgstr "%.1f Po" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2777 #, c-format msgid "%.1f EB" -msgstr "%.1f Eo" +msgstr "%.1f Eo" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2781 #, c-format msgid "%.1f KiB" -msgstr "%.1f Kio" +msgstr "%.1f Kio" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2783 #, c-format msgid "%.1f MiB" -msgstr "%.1f Mio" +msgstr "%.1f Mio" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2785 #, c-format msgid "%.1f GiB" -msgstr "%.1f Gio" +msgstr "%.1f Gio" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2787 #, c-format msgid "%.1f TiB" -msgstr "%.1f Tio" +msgstr "%.1f Tio" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2789 #, c-format msgid "%.1f PiB" -msgstr "%.1f Pio" +msgstr "%.1f Pio" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2791 #, c-format msgid "%.1f EiB" -msgstr "%.1f Eio" +msgstr "%.1f Eio" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2795 #, c-format msgid "%.1f kb" -msgstr "%.1f kb" +msgstr "%.1f kb" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2797 #, c-format msgid "%.1f Mb" -msgstr "%.1f Mb" +msgstr "%.1f Mb" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2799 @@ -6583,13 +6781,13 @@ msgstr "%.1f Gb" #: glib/gutils.c:2801 #, c-format msgid "%.1f Tb" -msgstr "%.1f Tb" +msgstr "%.1f Tb" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2803 #, c-format msgid "%.1f Pb" -msgstr "%.1f Pb" +msgstr "%.1f Pb" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2805 @@ -6601,37 +6799,37 @@ msgstr "%.1f Eb" #: glib/gutils.c:2809 #, c-format msgid "%.1f Kib" -msgstr "%.1f Kib" +msgstr "%.1f Kio" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2811 #, c-format msgid "%.1f Mib" -msgstr "%.1f Mib" +msgstr "%.1f Mio" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2813 #, c-format msgid "%.1f Gib" -msgstr "%.1f Gib" +msgstr "%.1f Gio" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2815 #, c-format msgid "%.1f Tib" -msgstr "%.1f Tib" +msgstr "%.1f Tio" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2817 #, c-format msgid "%.1f Pib" -msgstr "%.1f Pib" +msgstr "%.1f Pio" #. Translators: Keep the no-break space between %.1f and the unit symbol #: glib/gutils.c:2819 #, c-format msgid "%.1f Eib" -msgstr "%.1f Eib" +msgstr "%.1f Eio" #: glib/gutils.c:2853 glib/gutils.c:2970 #, c-format @@ -12,9 +12,9 @@ msgid "" msgstr "" "Project-Id-Version: 2.8\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/glib/issues\n" -"POT-Creation-Date: 2021-04-08 13:42+0000\n" -"PO-Revision-Date: 2021-04-11 20:17+0200\n" -"Last-Translator: Мирослав Николић <miroslavnikolic@rocketmail.com>\n" +"POT-Creation-Date: 2021-03-18 14:00+0000\n" +"PO-Revision-Date: 2021-03-19 08:29+0100\n" +"Last-Translator: Марко М. Костић <marko.m.kostic@gmail.com>\n" "Language-Team: српски <gnome-sr@googlegroups.org>\n" "Language: sr\n" "MIME-Version: 1.0\n" @@ -23,6 +23,7 @@ msgstr "" "Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n" "%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Project-Style: gnome\n" +"X-Generator: Poedit 2.4.2\n" #: gio/gapplication.c:500 msgid "GApplication options" @@ -966,7 +967,6 @@ msgstr "Не могу да добавим профил физичких дело #. Translators: Both placeholders are file paths #: gio/gdbusprivate.c:2494 #, c-format -#| msgid "Unable to load ‘%s‘: %s" msgid "Unable to load %s or %s: " msgstr "Не могу да учитам „%s“ или „%s“: " @@ -3983,36 +3983,36 @@ msgstr "Грешка у затварању утичнице: %s" msgid "Waiting for socket condition: %s" msgstr "Чекам услов утичнице: %s" -#: gio/gsocket.c:4806 gio/gsocket.c:4824 gio/gsocket.c:4837 +#: gio/gsocket.c:4804 gio/gsocket.c:4820 gio/gsocket.c:4833 #, c-format msgid "Unable to send message: %s" msgstr "Не могу да пошаљем поруку: %s" -#: gio/gsocket.c:4807 gio/gsocket.c:4825 gio/gsocket.c:4838 +#: gio/gsocket.c:4805 gio/gsocket.c:4821 gio/gsocket.c:4834 msgid "Message vectors too large" msgstr "Вектори поруке су превелики" -#: gio/gsocket.c:4854 gio/gsocket.c:4856 gio/gsocket.c:5003 gio/gsocket.c:5088 -#: gio/gsocket.c:5266 gio/gsocket.c:5306 gio/gsocket.c:5308 +#: gio/gsocket.c:4850 gio/gsocket.c:4852 gio/gsocket.c:4999 gio/gsocket.c:5084 +#: gio/gsocket.c:5262 gio/gsocket.c:5302 gio/gsocket.c:5304 #, c-format msgid "Error sending message: %s" msgstr "Грешка при слању поруке: %s" -#: gio/gsocket.c:5030 +#: gio/gsocket.c:5026 msgid "GSocketControlMessage not supported on Windows" msgstr "Порука управљања Гутичницом није подржана на Виндоузу" -#: gio/gsocket.c:5499 gio/gsocket.c:5575 gio/gsocket.c:5801 +#: gio/gsocket.c:5495 gio/gsocket.c:5571 gio/gsocket.c:5797 #, c-format msgid "Error receiving message: %s" msgstr "Грешка при примању поруке: %s" -#: gio/gsocket.c:6074 gio/gsocket.c:6085 gio/gsocket.c:6131 +#: gio/gsocket.c:6070 gio/gsocket.c:6081 gio/gsocket.c:6127 #, c-format msgid "Unable to read socket credentials: %s" msgstr "Не могу да прочитам уверења утичнице: %s" -#: gio/gsocket.c:6140 +#: gio/gsocket.c:6136 msgid "g_socket_get_credentials not implemented for this OS" msgstr "г_утичница_добавља_уверења није примењена за овај оперативни систем" @@ -5019,16 +5019,16 @@ msgstr "Канал се завршава делимичним знаком" msgid "Can’t do a raw read in g_io_channel_read_to_end" msgstr "Не могу да читам без обраде у г_уи_каналу_читај_до_краја" -#: glib/gkeyfile.c:790 +#: glib/gkeyfile.c:789 msgid "Valid key file could not be found in search dirs" msgstr "" "Не могу да нађем исправну датотеку са кључевима међу директоријумима претраге" -#: glib/gkeyfile.c:827 +#: glib/gkeyfile.c:826 msgid "Not a regular file" msgstr "Није обична датотека" -#: glib/gkeyfile.c:1282 +#: glib/gkeyfile.c:1281 #, c-format msgid "" "Key file contains line “%s” which is not a key-value pair, group, or comment" @@ -5036,49 +5036,49 @@ msgstr "" "Датотека са кључевима садржи ред „%s“ што не чини пар кључ-вредност, групу " "или примедбу" -#: glib/gkeyfile.c:1339 +#: glib/gkeyfile.c:1338 #, c-format msgid "Invalid group name: %s" msgstr "Неисправан назив групе: %s" -#: glib/gkeyfile.c:1361 +#: glib/gkeyfile.c:1360 msgid "Key file does not start with a group" msgstr "Датотека са кључевима не почиње групом" -#: glib/gkeyfile.c:1387 +#: glib/gkeyfile.c:1386 #, c-format msgid "Invalid key name: %s" msgstr "Неисправан назив кључа: %s" -#: glib/gkeyfile.c:1414 +#: glib/gkeyfile.c:1413 #, c-format msgid "Key file contains unsupported encoding “%s”" msgstr "Датотека са кључевима садржи неподржано кодирање „%s“" -#: glib/gkeyfile.c:1663 glib/gkeyfile.c:1836 glib/gkeyfile.c:3289 -#: glib/gkeyfile.c:3353 glib/gkeyfile.c:3483 glib/gkeyfile.c:3615 -#: glib/gkeyfile.c:3761 glib/gkeyfile.c:3996 glib/gkeyfile.c:4063 +#: glib/gkeyfile.c:1662 glib/gkeyfile.c:1835 glib/gkeyfile.c:3288 +#: glib/gkeyfile.c:3352 glib/gkeyfile.c:3482 glib/gkeyfile.c:3614 +#: glib/gkeyfile.c:3760 glib/gkeyfile.c:3995 glib/gkeyfile.c:4062 #, c-format msgid "Key file does not have group “%s”" msgstr "Датотека са кључевима нема групу „%s“" -#: glib/gkeyfile.c:1791 +#: glib/gkeyfile.c:1790 #, c-format msgid "Key file does not have key “%s” in group “%s”" msgstr "Датотека са кључевима не садржи кључ „%s“ у групи „%s“" -#: glib/gkeyfile.c:1953 glib/gkeyfile.c:2069 +#: glib/gkeyfile.c:1952 glib/gkeyfile.c:2068 #, c-format msgid "Key file contains key “%s” with value “%s” which is not UTF-8" msgstr "Датотека са кључевима садржи кључ „%s“ вредности „%s“ што није УТФ-8" -#: glib/gkeyfile.c:1973 glib/gkeyfile.c:2089 glib/gkeyfile.c:2531 +#: glib/gkeyfile.c:1972 glib/gkeyfile.c:2088 glib/gkeyfile.c:2530 #, c-format msgid "" "Key file contains key “%s” which has a value that cannot be interpreted." msgstr "Датотека са кључевима садржи кључ „%s“ неразумљиве вредности." -#: glib/gkeyfile.c:2749 glib/gkeyfile.c:3118 +#: glib/gkeyfile.c:2748 glib/gkeyfile.c:3117 #, c-format msgid "" "Key file contains key “%s” in group “%s” which has a value that cannot be " @@ -5086,36 +5086,36 @@ msgid "" msgstr "" "Датотека са кључевима садржи кључ „%s“ у групи „%s“ неразумљиве вредности." -#: glib/gkeyfile.c:2827 glib/gkeyfile.c:2904 +#: glib/gkeyfile.c:2826 glib/gkeyfile.c:2903 #, c-format msgid "Key “%s” in group “%s” has value “%s” where %s was expected" msgstr "Кључ „%s“ у групи „%s“ има вредност „%s“ где је очекивано %s" -#: glib/gkeyfile.c:4306 +#: glib/gkeyfile.c:4305 msgid "Key file contains escape character at end of line" msgstr "Датотека са кључевима садржи знак истицања на крају реда" -#: glib/gkeyfile.c:4328 +#: glib/gkeyfile.c:4327 #, c-format msgid "Key file contains invalid escape sequence “%s”" msgstr "Датотека са кључевима садржи недозвољен низ истицања „%s“" -#: glib/gkeyfile.c:4472 +#: glib/gkeyfile.c:4471 #, c-format msgid "Value “%s” cannot be interpreted as a number." msgstr "Вредност „%s“ се не може сматрати бројем." -#: glib/gkeyfile.c:4486 +#: glib/gkeyfile.c:4485 #, c-format msgid "Integer value “%s” out of range" msgstr "Целобројна вредност „%s“ је изван опсега" -#: glib/gkeyfile.c:4519 +#: glib/gkeyfile.c:4518 #, c-format msgid "Value “%s” cannot be interpreted as a float number." msgstr "Вредност „%s“ се не може сматрати реалним бројем једноструке тачности." -#: glib/gkeyfile.c:4558 +#: glib/gkeyfile.c:4557 #, c-format msgid "Value “%s” cannot be interpreted as a boolean." msgstr "Вредност „%s“ се не може сматрати истинитосном." diff --git a/po/zh_CN.po b/po/zh_CN.po index 547b5e7b9..776d6c446 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -20,9 +20,9 @@ # msgid "" msgstr "" -"Project-Id-Version: glib 2.68\n" +"Project-Id-Version: glib master\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/glib/issues\n" -"POT-Creation-Date: 2021-06-15 18:41+0000\n" +"POT-Creation-Date: 2021-03-22 11:48+0000\n" "PO-Revision-Date: 2021-03-28 01:17+0800\n" "Last-Translator: Dingzhong Chen <wsxy162@gmail.com>\n" "Language-Team: Chinese - China <i18n-zh@googlegroups.com>\n" @@ -627,7 +627,7 @@ msgstr "打开钥匙环“%s”以写入时出错:" #: gio/gdbusauthmechanismsha1.c:908 #, c-format msgid "(Additionally, releasing the lock for “%s” also failed: %s) " -msgstr "(此外,解除“%s”的锁定也失败了:%s)" +msgstr "(此外,解除“%s”的锁定也失败了:%s) " #: gio/gdbusconnection.c:603 gio/gdbusconnection.c:2405 msgid "The connection is closed" @@ -1378,7 +1378,7 @@ msgstr "无法复制特殊文件" msgid "Invalid symlink value given" msgstr "给定的符号链接值无效" -#: gio/gfile.c:4045 glib/gfileutils.c:2362 +#: gio/gfile.c:4045 glib/gfileutils.c:2354 msgid "Symbolic links not supported" msgstr "不支持符号链接" @@ -1871,7 +1871,7 @@ msgstr "无法加载“%s”的应用程序信息" #: gio/gio-tool-launch.c:119 #, c-format msgid "Unable to launch application ‘%s’: %s" -msgstr "无法启动应用程序“%s”:%s" +msgstr "无法启动应用程序“%s”: %s" #: gio/gio-tool-list.c:37 gio/gio-tool-tree.c:32 msgid "Show hidden files" @@ -2264,7 +2264,7 @@ msgstr "无法找到原始路径" #: gio/gio-tool-trash.c:123 msgid "Unable to recreate original location: " -msgstr "无法重新创建原始位置:" +msgstr "无法创建原始位置:" #: gio/gio-tool-trash.c:136 msgid "Unable to move file to its original location: " @@ -2272,7 +2272,7 @@ msgstr "无法移动文件回它的原始位置:" #: gio/gio-tool-trash.c:225 msgid "Move/Restore files or directories to the trash." -msgstr "移动/恢复文件或目录到回收站。" +msgstr "移动/还原文件或目录到回收站。" #: gio/gio-tool-trash.c:227 msgid "" @@ -3000,9 +3000,9 @@ msgstr "移动文件 %s 时出错:%s" msgid "Can’t move directory over directory" msgstr "无法将目录移动到目录" -#: gio/glocalfile.c:2493 gio/glocalfileoutputstream.c:1108 -#: gio/glocalfileoutputstream.c:1122 gio/glocalfileoutputstream.c:1137 -#: gio/glocalfileoutputstream.c:1154 gio/glocalfileoutputstream.c:1168 +#: gio/glocalfile.c:2493 gio/glocalfileoutputstream.c:1079 +#: gio/glocalfileoutputstream.c:1093 gio/glocalfileoutputstream.c:1108 +#: gio/glocalfileoutputstream.c:1125 gio/glocalfileoutputstream.c:1139 msgid "Backup file creation failed" msgstr "备份文件创建失败" @@ -3039,10 +3039,9 @@ msgstr "设置扩展属性“%s”时出错:%s" #: gio/glocalfileinfo.c:1709 gio/win32/gwinhttpfile.c:191 msgid " (invalid encoding)" -msgstr "(无效的编码)" +msgstr " (无效的编码)" #: gio/glocalfileinfo.c:1868 gio/glocalfileoutputstream.c:943 -#: gio/glocalfileoutputstream.c:995 #, c-format msgid "Error when getting information for file “%s”: %s" msgstr "获取文件“%s”的信息时出错:%s" @@ -3162,7 +3161,7 @@ msgid "Error closing file: %s" msgstr "关闭文件出错:%s" #: gio/glocalfileinputstream.c:272 gio/glocalfileoutputstream.c:563 -#: gio/glocalfileoutputstream.c:1186 +#: gio/glocalfileoutputstream.c:1157 #, c-format msgid "Error seeking in file: %s" msgstr "在文件中定位时出错:%s" @@ -3192,13 +3191,13 @@ msgstr "创建备份拷贝:%s" msgid "Error renaming temporary file: %s" msgstr "重命名临时文件出错:%s" -#: gio/glocalfileoutputstream.c:609 gio/glocalfileoutputstream.c:1237 +#: gio/glocalfileoutputstream.c:609 gio/glocalfileoutputstream.c:1208 #, c-format msgid "Error truncating file: %s" msgstr "截断文件出错:%s" #: gio/glocalfileoutputstream.c:662 gio/glocalfileoutputstream.c:907 -#: gio/glocalfileoutputstream.c:1218 gio/gsubprocess.c:226 +#: gio/glocalfileoutputstream.c:1189 gio/gsubprocess.c:226 #, c-format msgid "Error opening file “%s”: %s" msgstr "打开文件“%s”出错:%s" @@ -3211,11 +3210,11 @@ msgstr "目标文件是目录" msgid "Target file is not a regular file" msgstr "目标文件不是普通文件" -#: gio/glocalfileoutputstream.c:1013 +#: gio/glocalfileoutputstream.c:984 msgid "The file was externally modified" msgstr "文件已经被其他程序修改" -#: gio/glocalfileoutputstream.c:1202 +#: gio/glocalfileoutputstream.c:1173 #, c-format msgid "Error removing old file: %s" msgstr "移除旧文件出错:%s" @@ -3884,36 +3883,36 @@ msgstr "关闭套接字时出错:%s" msgid "Waiting for socket condition: %s" msgstr "等待套接字状态:%s" -#: gio/gsocket.c:4806 gio/gsocket.c:4824 gio/gsocket.c:4837 +#: gio/gsocket.c:4804 gio/gsocket.c:4820 gio/gsocket.c:4833 #, c-format msgid "Unable to send message: %s" -msgstr "无法发送消息:%s" +msgstr "无法发送信息:%s" -#: gio/gsocket.c:4807 gio/gsocket.c:4825 gio/gsocket.c:4838 +#: gio/gsocket.c:4805 gio/gsocket.c:4821 gio/gsocket.c:4834 msgid "Message vectors too large" msgstr "信息向量过大" -#: gio/gsocket.c:4854 gio/gsocket.c:4856 gio/gsocket.c:5003 gio/gsocket.c:5088 -#: gio/gsocket.c:5266 gio/gsocket.c:5306 gio/gsocket.c:5308 +#: gio/gsocket.c:4850 gio/gsocket.c:4852 gio/gsocket.c:4999 gio/gsocket.c:5084 +#: gio/gsocket.c:5262 gio/gsocket.c:5302 gio/gsocket.c:5304 #, c-format msgid "Error sending message: %s" msgstr "发送信息时出错:%s" -#: gio/gsocket.c:5030 +#: gio/gsocket.c:5026 msgid "GSocketControlMessage not supported on Windows" msgstr "Windows 不支持 GSocketControlMessage" -#: gio/gsocket.c:5499 gio/gsocket.c:5575 gio/gsocket.c:5801 +#: gio/gsocket.c:5495 gio/gsocket.c:5571 gio/gsocket.c:5797 #, c-format msgid "Error receiving message: %s" msgstr "接受信息时出错:%s" -#: gio/gsocket.c:6074 gio/gsocket.c:6085 gio/gsocket.c:6131 +#: gio/gsocket.c:6070 gio/gsocket.c:6081 gio/gsocket.c:6127 #, c-format msgid "Unable to read socket credentials: %s" msgstr "无法读取套接字认证信息:%s" -#: gio/gsocket.c:6140 +#: gio/gsocket.c:6136 msgid "g_socket_get_credentials not implemented for this OS" msgstr "此操作系统上没有实现 g_socket_get_credentials" @@ -4064,29 +4063,29 @@ msgstr "暂时无法解析“%s”" msgid "Error resolving “%s”" msgstr "解析“%s”时出错" -#: gio/gtlscertificate.c:299 +#: gio/gtlscertificate.c:298 msgid "No PEM-encoded private key found" msgstr "未找到 PEM 加密的私钥" -#: gio/gtlscertificate.c:309 +#: gio/gtlscertificate.c:308 msgid "Cannot decrypt PEM-encoded private key" msgstr "无法解密 PEM 加密的私钥" -#: gio/gtlscertificate.c:320 +#: gio/gtlscertificate.c:319 msgid "Could not parse PEM-encoded private key" msgstr "无法解析 PEM 加密的私钥" -#: gio/gtlscertificate.c:347 +#: gio/gtlscertificate.c:346 msgid "No PEM-encoded certificate found" msgstr "未找到 PEM 加密的证书" -#: gio/gtlscertificate.c:356 +#: gio/gtlscertificate.c:355 msgid "Could not parse PEM-encoded certificate" msgstr "无法解析 PEM 加密的证书" -#: gio/gtlscertificate.c:711 +#: gio/gtlscertificate.c:710 msgid "This GTlsBackend does not support creating PKCS #11 certificates" -msgstr "此 GTlsBackend 不支持创建 PKCS #11 证书" +msgstr "本 GTlsBackend 不支持创建 PKCS #11 证书" #: gio/gtlspassword.c:111 msgid "" @@ -4818,7 +4817,7 @@ msgstr "文件“%s”过大" msgid "Failed to read from file “%s”: %s" msgstr "读取文件“%s”失败:%s" -#: glib/gfileutils.c:904 glib/gfileutils.c:979 glib/gfileutils.c:1476 +#: glib/gfileutils.c:904 glib/gfileutils.c:979 glib/gfileutils.c:1468 #, c-format msgid "Failed to open file “%s”: %s" msgstr "打开文件“%s”失败:%s" @@ -4848,27 +4847,27 @@ msgstr "写入文件“%s”失败:write() 失败:%s" msgid "Failed to write file “%s”: fsync() failed: %s" msgstr "写入文件“%s”失败:fsync() 失败:%s" -#: glib/gfileutils.c:1365 glib/gfileutils.c:1780 +#: glib/gfileutils.c:1357 glib/gfileutils.c:1772 #, c-format msgid "Failed to create file “%s”: %s" msgstr "创建文件“%s”失败:%s" -#: glib/gfileutils.c:1410 +#: glib/gfileutils.c:1402 #, c-format msgid "Existing file “%s” could not be removed: g_unlink() failed: %s" msgstr "无法删除已有文件“%s”:g_unlink() 失败:%s" -#: glib/gfileutils.c:1745 +#: glib/gfileutils.c:1737 #, c-format msgid "Template “%s” invalid, should not contain a “%s”" msgstr "模板“%s”无效,不应该包含“%s”" -#: glib/gfileutils.c:1758 +#: glib/gfileutils.c:1750 #, c-format msgid "Template “%s” doesn’t contain XXXXXX" msgstr "模板“%s”不包含 XXXXXX" -#: glib/gfileutils.c:2318 glib/gfileutils.c:2347 +#: glib/gfileutils.c:2310 glib/gfileutils.c:2339 #, c-format msgid "Failed to read the symbolic link “%s”: %s" msgstr "读取符号链接“%s”失败:%s" @@ -4894,99 +4893,99 @@ msgstr "通道终止于未尽字符" msgid "Can’t do a raw read in g_io_channel_read_to_end" msgstr "g_io_channel_read_to_end 函数无法进行原始读取" -#: glib/gkeyfile.c:790 +#: glib/gkeyfile.c:789 msgid "Valid key file could not be found in search dirs" msgstr "在搜索目录中无法找到有效的键文件" -#: glib/gkeyfile.c:827 +#: glib/gkeyfile.c:826 msgid "Not a regular file" msgstr "不是普通文件" -#: glib/gkeyfile.c:1282 +#: glib/gkeyfile.c:1281 #, c-format msgid "" "Key file contains line “%s” which is not a key-value pair, group, or comment" msgstr "键文件包含不是键-值对、组或注释的行“%s”" -#: glib/gkeyfile.c:1339 +#: glib/gkeyfile.c:1338 #, c-format msgid "Invalid group name: %s" msgstr "无效的组名:%s" -#: glib/gkeyfile.c:1361 +#: glib/gkeyfile.c:1360 msgid "Key file does not start with a group" msgstr "键文件不以组开始" -#: glib/gkeyfile.c:1387 +#: glib/gkeyfile.c:1386 #, c-format msgid "Invalid key name: %s" msgstr "无效的键名:%s" -#: glib/gkeyfile.c:1414 +#: glib/gkeyfile.c:1413 #, c-format msgid "Key file contains unsupported encoding “%s”" msgstr "键文件包含不支持的编码“%s”" -#: glib/gkeyfile.c:1663 glib/gkeyfile.c:1836 glib/gkeyfile.c:3289 -#: glib/gkeyfile.c:3353 glib/gkeyfile.c:3483 glib/gkeyfile.c:3615 -#: glib/gkeyfile.c:3761 glib/gkeyfile.c:3996 glib/gkeyfile.c:4063 +#: glib/gkeyfile.c:1662 glib/gkeyfile.c:1835 glib/gkeyfile.c:3288 +#: glib/gkeyfile.c:3352 glib/gkeyfile.c:3482 glib/gkeyfile.c:3614 +#: glib/gkeyfile.c:3760 glib/gkeyfile.c:3995 glib/gkeyfile.c:4062 #, c-format msgid "Key file does not have group “%s”" msgstr "键文件没有组“%s”" -#: glib/gkeyfile.c:1791 +#: glib/gkeyfile.c:1790 #, c-format msgid "Key file does not have key “%s” in group “%s”" msgstr "键文件在组“%2$s”中没有键“%1$s”" -#: glib/gkeyfile.c:1953 glib/gkeyfile.c:2069 +#: glib/gkeyfile.c:1952 glib/gkeyfile.c:2068 #, c-format msgid "Key file contains key “%s” with value “%s” which is not UTF-8" msgstr "键文件包含键“%s”,其值“%s”不是 UTF-8" -#: glib/gkeyfile.c:1973 glib/gkeyfile.c:2089 glib/gkeyfile.c:2531 +#: glib/gkeyfile.c:1972 glib/gkeyfile.c:2088 glib/gkeyfile.c:2530 #, c-format msgid "" "Key file contains key “%s” which has a value that cannot be interpreted." msgstr "键文件包含键“%s”,其值无法解析。" -#: glib/gkeyfile.c:2749 glib/gkeyfile.c:3118 +#: glib/gkeyfile.c:2748 glib/gkeyfile.c:3117 #, c-format msgid "" "Key file contains key “%s” in group “%s” which has a value that cannot be " "interpreted." msgstr "键文件包含组“%2$s”中的键“%1$s”,其值无法解释。" -#: glib/gkeyfile.c:2827 glib/gkeyfile.c:2904 +#: glib/gkeyfile.c:2826 glib/gkeyfile.c:2903 #, c-format msgid "Key “%s” in group “%s” has value “%s” where %s was expected" msgstr "组“%2$s”中的键“%1$s”的值为“%3$s”,应为 %4$s" -#: glib/gkeyfile.c:4306 +#: glib/gkeyfile.c:4305 msgid "Key file contains escape character at end of line" msgstr "键文件在行尾含有转义字符" -#: glib/gkeyfile.c:4328 +#: glib/gkeyfile.c:4327 #, c-format msgid "Key file contains invalid escape sequence “%s”" msgstr "键文件中包含无效的转义序列“%s”" -#: glib/gkeyfile.c:4472 +#: glib/gkeyfile.c:4471 #, c-format msgid "Value “%s” cannot be interpreted as a number." msgstr "无法将值“%s”解释为数值。" -#: glib/gkeyfile.c:4486 +#: glib/gkeyfile.c:4485 #, c-format msgid "Integer value “%s” out of range" msgstr "整数值“%s”超出范围" -#: glib/gkeyfile.c:4519 +#: glib/gkeyfile.c:4518 #, c-format msgid "Value “%s” cannot be interpreted as a float number." msgstr "无法将值“%s”解释为浮点数。" -#: glib/gkeyfile.c:4558 +#: glib/gkeyfile.c:4557 #, c-format msgid "Value “%s” cannot be interpreted as a boolean." msgstr "无法将值“%s”解释为布尔值。" @@ -5009,7 +5008,7 @@ msgstr "打开文件“%s”失败:open() 失败:%s" #: glib/gmarkup.c:398 glib/gmarkup.c:440 #, c-format msgid "Error on line %d char %d: " -msgstr "第 %d 行第 %d 个字符出错:" +msgstr "第 %d 行第 %d 个字符出错: " #: glib/gmarkup.c:462 glib/gmarkup.c:545 #, c-format @@ -5248,12 +5247,12 @@ msgstr "%2$s 所用的双精度值“%1$s”超出范围" msgid "Error parsing option %s" msgstr "解析选项 %s 时出错" -#: glib/goption.c:1570 glib/goption.c:1683 +#: glib/goption.c:1561 glib/goption.c:1674 #, c-format msgid "Missing argument for %s" msgstr "缺少 %s 的参数" -#: glib/goption.c:2194 +#: glib/goption.c:2185 #, c-format msgid "Unknown option %s" msgstr "未知选项 %s" @@ -5645,82 +5644,82 @@ msgstr "在找到为 %c 匹配的引用之前,文本已结束。(文本为 msgid "Text was empty (or contained only whitespace)" msgstr "文本为空(或仅含空白字符)" -#: glib/gspawn.c:318 +#: glib/gspawn.c:308 #, c-format msgid "Failed to read data from child process (%s)" msgstr "从子进程中读取数据失败(%s)" -#: glib/gspawn.c:465 +#: glib/gspawn.c:455 #, c-format msgid "Unexpected error in reading data from a child process (%s)" msgstr "在从子进程中读取数据时出现异常错误(%s)" -#: glib/gspawn.c:550 +#: glib/gspawn.c:540 #, c-format msgid "Unexpected error in waitpid() (%s)" msgstr "waitpid() 出现异常错误(%s)" -#: glib/gspawn.c:1154 glib/gspawn-win32.c:1383 +#: glib/gspawn.c:1144 glib/gspawn-win32.c:1383 #, c-format msgid "Child process exited with code %ld" msgstr "子进程已退出,代码 %ld" -#: glib/gspawn.c:1162 +#: glib/gspawn.c:1152 #, c-format msgid "Child process killed by signal %ld" msgstr "子进程已由信号 %ld 杀死" -#: glib/gspawn.c:1169 +#: glib/gspawn.c:1159 #, c-format msgid "Child process stopped by signal %ld" msgstr "子进程已由信号 %ld 停止" -#: glib/gspawn.c:1176 +#: glib/gspawn.c:1166 #, c-format msgid "Child process exited abnormally" msgstr "子进程异常中止" -#: glib/gspawn.c:1767 glib/gspawn-win32.c:350 glib/gspawn-win32.c:358 +#: glib/gspawn.c:1757 glib/gspawn-win32.c:350 glib/gspawn-win32.c:358 #, c-format msgid "Failed to read from child pipe (%s)" msgstr "从子管道中读取失败(%s)" -#: glib/gspawn.c:2069 +#: glib/gspawn.c:2059 #, c-format msgid "Failed to spawn child process “%s” (%s)" msgstr "生成子进程“%s”失败(%s)" -#: glib/gspawn.c:2186 +#: glib/gspawn.c:2176 #, c-format msgid "Failed to fork (%s)" msgstr "fork 失败(%s)" -#: glib/gspawn.c:2346 glib/gspawn-win32.c:381 +#: glib/gspawn.c:2336 glib/gspawn-win32.c:381 #, c-format msgid "Failed to change to directory “%s” (%s)" msgstr "切换到目录“%s”失败(%s)" -#: glib/gspawn.c:2356 +#: glib/gspawn.c:2346 #, c-format msgid "Failed to execute child process “%s” (%s)" msgstr "执行子进程“%s”失败(%s)" -#: glib/gspawn.c:2366 +#: glib/gspawn.c:2356 #, c-format msgid "Failed to redirect output or input of child process (%s)" msgstr "重定位子进程(%s)的输入或输出失败" -#: glib/gspawn.c:2375 +#: glib/gspawn.c:2365 #, c-format msgid "Failed to fork child process (%s)" msgstr "fork 子进程失败(%s)" -#: glib/gspawn.c:2383 +#: glib/gspawn.c:2373 #, c-format msgid "Unknown error executing child process “%s”" msgstr "执行子进程“%s”时出现未知错误" -#: glib/gspawn.c:2407 +#: glib/gspawn.c:2397 #, c-format msgid "Failed to read enough data from child pid pipe (%s)" msgstr "从子进程管道中读取足够的数据失败(%s)" diff --git a/po/zh_TW.po b/po/zh_TW.po index 11eb59c35..dd7951f8a 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -10,17 +10,16 @@ msgid "" msgstr "" "Project-Id-Version: glib 2.64\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/glib/issues\n" -"POT-Creation-Date: 2021-03-27 11:34+0000\n" -"PO-Revision-Date: 2021-04-26 06:53+0000\n" -"Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n" -"Language-Team: Chinese (Traditional) <http://darkbear.ddns.net/projects/" -"gnome-40/glib-glib-2-68-zh_tw/zh_Hant/>\n" +"POT-Creation-Date: 2020-10-01 16:40+0000\n" +"PO-Revision-Date: 2020-10-12 22:54+0800\n" +"Last-Translator: Cheng-Chia Tseng <pswo10680@gmail.com>\n" +"Language-Team: Chinese (Traditional) <zh-l10n@lists.linux.org.tw>\n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.6\n" +"X-Generator: Poedit 2.4.1\n" #: gio/gapplication.c:500 msgid "GApplication options" @@ -59,90 +58,90 @@ msgstr "顯示版本" msgid "Print version information and exit" msgstr "輸出版本資訊並離開" -#: gio/gapplication-tool.c:53 +#: gio/gapplication-tool.c:52 msgid "List applications" msgstr "列出應用程式" -#: gio/gapplication-tool.c:54 +#: gio/gapplication-tool.c:53 msgid "List the installed D-Bus activatable applications (by .desktop files)" msgstr "列出已安裝可使用 D-Bus 的應用程式 (依 .desktop 檔案)" -#: gio/gapplication-tool.c:57 +#: gio/gapplication-tool.c:55 msgid "Launch an application" msgstr "執行應用程式" -#: gio/gapplication-tool.c:58 +#: gio/gapplication-tool.c:56 msgid "Launch the application (with optional files to open)" msgstr "執行應用程式 (選擇性加上要開啟的檔案)" -#: gio/gapplication-tool.c:59 +#: gio/gapplication-tool.c:57 msgid "APPID [FILE…]" msgstr "APPID [FILE...]" -#: gio/gapplication-tool.c:61 +#: gio/gapplication-tool.c:59 msgid "Activate an action" msgstr "讓動作生效" -#: gio/gapplication-tool.c:62 +#: gio/gapplication-tool.c:60 msgid "Invoke an action on the application" msgstr "呼叫應用程式的動作" -#: gio/gapplication-tool.c:63 +#: gio/gapplication-tool.c:61 msgid "APPID ACTION [PARAMETER]" msgstr "APPID ACTION [PARAMETER]" -#: gio/gapplication-tool.c:65 +#: gio/gapplication-tool.c:63 msgid "List available actions" msgstr "列出可用的動作" -#: gio/gapplication-tool.c:66 +#: gio/gapplication-tool.c:64 msgid "List static actions for an application (from .desktop file)" msgstr "列出應用程式的靜態動作 (從 .desktop 檔案)" -#: gio/gapplication-tool.c:67 gio/gapplication-tool.c:73 +#: gio/gapplication-tool.c:65 gio/gapplication-tool.c:71 msgid "APPID" msgstr "APPID" -#: gio/gapplication-tool.c:72 gio/gapplication-tool.c:135 gio/gdbus-tool.c:106 +#: gio/gapplication-tool.c:70 gio/gapplication-tool.c:133 gio/gdbus-tool.c:102 #: gio/gio-tool.c:224 msgid "COMMAND" msgstr "指令" -#: gio/gapplication-tool.c:72 +#: gio/gapplication-tool.c:70 msgid "The command to print detailed help for" msgstr "顯示詳細求助的指令" -#: gio/gapplication-tool.c:73 +#: gio/gapplication-tool.c:71 msgid "Application identifier in D-Bus format (eg: org.example.viewer)" msgstr "D-Bus 格式的應用程式識別碼(例如:org.example.viewer)" -#: gio/gapplication-tool.c:74 gio/glib-compile-resources.c:738 +#: gio/gapplication-tool.c:72 gio/glib-compile-resources.c:738 #: gio/glib-compile-resources.c:744 gio/glib-compile-resources.c:772 #: gio/gresource-tool.c:500 gio/gresource-tool.c:566 msgid "FILE" msgstr "FILE" -#: gio/gapplication-tool.c:74 +#: gio/gapplication-tool.c:72 msgid "Optional relative or absolute filenames, or URIs to open" msgstr "選擇性相對或絕對的檔案名稱,或要開啟的 URI" -#: gio/gapplication-tool.c:75 +#: gio/gapplication-tool.c:73 msgid "ACTION" msgstr "動作" -#: gio/gapplication-tool.c:75 +#: gio/gapplication-tool.c:73 msgid "The action name to invoke" msgstr "要呼叫的動作名稱" -#: gio/gapplication-tool.c:76 +#: gio/gapplication-tool.c:74 msgid "PARAMETER" msgstr "參數" -#: gio/gapplication-tool.c:76 +#: gio/gapplication-tool.c:74 msgid "Optional parameter to the action invocation, in GVariant format" msgstr "動作呼叫時選擇性的參數,以 GVariant 格式" -#: gio/gapplication-tool.c:98 gio/gresource-tool.c:531 gio/gsettings-tool.c:659 +#: gio/gapplication-tool.c:96 gio/gresource-tool.c:531 gio/gsettings-tool.c:659 #, c-format msgid "" "Unknown command %s\n" @@ -151,26 +150,26 @@ msgstr "" "不明指令 %s\n" "\n" -#: gio/gapplication-tool.c:103 +#: gio/gapplication-tool.c:101 msgid "Usage:\n" msgstr "用法:\n" -#: gio/gapplication-tool.c:116 gio/gresource-tool.c:556 +#: gio/gapplication-tool.c:114 gio/gresource-tool.c:556 #: gio/gsettings-tool.c:694 msgid "Arguments:\n" msgstr "引數:\n" -#: gio/gapplication-tool.c:135 gio/gio-tool.c:224 +#: gio/gapplication-tool.c:133 gio/gio-tool.c:224 msgid "[ARGS…]" msgstr "[ARGS...]" -#: gio/gapplication-tool.c:136 +#: gio/gapplication-tool.c:134 #, c-format msgid "Commands:\n" msgstr "指令:\n" #. Translators: do not translate 'help', but please translate 'COMMAND'. -#: gio/gapplication-tool.c:148 +#: gio/gapplication-tool.c:146 #, c-format msgid "" "Use “%s help COMMAND” to get detailed help.\n" @@ -179,7 +178,7 @@ msgstr "" "使用「'%s help COMMAND」以取得詳細的求助。\n" "\n" -#: gio/gapplication-tool.c:167 +#: gio/gapplication-tool.c:165 #, c-format msgid "" "%s command requires an application id to directly follow\n" @@ -188,13 +187,13 @@ msgstr "" "%s 指令需要應用程式 id 直接跟隨\n" "\n" -#: gio/gapplication-tool.c:173 +#: gio/gapplication-tool.c:171 #, c-format msgid "invalid application id: “%s”\n" msgstr "無效的應用程式 id:「%s」\n" #. Translators: %s is replaced with a command name like 'list-actions' -#: gio/gapplication-tool.c:184 +#: gio/gapplication-tool.c:182 #, c-format msgid "" "“%s” takes no arguments\n" @@ -203,21 +202,21 @@ msgstr "" "「%s」不需要引數\n" "\n" -#: gio/gapplication-tool.c:268 +#: gio/gapplication-tool.c:266 #, c-format msgid "unable to connect to D-Bus: %s\n" msgstr "無法連接到 D-Bus:%s\n" -#: gio/gapplication-tool.c:288 +#: gio/gapplication-tool.c:286 #, c-format msgid "error sending %s message to application: %s\n" msgstr "傳送 %s 訊息到應用程式時發生錯誤:%s\n" -#: gio/gapplication-tool.c:319 +#: gio/gapplication-tool.c:317 msgid "action name must be given after application id\n" msgstr "動作名稱必須在應用程式 id 之後\n" -#: gio/gapplication-tool.c:327 +#: gio/gapplication-tool.c:325 #, c-format msgid "" "invalid action name: “%s”\n" @@ -226,25 +225,25 @@ msgstr "" "無效的動作名稱:「%s」\n" "動作名稱必須只由字母、「-」和「.」組成\n" -#: gio/gapplication-tool.c:346 +#: gio/gapplication-tool.c:344 #, c-format msgid "error parsing action parameter: %s\n" msgstr "解析動作參數時發生錯誤:%s\n" -#: gio/gapplication-tool.c:358 +#: gio/gapplication-tool.c:356 msgid "actions accept a maximum of one parameter\n" msgstr "動作最大只能接受一個參數\n" -#: gio/gapplication-tool.c:413 +#: gio/gapplication-tool.c:411 msgid "list-actions command takes only the application id" msgstr "list-actions 指令只接受應用程式 id" -#: gio/gapplication-tool.c:423 +#: gio/gapplication-tool.c:421 #, c-format msgid "unable to find desktop file for application %s\n" msgstr "無法找到應用程式的桌面檔案 %s\n" -#: gio/gapplication-tool.c:468 +#: gio/gapplication-tool.c:466 #, c-format msgid "" "unrecognised command: %s\n" @@ -254,8 +253,8 @@ msgstr "" "\n" #: gio/gbufferedinputstream.c:420 gio/gbufferedinputstream.c:498 -#: gio/ginputstream.c:179 gio/ginputstream.c:379 gio/ginputstream.c:646 -#: gio/ginputstream.c:1048 gio/goutputstream.c:223 gio/goutputstream.c:1049 +#: gio/ginputstream.c:179 gio/ginputstream.c:379 gio/ginputstream.c:617 +#: gio/ginputstream.c:1019 gio/goutputstream.c:223 gio/goutputstream.c:1049 #: gio/gpollableinputstream.c:205 gio/gpollableoutputstream.c:277 #, c-format msgid "Too large count value passed to %s" @@ -266,11 +265,11 @@ msgstr "傳給 %s 的計數值太大" msgid "Seek not supported on base stream" msgstr "不支援在基礎串流中搜尋" -#: gio/gbufferedinputstream.c:938 +#: gio/gbufferedinputstream.c:937 msgid "Cannot truncate GBufferedInputStream" msgstr "不能截短 GBufferedInputStream" -#: gio/gbufferedinputstream.c:983 gio/ginputstream.c:1237 gio/giostream.c:300 +#: gio/gbufferedinputstream.c:982 gio/ginputstream.c:1208 gio/giostream.c:300 #: gio/goutputstream.c:2198 msgid "Stream is already closed" msgstr "串流已經關閉" @@ -279,7 +278,7 @@ msgstr "串流已經關閉" msgid "Truncate not supported on base stream" msgstr "在基礎串流中不支援截短(truncate)" -#: gio/gcancellable.c:319 gio/gdbusconnection.c:1872 gio/gdbusprivate.c:1416 +#: gio/gcancellable.c:319 gio/gdbusconnection.c:1862 gio/gdbusprivate.c:1413 #: gio/gsimpleasyncresult.c:871 gio/gsimpleasyncresult.c:897 #, c-format msgid "Operation was cancelled" @@ -298,23 +297,23 @@ msgid "Not enough space in destination" msgstr "在目的端中沒有足夠的空間" #: gio/gcharsetconverter.c:342 gio/gdatainputstream.c:848 -#: gio/gdatainputstream.c:1266 glib/gconvert.c:448 glib/gconvert.c:878 -#: glib/giochannel.c:1573 glib/giochannel.c:1615 glib/giochannel.c:2470 +#: gio/gdatainputstream.c:1261 glib/gconvert.c:448 glib/gconvert.c:878 +#: glib/giochannel.c:1564 glib/giochannel.c:1606 glib/giochannel.c:2461 #: glib/gutf8.c:875 glib/gutf8.c:1328 msgid "Invalid byte sequence in conversion input" msgstr "轉換輸入資料時遇到不正確的位元組組合" #: gio/gcharsetconverter.c:347 glib/gconvert.c:456 glib/gconvert.c:792 -#: glib/giochannel.c:1580 glib/giochannel.c:2482 +#: glib/giochannel.c:1571 glib/giochannel.c:2473 #, c-format msgid "Error during conversion: %s" msgstr "轉換時發生錯誤:%s" -#: gio/gcharsetconverter.c:445 gio/gsocket.c:1143 +#: gio/gcharsetconverter.c:445 gio/gsocket.c:1133 msgid "Cancellable initialization not supported" msgstr "不支援可取消的初始化" -#: gio/gcharsetconverter.c:456 glib/gconvert.c:321 glib/giochannel.c:1401 +#: gio/gcharsetconverter.c:456 glib/gconvert.c:321 glib/giochannel.c:1392 #, c-format msgid "Conversion from character set “%s” to “%s” is not supported" msgstr "不支援將字元集「%s」轉換成「%s」" @@ -324,7 +323,7 @@ msgstr "不支援將字元集「%s」轉換成「%s」" msgid "Could not open converter from “%s” to “%s”" msgstr "無法開啟「%s」至「%s」的轉換" -#: gio/gcontenttype.c:454 +#: gio/gcontenttype.c:452 #, c-format msgid "%s type" msgstr "%s 類型" @@ -362,152 +361,152 @@ msgstr "在這個 OS 無法做到憑證偽裝" msgid "Unexpected early end-of-stream" msgstr "未預期的串流過早結束" -#: gio/gdbusaddress.c:159 gio/gdbusaddress.c:233 gio/gdbusaddress.c:322 +#: gio/gdbusaddress.c:158 gio/gdbusaddress.c:232 gio/gdbusaddress.c:321 #, c-format msgid "Unsupported key “%s” in address entry “%s”" msgstr "「%2$s」位址條目有不支援的「%1$s」鍵" -#: gio/gdbusaddress.c:172 +#: gio/gdbusaddress.c:171 #, c-format msgid "Meaningless key/value pair combination in address entry “%s”" msgstr "在「%s」位址條目中有無意義的鍵/值組合配對" -#: gio/gdbusaddress.c:181 +#: gio/gdbusaddress.c:180 #, c-format msgid "" "Address “%s” is invalid (need exactly one of path, dir, tmpdir, or abstract " "keys)" msgstr "「%s」位址無效 (需要有明確的 path、dir、tmpdir 或 abstract 鍵之一)" -#: gio/gdbusaddress.c:248 gio/gdbusaddress.c:259 gio/gdbusaddress.c:274 -#: gio/gdbusaddress.c:337 gio/gdbusaddress.c:348 +#: gio/gdbusaddress.c:247 gio/gdbusaddress.c:258 gio/gdbusaddress.c:273 +#: gio/gdbusaddress.c:336 gio/gdbusaddress.c:347 #, c-format msgid "Error in address “%s” — the “%s” attribute is malformed" msgstr "「%s」位址有錯誤 —「%s」特性的格式不良" -#: gio/gdbusaddress.c:418 gio/gdbusaddress.c:682 +#: gio/gdbusaddress.c:417 gio/gdbusaddress.c:681 #, c-format msgid "Unknown or unsupported transport “%s” for address “%s”" msgstr "「%2$s」位址有不明或不支援的「%1$s」傳輸" -#: gio/gdbusaddress.c:462 +#: gio/gdbusaddress.c:461 #, c-format msgid "Address element “%s” does not contain a colon (:)" msgstr "「%s」位址元素中並未包含分號 (:)" -#: gio/gdbusaddress.c:471 +#: gio/gdbusaddress.c:470 #, c-format msgid "Transport name in address element “%s” must not be empty" msgstr "「%s」位址元素中的傳輸名稱不能空白" -#: gio/gdbusaddress.c:492 +#: gio/gdbusaddress.c:491 #, c-format msgid "" "Key/Value pair %d, “%s”, in address element “%s” does not contain an equal " "sign" msgstr "在鍵/值配對 %d,「%s」,「%s」位址元素中,並未包含等於符號" -#: gio/gdbusaddress.c:503 +#: gio/gdbusaddress.c:502 #, c-format msgid "" "Key/Value pair %d, “%s”, in address element “%s” must not have an empty key" msgstr "在鍵/值配對 %d,「%s」,「%s」位址元素中,不能有空白的鍵" -#: gio/gdbusaddress.c:517 +#: gio/gdbusaddress.c:516 #, c-format msgid "" "Error unescaping key or value in Key/Value pair %d, “%s”, in address element " "“%s”" msgstr "在鍵/值配對 %d,「%s」,「%s」位址元素中有錯誤的反轉義鍵" -#: gio/gdbusaddress.c:589 +#: gio/gdbusaddress.c:588 #, c-format msgid "" "Error in address “%s” — the unix transport requires exactly one of the keys " "“path” or “abstract” to be set" msgstr "「%s」位址有錯誤 — unix 傳輸需要明確的設定一個「path」或「abstract」鍵" -#: gio/gdbusaddress.c:625 +#: gio/gdbusaddress.c:624 #, c-format msgid "Error in address “%s” — the host attribute is missing or malformed" msgstr "「%s」位址有錯誤 — host 特性遺失或格式不良" -#: gio/gdbusaddress.c:639 +#: gio/gdbusaddress.c:638 #, c-format msgid "Error in address “%s” — the port attribute is missing or malformed" msgstr "「%s」位址有錯誤 — port 特性遺失或格式不良" -#: gio/gdbusaddress.c:653 +#: gio/gdbusaddress.c:652 #, c-format msgid "Error in address “%s” — the noncefile attribute is missing or malformed" msgstr "「%s」位址有錯誤 — noncefile 特性遺失或格式不良" -#: gio/gdbusaddress.c:674 +#: gio/gdbusaddress.c:673 msgid "Error auto-launching: " msgstr "自動執行失敗:" -#: gio/gdbusaddress.c:727 +#: gio/gdbusaddress.c:726 #, c-format msgid "Error opening nonce file “%s”: %s" msgstr "開啟臨時檔案「%s」時發生錯誤:%s" -#: gio/gdbusaddress.c:746 +#: gio/gdbusaddress.c:745 #, c-format msgid "Error reading from nonce file “%s”: %s" msgstr "讀取臨時檔案「%s」時發生錯誤:%s" -#: gio/gdbusaddress.c:755 +#: gio/gdbusaddress.c:754 #, c-format msgid "Error reading from nonce file “%s”, expected 16 bytes, got %d" msgstr "讀取臨時檔案「%s」時發生錯誤,預期為 16 位元組,卻得到 %d" -#: gio/gdbusaddress.c:773 +#: gio/gdbusaddress.c:772 #, c-format msgid "Error writing contents of nonce file “%s” to stream:" msgstr "寫入臨時檔案「%s」的內容到串流時發生錯誤:" -#: gio/gdbusaddress.c:988 +#: gio/gdbusaddress.c:981 msgid "The given address is empty" msgstr "指定的位址是空白的" -#: gio/gdbusaddress.c:1101 +#: gio/gdbusaddress.c:1094 #, c-format msgid "Cannot spawn a message bus when setuid" msgstr "在 setuid 時不能產生訊息匯流排" -#: gio/gdbusaddress.c:1108 +#: gio/gdbusaddress.c:1101 msgid "Cannot spawn a message bus without a machine-id: " msgstr "沒有 machine-id 不能產生訊息匯流排:" -#: gio/gdbusaddress.c:1115 +#: gio/gdbusaddress.c:1108 #, c-format msgid "Cannot autolaunch D-Bus without X11 $DISPLAY" msgstr "沒有 X11 $DISPLAY 不能自動執行 D-Bus " -#: gio/gdbusaddress.c:1157 +#: gio/gdbusaddress.c:1150 #, c-format msgid "Error spawning command line “%s”: " msgstr "產生命令列「%s」時出現錯誤:" -#: gio/gdbusaddress.c:1226 +#: gio/gdbusaddress.c:1219 #, c-format msgid "Cannot determine session bus address (not implemented for this OS)" msgstr "不能判斷作業階段匯流排位址(沒有在這個 OS 實作)" -#: gio/gdbusaddress.c:1397 gio/gdbusconnection.c:7241 +#: gio/gdbusaddress.c:1357 gio/gdbusconnection.c:7192 #, c-format msgid "" "Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment variable " "— unknown value “%s”" msgstr "不能從 DBUS_STARTER_BUS_TYPE 環境變數判斷匯流排位址 — 不明的「%s」值" -#: gio/gdbusaddress.c:1406 gio/gdbusconnection.c:7250 +#: gio/gdbusaddress.c:1366 gio/gdbusconnection.c:7201 msgid "" "Cannot determine bus address because the DBUS_STARTER_BUS_TYPE environment " "variable is not set" msgstr "不能判斷匯流排位址,因為尚未設定 DBUS_STARTER_BUS_TYPE 環境變數" -#: gio/gdbusaddress.c:1416 +#: gio/gdbusaddress.c:1376 #, c-format msgid "Unknown bus type %d" msgstr "不明的匯流排類型 %d" @@ -526,232 +525,218 @@ msgid "" "Exhausted all available authentication mechanisms (tried: %s) (available: %s)" msgstr "竭盡所有可用的核對機制 (已嘗試:%s) (可用:%s)" -#: gio/gdbusauth.c:1170 -msgid "User IDs must be the same for peer and server" -msgstr "對等端和伺服器端的使用者 ID 必須相同" - -#: gio/gdbusauth.c:1182 +#: gio/gdbusauth.c:1167 msgid "Cancelled via GDBusAuthObserver::authorize-authenticated-peer" msgstr "已透過 GDBusAuthObserver::authorize-authenticated-peer 取消" -#: gio/gdbusauthmechanismsha1.c:298 +#: gio/gdbusauthmechanismsha1.c:296 #, c-format msgid "Error when getting information for directory “%s”: %s" msgstr "從目錄「%s」取得資訊時發生錯誤:%s" -#: gio/gdbusauthmechanismsha1.c:313 +#: gio/gdbusauthmechanismsha1.c:311 #, c-format msgid "" "Permissions on directory “%s” are malformed. Expected mode 0700, got 0%o" -msgstr "目錄「%s」的權限格式不良。預期的模式為 0700,卻得到 0%o" +msgstr "目錄「%s」的權限格式下良。預期的模式為 0700,卻得到 0%o" -#: gio/gdbusauthmechanismsha1.c:346 gio/gdbusauthmechanismsha1.c:357 +#: gio/gdbusauthmechanismsha1.c:341 #, c-format msgid "Error creating directory “%s”: %s" msgstr "建立目錄「%s」時發生錯誤:%s" -#: gio/gdbusauthmechanismsha1.c:359 gio/gfile.c:1062 gio/gfile.c:1300 -#: gio/gfile.c:1438 gio/gfile.c:1676 gio/gfile.c:1731 gio/gfile.c:1789 -#: gio/gfile.c:1873 gio/gfile.c:1930 gio/gfile.c:1994 gio/gfile.c:2049 -#: gio/gfile.c:3754 gio/gfile.c:3809 gio/gfile.c:4102 gio/gfile.c:4572 -#: gio/gfile.c:4983 gio/gfile.c:5068 gio/gfile.c:5158 gio/gfile.c:5255 -#: gio/gfile.c:5342 gio/gfile.c:5443 gio/gfile.c:8153 gio/gfile.c:8243 -#: gio/gfile.c:8327 gio/win32/gwinhttpfile.c:453 -msgid "Operation not supported" -msgstr "不支援的操作" - -#: gio/gdbusauthmechanismsha1.c:402 +#: gio/gdbusauthmechanismsha1.c:386 #, c-format msgid "Error opening keyring “%s” for reading: " msgstr "開啟鑰匙圈「%s」讀取時發生錯誤:" -#: gio/gdbusauthmechanismsha1.c:425 gio/gdbusauthmechanismsha1.c:747 +#: gio/gdbusauthmechanismsha1.c:409 gio/gdbusauthmechanismsha1.c:731 #, c-format msgid "Line %d of the keyring at “%s” with content “%s” is malformed" msgstr "位於「%2$s」內容「%3$s」的鑰匙圈第 %1$d 列格式不良" -#: gio/gdbusauthmechanismsha1.c:439 gio/gdbusauthmechanismsha1.c:761 +#: gio/gdbusauthmechanismsha1.c:423 gio/gdbusauthmechanismsha1.c:745 #, c-format msgid "" "First token of line %d of the keyring at “%s” with content “%s” is malformed" msgstr "位於「%2$s」內容「%3$s」的鑰匙圈第 %1$d 列第一記號格式不良" -#: gio/gdbusauthmechanismsha1.c:453 gio/gdbusauthmechanismsha1.c:775 +#: gio/gdbusauthmechanismsha1.c:437 gio/gdbusauthmechanismsha1.c:759 #, c-format msgid "" "Second token of line %d of the keyring at “%s” with content “%s” is malformed" msgstr "位於「%2$s」內容「%3$s」的鑰匙圈第 %1$d 列第二記號格式不良" -#: gio/gdbusauthmechanismsha1.c:477 +#: gio/gdbusauthmechanismsha1.c:461 #, c-format msgid "Didn’t find cookie with id %d in the keyring at “%s”" msgstr "在「%2$s」鑰匙圈找不到 id %1$d 的 cookie" -#: gio/gdbusauthmechanismsha1.c:523 +#: gio/gdbusauthmechanismsha1.c:507 #, c-format msgid "Error creating lock file “%s”: %s" msgstr "建立鎖定檔案「%s」時發生錯誤:%s" -#: gio/gdbusauthmechanismsha1.c:587 +#: gio/gdbusauthmechanismsha1.c:571 #, c-format msgid "Error deleting stale lock file “%s”: %s" msgstr "刪除舊的鎖定檔案「%s」時發生錯誤:%s" -#: gio/gdbusauthmechanismsha1.c:626 +#: gio/gdbusauthmechanismsha1.c:610 #, c-format msgid "Error closing (unlinked) lock file “%s”: %s" msgstr "關閉 (取消連結) 鎖定檔案時發生錯誤「%s」:%s" -#: gio/gdbusauthmechanismsha1.c:637 +#: gio/gdbusauthmechanismsha1.c:621 #, c-format msgid "Error unlinking lock file “%s”: %s" msgstr "取消連結鎖定檔案時發生錯誤「%s」:%s" -#: gio/gdbusauthmechanismsha1.c:714 +#: gio/gdbusauthmechanismsha1.c:698 #, c-format msgid "Error opening keyring “%s” for writing: " msgstr "開啟鑰匙圈「%s」寫入時發生錯誤:" -#: gio/gdbusauthmechanismsha1.c:908 +#: gio/gdbusauthmechanismsha1.c:892 #, c-format msgid "(Additionally, releasing the lock for “%s” also failed: %s) " msgstr "(另外,釋放「%s」的鎖定失敗:%s)" -#: gio/gdbusconnection.c:603 gio/gdbusconnection.c:2405 +#: gio/gdbusconnection.c:595 gio/gdbusconnection.c:2391 msgid "The connection is closed" msgstr "這個連線已關閉" -#: gio/gdbusconnection.c:1902 +#: gio/gdbusconnection.c:1892 msgid "Timeout was reached" msgstr "已達逾時時間" -#: gio/gdbusconnection.c:2528 +#: gio/gdbusconnection.c:2513 msgid "" "Unsupported flags encountered when constructing a client-side connection" msgstr "當建立客戶端連線時遇到不支援的旗標" -#: gio/gdbusconnection.c:4186 gio/gdbusconnection.c:4533 +#: gio/gdbusconnection.c:4163 gio/gdbusconnection.c:4510 #, c-format msgid "" "No such interface “org.freedesktop.DBus.Properties” on object at path %s" msgstr "在 %s 路徑的物件沒有「org.freedesktop.DBus.Properties」這個介面" -#: gio/gdbusconnection.c:4328 +#: gio/gdbusconnection.c:4305 #, c-format msgid "No such property “%s”" msgstr "沒有這個屬性「%s」" -#: gio/gdbusconnection.c:4340 +#: gio/gdbusconnection.c:4317 #, c-format msgid "Property “%s” is not readable" msgstr "無法讀取「%s」屬性" -#: gio/gdbusconnection.c:4351 +#: gio/gdbusconnection.c:4328 #, c-format msgid "Property “%s” is not writable" msgstr "無法寫入「%s」屬性" -#: gio/gdbusconnection.c:4371 +#: gio/gdbusconnection.c:4348 #, c-format msgid "Error setting property “%s”: Expected type “%s” but got “%s”" msgstr "「%s」屬性設定錯誤:預期的類型為「%s」但得到「%s」" -#: gio/gdbusconnection.c:4476 gio/gdbusconnection.c:4684 -#: gio/gdbusconnection.c:6681 +#: gio/gdbusconnection.c:4453 gio/gdbusconnection.c:4661 +#: gio/gdbusconnection.c:6632 #, c-format msgid "No such interface “%s”" msgstr "沒有這個「%s」介面" -#: gio/gdbusconnection.c:4902 gio/gdbusconnection.c:7190 +#: gio/gdbusconnection.c:4879 gio/gdbusconnection.c:7141 #, c-format msgid "No such interface “%s” on object at path %s" msgstr "在 %2$s 路徑的物件沒有「%1$s」這個介面" -#: gio/gdbusconnection.c:5000 +#: gio/gdbusconnection.c:4977 #, c-format msgid "No such method “%s”" msgstr "沒有「%s」方法" -#: gio/gdbusconnection.c:5031 +#: gio/gdbusconnection.c:5008 #, c-format msgid "Type of message, “%s”, does not match expected type “%s”" msgstr "訊息的類型,「%s」,不符合預期的類型「%s」" -#: gio/gdbusconnection.c:5229 +#: gio/gdbusconnection.c:5206 #, c-format msgid "An object is already exported for the interface %s at %s" msgstr "有物件已為介面 %s 匯出於 %s" -#: gio/gdbusconnection.c:5455 +#: gio/gdbusconnection.c:5432 #, c-format msgid "Unable to retrieve property %s.%s" msgstr "無法取回屬性 %s.%s" -#: gio/gdbusconnection.c:5511 +#: gio/gdbusconnection.c:5488 #, c-format msgid "Unable to set property %s.%s" msgstr "無法設定屬性 %s.%s" -#: gio/gdbusconnection.c:5690 +#: gio/gdbusconnection.c:5666 #, c-format msgid "Method “%s” returned type “%s”, but expected “%s”" msgstr "方法「%s」傳回類型「%s」,但預期為「%s」" -#: gio/gdbusconnection.c:6792 +#: gio/gdbusconnection.c:6743 #, c-format msgid "Method “%s” on interface “%s” with signature “%s” does not exist" msgstr "介面「%2$s」簽章「%3$s」的方法「%1$s」不存在" -#: gio/gdbusconnection.c:6913 +#: gio/gdbusconnection.c:6864 #, c-format msgid "A subtree is already exported for %s" msgstr "子樹狀目錄已為 %s 匯出" -#: gio/gdbusmessage.c:1266 +#: gio/gdbusmessage.c:1255 msgid "type is INVALID" msgstr "類型為無效" -#: gio/gdbusmessage.c:1277 +#: gio/gdbusmessage.c:1266 msgid "METHOD_CALL message: PATH or MEMBER header field is missing" msgstr "METHOD_CALL 訊息:缺少 PATH 或 MEMBER 標頭欄位" -#: gio/gdbusmessage.c:1288 +#: gio/gdbusmessage.c:1277 msgid "METHOD_RETURN message: REPLY_SERIAL header field is missing" msgstr "METHOD_RETURN 訊息:缺少 REPLY_SERIAL 標頭欄位" -#: gio/gdbusmessage.c:1300 +#: gio/gdbusmessage.c:1289 msgid "ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing" msgstr "ERROR 訊息:缺少 REPLY_SERIAL 或 ERROR_NAME 標頭欄位" -#: gio/gdbusmessage.c:1313 +#: gio/gdbusmessage.c:1302 msgid "SIGNAL message: PATH, INTERFACE or MEMBER header field is missing" msgstr "SIGNAL 訊息:缺少 PATH、INTERFACE 或 MEMBER 標頭欄位" -#: gio/gdbusmessage.c:1321 +#: gio/gdbusmessage.c:1310 msgid "" "SIGNAL message: The PATH header field is using the reserved value /org/" "freedesktop/DBus/Local" msgstr "SIGNAL 訊息:PATH 標頭欄位使用了保留的值 /org/freedesktop/DBus/Local" -#: gio/gdbusmessage.c:1329 +#: gio/gdbusmessage.c:1318 msgid "" "SIGNAL message: The INTERFACE header field is using the reserved value org." "freedesktop.DBus.Local" msgstr "" "SIGNAL 訊息:INTERFACE 標頭欄位使用了保留的值 org.freedesktop.DBus.Local" -#: gio/gdbusmessage.c:1377 gio/gdbusmessage.c:1437 +#: gio/gdbusmessage.c:1366 gio/gdbusmessage.c:1426 #, c-format msgid "Wanted to read %lu byte but only got %lu" msgid_plural "Wanted to read %lu bytes but only got %lu" msgstr[0] "嘗試讀取 %lu 位元組卻只得到 %lu" -#: gio/gdbusmessage.c:1391 +#: gio/gdbusmessage.c:1380 #, c-format msgid "Expected NUL byte after the string “%s” but found byte %d" msgstr "預期在字串「%s」之後為 NUL 位元組,但是發現位元組 %d" -#: gio/gdbusmessage.c:1410 +#: gio/gdbusmessage.c:1399 #, c-format msgid "" "Expected valid UTF-8 string but found invalid bytes at byte offset %d " @@ -760,21 +745,21 @@ msgstr "" "預期為有效的 UTF-8 字串但是在位元組 %d 處發現無效的位元組 (字串的長度為 %d)。" "到那一點之前的有效 UTF-8 字串為「%s」" -#: gio/gdbusmessage.c:1474 gio/gdbusmessage.c:1722 gio/gdbusmessage.c:1911 +#: gio/gdbusmessage.c:1463 gio/gdbusmessage.c:1711 gio/gdbusmessage.c:1900 msgid "Value nested too deeply" msgstr "值的巢狀層次過深" -#: gio/gdbusmessage.c:1620 +#: gio/gdbusmessage.c:1609 #, c-format msgid "Parsed value “%s” is not a valid D-Bus object path" msgstr "已解析「%s」值不是有效的 D-Bus 物件路徑" -#: gio/gdbusmessage.c:1642 +#: gio/gdbusmessage.c:1631 #, c-format msgid "Parsed value “%s” is not a valid D-Bus signature" msgstr "已解析「%s」值不是一個有效的 D-Bus 簽章" -#: gio/gdbusmessage.c:1689 +#: gio/gdbusmessage.c:1678 #, c-format msgid "" "Encountered array of length %u byte. Maximum length is 2<<26 bytes (64 MiB)." @@ -782,7 +767,7 @@ msgid_plural "" "Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB)." msgstr[0] "遇到長度為 %u 位元組的陣列。最大長度為 2<<26 位元組 (64 MiB)。" -#: gio/gdbusmessage.c:1709 +#: gio/gdbusmessage.c:1698 #, c-format msgid "" "Encountered array of type “a%c”, expected to have a length a multiple of %u " @@ -790,115 +775,113 @@ msgid "" msgstr "" "遇到類型「a%c」的陣列,預期長度應為 %u 位元組的倍數,但發現長度為 %u 位元組" -#: gio/gdbusmessage.c:1895 +#: gio/gdbusmessage.c:1884 #, c-format msgid "Parsed value “%s” for variant is not a valid D-Bus signature" msgstr "已解析「%s」值不是有效的 D-Bus 簽章" -#: gio/gdbusmessage.c:1936 +#: gio/gdbusmessage.c:1925 #, c-format msgid "" "Error deserializing GVariant with type string “%s” from the D-Bus wire format" msgstr "從 D-Bus 線性格式以類型字串「%s」反序列化 GVariant 時發生錯誤" -#: gio/gdbusmessage.c:2121 +#: gio/gdbusmessage.c:2110 #, c-format msgid "" "Invalid endianness value. Expected 0x6c (“l”) or 0x42 (“B”) but found value " "0x%02x" msgstr "無效的字節順序值。預期為 0x6c (「I」) 或 0x42 (「B」) 卻得到值 0x%02x" -#: gio/gdbusmessage.c:2134 +#: gio/gdbusmessage.c:2123 #, c-format msgid "Invalid major protocol version. Expected 1 but found %d" msgstr "無效的主通訊協定版本。預期為 1 但找到 %d" -#: gio/gdbusmessage.c:2188 gio/gdbusmessage.c:2784 +#: gio/gdbusmessage.c:2177 gio/gdbusmessage.c:2773 msgid "Signature header found but is not of type signature" msgstr "找到簽章標頭,但不是一種類型簽章" -#: gio/gdbusmessage.c:2200 +#: gio/gdbusmessage.c:2189 #, c-format msgid "Signature header with signature “%s” found but message body is empty" msgstr "發現簽章「%s」的簽章標頭但訊息主體是空的" -#: gio/gdbusmessage.c:2215 +#: gio/gdbusmessage.c:2204 #, c-format msgid "Parsed value “%s” is not a valid D-Bus signature (for body)" msgstr "已解析「%s」值不是有效的 D-Bus 簽章 (於主體)" -#: gio/gdbusmessage.c:2247 +#: gio/gdbusmessage.c:2236 #, c-format msgid "No signature header in message but the message body is %u byte" msgid_plural "No signature header in message but the message body is %u bytes" msgstr[0] "在訊息中沒有簽章標頭但訊息主體有 %u 位元組" -#: gio/gdbusmessage.c:2257 +#: gio/gdbusmessage.c:2246 msgid "Cannot deserialize message: " msgstr "不能反序列化訊息:" -#: gio/gdbusmessage.c:2601 +#: gio/gdbusmessage.c:2590 #, c-format msgid "" "Error serializing GVariant with type string “%s” to the D-Bus wire format" msgstr "從 D-Bus 線性格式以類型字串「%s」序列化 GVariant 時發生錯誤" -#: gio/gdbusmessage.c:2738 +#: gio/gdbusmessage.c:2727 #, c-format msgid "" "Number of file descriptors in message (%d) differs from header field (%d)" msgstr "訊息 (%d) 中的檔案描述狀態數量跟標頭欄位 (%d) 的不同" -#: gio/gdbusmessage.c:2746 +#: gio/gdbusmessage.c:2735 msgid "Cannot serialize message: " msgstr "不能序列化訊息:" -#: gio/gdbusmessage.c:2799 +#: gio/gdbusmessage.c:2788 #, c-format msgid "Message body has signature “%s” but there is no signature header" msgstr "訊息主體有簽章「%s」但是沒有簽章標頭" -#: gio/gdbusmessage.c:2809 +#: gio/gdbusmessage.c:2798 #, c-format msgid "" "Message body has type signature “%s” but signature in the header field is " "“%s”" msgstr "訊息主體有類型簽章「%s」但是標頭欄位中的簽章為「%s」" -#: gio/gdbusmessage.c:2825 +#: gio/gdbusmessage.c:2814 #, c-format msgid "Message body is empty but signature in the header field is “(%s)”" msgstr "訊息主體是空的但是標頭欄位中的簽章為「%s」" -#: gio/gdbusmessage.c:3378 +#: gio/gdbusmessage.c:3367 #, c-format msgid "Error return with body of type “%s”" msgstr "傳回類型「%s」主體時發生錯誤" -#: gio/gdbusmessage.c:3386 +#: gio/gdbusmessage.c:3375 msgid "Error return with empty body" msgstr "傳回空白主體錯誤" -#: gio/gdbusprivate.c:2246 +#: gio/gdbusprivate.c:2244 #, c-format msgid "(Type any character to close this window)\n" msgstr "(輸入任何字元以關閉這個視窗)\n" -#: gio/gdbusprivate.c:2420 +#: gio/gdbusprivate.c:2418 #, c-format msgid "Session dbus not running, and autolaunch failed" msgstr "作業階段 dbus 尚未執行,且自動執行失敗" -#: gio/gdbusprivate.c:2443 +#: gio/gdbusprivate.c:2441 #, c-format msgid "Unable to get Hardware profile: %s" msgstr "無法取得硬體設定檔:%s" -#. Translators: Both placeholders are file paths -#: gio/gdbusprivate.c:2494 -#, c-format -msgid "Unable to load %s or %s: " -msgstr "無法載入 %s 或 %s︰ " +#: gio/gdbusprivate.c:2486 +msgid "Unable to load /var/lib/dbus/machine-id or /etc/machine-id: " +msgstr "無法載入 /var/lib/dbus/machine-id 或 /etc/machine-id:" #: gio/gdbusproxy.c:1562 #, c-format @@ -919,30 +902,30 @@ msgstr "" "不能呼叫方法;Proxy 是沒有擁有者的 %s 已知名稱,而 Proxy 以 " "G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START 旗標建構" -#: gio/gdbusserver.c:763 +#: gio/gdbusserver.c:755 msgid "Abstract namespace not supported" msgstr "不支援抽象命名空間" -#: gio/gdbusserver.c:856 +#: gio/gdbusserver.c:848 msgid "Cannot specify nonce file when creating a server" msgstr "當建立伺服器時不能指定臨時檔案" -#: gio/gdbusserver.c:938 +#: gio/gdbusserver.c:930 #, c-format msgid "Error writing nonce file at “%s”: %s" msgstr "在「%s」寫入臨時檔案時發生錯誤:%s" -#: gio/gdbusserver.c:1113 +#: gio/gdbusserver.c:1103 #, c-format msgid "The string “%s” is not a valid D-Bus GUID" msgstr "字串「%s」不是一個有效的 D-Bus GUID" -#: gio/gdbusserver.c:1153 +#: gio/gdbusserver.c:1143 #, c-format msgid "Cannot listen on unsupported transport “%s”" msgstr "不能聽取不支援的傳輸「%s」" -#: gio/gdbus-tool.c:111 +#: gio/gdbus-tool.c:107 #, c-format msgid "" "Commands:\n" @@ -965,288 +948,283 @@ msgstr "" " \n" "使用「%s COMMAND --help」來取得每個指令的求助資訊。\n" -#: gio/gdbus-tool.c:201 gio/gdbus-tool.c:273 gio/gdbus-tool.c:345 -#: gio/gdbus-tool.c:369 gio/gdbus-tool.c:859 gio/gdbus-tool.c:1236 -#: gio/gdbus-tool.c:1724 +#: gio/gdbus-tool.c:197 gio/gdbus-tool.c:264 gio/gdbus-tool.c:336 +#: gio/gdbus-tool.c:360 gio/gdbus-tool.c:850 gio/gdbus-tool.c:1187 +#: gio/gdbus-tool.c:1672 #, c-format msgid "Error: %s\n" msgstr "錯誤:%s\n" -#: gio/gdbus-tool.c:212 gio/gdbus-tool.c:286 gio/gdbus-tool.c:1740 +#: gio/gdbus-tool.c:208 gio/gdbus-tool.c:277 gio/gdbus-tool.c:1688 #, c-format msgid "Error parsing introspection XML: %s\n" msgstr "解析檢討 XML 時出現錯誤:%s\n" -#: gio/gdbus-tool.c:250 +#: gio/gdbus-tool.c:246 #, c-format msgid "Error: %s is not a valid name\n" msgstr "錯誤:%s 不是有效的名稱\n" -#: gio/gdbus-tool.c:255 gio/gdbus-tool.c:745 gio/gdbus-tool.c:1060 -#: gio/gdbus-tool.c:1890 gio/gdbus-tool.c:2130 -#, c-format -msgid "Error: %s is not a valid object path\n" -msgstr "錯誤:%s 不是有效的物件路徑\n" - -#: gio/gdbus-tool.c:403 +#: gio/gdbus-tool.c:394 msgid "Connect to the system bus" msgstr "連線到系統匯流排" -#: gio/gdbus-tool.c:404 +#: gio/gdbus-tool.c:395 msgid "Connect to the session bus" msgstr "連線到作業階段匯流排" -#: gio/gdbus-tool.c:405 +#: gio/gdbus-tool.c:396 msgid "Connect to given D-Bus address" msgstr "連線到指定的 D-Bus 位址" -#: gio/gdbus-tool.c:415 +#: gio/gdbus-tool.c:406 msgid "Connection Endpoint Options:" msgstr "連線端點選項:" -#: gio/gdbus-tool.c:416 +#: gio/gdbus-tool.c:407 msgid "Options specifying the connection endpoint" msgstr "指定連線端點的選項" -#: gio/gdbus-tool.c:439 +#: gio/gdbus-tool.c:430 #, c-format msgid "No connection endpoint specified" msgstr "沒有指定連線端點" -#: gio/gdbus-tool.c:449 +#: gio/gdbus-tool.c:440 #, c-format msgid "Multiple connection endpoints specified" msgstr "指定了多重連線端點" -#: gio/gdbus-tool.c:522 +#: gio/gdbus-tool.c:513 #, c-format msgid "" "Warning: According to introspection data, interface “%s” does not exist\n" msgstr "警告:根據檢討資料,介面「%s」不存在\n" -#: gio/gdbus-tool.c:531 +#: gio/gdbus-tool.c:522 #, c-format msgid "" "Warning: According to introspection data, method “%s” does not exist on " "interface “%s”\n" msgstr "警告:根據檢討資料,介面「%2$s」的方法「%1$s」不存在\n" -#: gio/gdbus-tool.c:593 +#: gio/gdbus-tool.c:584 msgid "Optional destination for signal (unique name)" msgstr "信號的選擇性目的端 (獨特名稱)" -#: gio/gdbus-tool.c:594 +#: gio/gdbus-tool.c:585 msgid "Object path to emit signal on" msgstr "要發出信號的物件路徑" -#: gio/gdbus-tool.c:595 +#: gio/gdbus-tool.c:586 msgid "Signal and interface name" msgstr "信號和介面名稱" -#: gio/gdbus-tool.c:628 +#: gio/gdbus-tool.c:619 msgid "Emit a signal." msgstr "發出信號。" -#: gio/gdbus-tool.c:683 gio/gdbus-tool.c:997 gio/gdbus-tool.c:1827 -#: gio/gdbus-tool.c:2059 gio/gdbus-tool.c:2279 +#: gio/gdbus-tool.c:674 gio/gdbus-tool.c:981 gio/gdbus-tool.c:1775 +#: gio/gdbus-tool.c:2007 gio/gdbus-tool.c:2227 #, c-format msgid "Error connecting: %s\n" msgstr "連線錯誤:%s\n" -#: gio/gdbus-tool.c:703 +#: gio/gdbus-tool.c:694 #, c-format msgid "Error: %s is not a valid unique bus name.\n" msgstr "錯誤:%s 不是有效的獨特匯流排名稱。\n" -#: gio/gdbus-tool.c:722 gio/gdbus-tool.c:1040 gio/gdbus-tool.c:1870 +#: gio/gdbus-tool.c:713 gio/gdbus-tool.c:1024 gio/gdbus-tool.c:1818 msgid "Error: Object path is not specified\n" msgstr "錯誤:沒有指定物件路徑\n" -#: gio/gdbus-tool.c:765 +#: gio/gdbus-tool.c:736 gio/gdbus-tool.c:1044 gio/gdbus-tool.c:1838 +#: gio/gdbus-tool.c:2078 +#, c-format +msgid "Error: %s is not a valid object path\n" +msgstr "錯誤:%s 不是有效的物件路徑\n" + +#: gio/gdbus-tool.c:756 msgid "Error: Signal name is not specified\n" msgstr "錯誤:沒有指定信號名稱\n" -#: gio/gdbus-tool.c:779 +#: gio/gdbus-tool.c:770 #, c-format msgid "Error: Signal name “%s” is invalid\n" msgstr "錯誤:「%s」信號名稱無效\n" -#: gio/gdbus-tool.c:791 +#: gio/gdbus-tool.c:782 #, c-format msgid "Error: %s is not a valid interface name\n" msgstr "錯誤:%s 不是有效的介面名稱\n" -#: gio/gdbus-tool.c:797 +#: gio/gdbus-tool.c:788 #, c-format msgid "Error: %s is not a valid member name\n" msgstr "錯誤:%s 不是有效的成員名稱\n" #. Use the original non-"parse-me-harder" error -#: gio/gdbus-tool.c:834 gio/gdbus-tool.c:1172 +#: gio/gdbus-tool.c:825 gio/gdbus-tool.c:1156 #, c-format msgid "Error parsing parameter %d: %s\n" msgstr "解析參數 %d 時發生錯誤:%s\n" -#: gio/gdbus-tool.c:866 +#: gio/gdbus-tool.c:857 #, c-format msgid "Error flushing connection: %s\n" msgstr "清除連線時發生錯誤:%s\n" -#: gio/gdbus-tool.c:893 +#: gio/gdbus-tool.c:884 msgid "Destination name to invoke method on" msgstr "要呼叫方法的目的端名稱" -#: gio/gdbus-tool.c:894 +#: gio/gdbus-tool.c:885 msgid "Object path to invoke method on" msgstr "要呼叫方法的物件路徑" -#: gio/gdbus-tool.c:895 +#: gio/gdbus-tool.c:886 msgid "Method and interface name" msgstr "方法和介面名稱" -#: gio/gdbus-tool.c:896 +#: gio/gdbus-tool.c:887 msgid "Timeout in seconds" msgstr "逾時時間(秒)" -#: gio/gdbus-tool.c:942 +#: gio/gdbus-tool.c:926 msgid "Invoke a method on a remote object." msgstr "呼叫遠端物件的方法。" -#: gio/gdbus-tool.c:1014 gio/gdbus-tool.c:1844 gio/gdbus-tool.c:2084 +#: gio/gdbus-tool.c:998 gio/gdbus-tool.c:1792 gio/gdbus-tool.c:2032 msgid "Error: Destination is not specified\n" msgstr "錯誤:尚未指定目的端\n" -#: gio/gdbus-tool.c:1025 gio/gdbus-tool.c:1861 gio/gdbus-tool.c:2095 +#: gio/gdbus-tool.c:1009 gio/gdbus-tool.c:1809 gio/gdbus-tool.c:2043 #, c-format msgid "Error: %s is not a valid bus name\n" msgstr "錯誤:%s 不是有效的匯流排名稱\n" -#: gio/gdbus-tool.c:1075 +#: gio/gdbus-tool.c:1059 msgid "Error: Method name is not specified\n" msgstr "錯誤:沒有指定方法名稱\n" -#: gio/gdbus-tool.c:1086 +#: gio/gdbus-tool.c:1070 #, c-format msgid "Error: Method name “%s” is invalid\n" msgstr "錯誤:方法名稱「%s」是無效的\n" -#: gio/gdbus-tool.c:1164 +#: gio/gdbus-tool.c:1148 #, c-format msgid "Error parsing parameter %d of type “%s”: %s\n" msgstr "解析類型「%2$s」的參數 %1$d 時發生錯誤:%3$s\n" -#: gio/gdbus-tool.c:1190 -#, c-format -msgid "Error adding handle %d: %s\n" -msgstr "加入處理程式 %d 時發生錯誤:%s\n" - -#: gio/gdbus-tool.c:1686 +#: gio/gdbus-tool.c:1634 msgid "Destination name to introspect" msgstr "要檢討的目的端名稱" -#: gio/gdbus-tool.c:1687 +#: gio/gdbus-tool.c:1635 msgid "Object path to introspect" msgstr "要檢討的物件路徑" -#: gio/gdbus-tool.c:1688 +#: gio/gdbus-tool.c:1636 msgid "Print XML" msgstr "顯示 XML" -#: gio/gdbus-tool.c:1689 +#: gio/gdbus-tool.c:1637 msgid "Introspect children" msgstr "Introspect 子項目" -#: gio/gdbus-tool.c:1690 +#: gio/gdbus-tool.c:1638 msgid "Only print properties" msgstr "只有列印特性" -#: gio/gdbus-tool.c:1779 +#: gio/gdbus-tool.c:1727 msgid "Introspect a remote object." msgstr "檢查遠端物件。" -#: gio/gdbus-tool.c:1985 +#: gio/gdbus-tool.c:1933 msgid "Destination name to monitor" msgstr "要監控的目的端名稱" -#: gio/gdbus-tool.c:1986 +#: gio/gdbus-tool.c:1934 msgid "Object path to monitor" msgstr "要監控的物件路徑" -#: gio/gdbus-tool.c:2011 +#: gio/gdbus-tool.c:1959 msgid "Monitor a remote object." msgstr "監控遠端物件。" -#: gio/gdbus-tool.c:2069 +#: gio/gdbus-tool.c:2017 msgid "Error: can’t monitor a non-message-bus connection\n" msgstr "錯誤:無法監控非訊息匯流排的連線\n" -#: gio/gdbus-tool.c:2193 +#: gio/gdbus-tool.c:2141 msgid "Service to activate before waiting for the other one (well-known name)" msgstr "在等待其他前要啟用的服務(已知名稱)" -#: gio/gdbus-tool.c:2196 +#: gio/gdbus-tool.c:2144 msgid "" "Timeout to wait for before exiting with an error (seconds); 0 for no timeout " "(default)" msgstr "發生錯誤結束前的等待逾時(秒);0 表示沒有逾時(預設值)" -#: gio/gdbus-tool.c:2244 +#: gio/gdbus-tool.c:2192 msgid "[OPTION…] BUS-NAME" msgstr "[OPTION…] BUS-NAME" -#: gio/gdbus-tool.c:2245 +#: gio/gdbus-tool.c:2193 msgid "Wait for a bus name to appear." msgstr "等待匯流排名稱顯示。" -#: gio/gdbus-tool.c:2321 +#: gio/gdbus-tool.c:2269 msgid "Error: A service to activate for must be specified.\n" msgstr "錯誤:需要指定要啟用的服務。\n" -#: gio/gdbus-tool.c:2326 +#: gio/gdbus-tool.c:2274 msgid "Error: A service to wait for must be specified.\n" msgstr "錯誤:需要指定要等待的服務。\n" -#: gio/gdbus-tool.c:2331 +#: gio/gdbus-tool.c:2279 msgid "Error: Too many arguments.\n" msgstr "錯誤:引數太多。\n" -#: gio/gdbus-tool.c:2339 gio/gdbus-tool.c:2346 +#: gio/gdbus-tool.c:2287 gio/gdbus-tool.c:2294 #, c-format msgid "Error: %s is not a valid well-known bus name.\n" msgstr "錯誤:%s 不是有效的已知匯流排名稱。\n" -#: gio/gdesktopappinfo.c:2106 gio/gdesktopappinfo.c:4932 +#: gio/gdesktopappinfo.c:2073 gio/gdesktopappinfo.c:4893 msgid "Unnamed" msgstr "未命名的" -#: gio/gdesktopappinfo.c:2516 +#: gio/gdesktopappinfo.c:2483 msgid "Desktop file didn’t specify Exec field" msgstr "桌面(Desktop)檔案未指定 Exec 欄位" -#: gio/gdesktopappinfo.c:2801 +#: gio/gdesktopappinfo.c:2763 msgid "Unable to find terminal required for application" msgstr "無法找到應用程式要求的終端機" -#: gio/gdesktopappinfo.c:3452 +#: gio/gdesktopappinfo.c:3414 #, c-format msgid "Can’t create user application configuration folder %s: %s" msgstr "不能建立使用者應用程式設定資料夾 %s:%s" -#: gio/gdesktopappinfo.c:3456 +#: gio/gdesktopappinfo.c:3418 #, c-format msgid "Can’t create user MIME configuration folder %s: %s" msgstr "不能建立使用者 MIME 設定資料夾 %s:%s" -#: gio/gdesktopappinfo.c:3698 gio/gdesktopappinfo.c:3722 +#: gio/gdesktopappinfo.c:3660 gio/gdesktopappinfo.c:3684 msgid "Application information lacks an identifier" msgstr "應用程式資訊缺少識別碼" -#: gio/gdesktopappinfo.c:3958 +#: gio/gdesktopappinfo.c:3920 #, c-format msgid "Can’t create user desktop file %s" msgstr "不能建立使用者桌面檔案 %s" -#: gio/gdesktopappinfo.c:4094 +#: gio/gdesktopappinfo.c:4056 #, c-format msgid "Custom definition for %s" msgstr "自訂 %s 的定義" @@ -1311,77 +1289,87 @@ msgstr "GEmblemedIcon 編碼中記號 (%d) 的數量格式不正確" msgid "Expected a GEmblem for GEmblemedIcon" msgstr "預期為 GEmblemedIcon 的 GEmblem" +#: gio/gfile.c:1044 gio/gfile.c:1282 gio/gfile.c:1420 gio/gfile.c:1658 +#: gio/gfile.c:1713 gio/gfile.c:1771 gio/gfile.c:1855 gio/gfile.c:1912 +#: gio/gfile.c:1976 gio/gfile.c:2031 gio/gfile.c:3722 gio/gfile.c:3777 +#: gio/gfile.c:4070 gio/gfile.c:4540 gio/gfile.c:4951 gio/gfile.c:5036 +#: gio/gfile.c:5126 gio/gfile.c:5223 gio/gfile.c:5310 gio/gfile.c:5411 +#: gio/gfile.c:8121 gio/gfile.c:8211 gio/gfile.c:8295 +#: gio/win32/gwinhttpfile.c:453 +msgid "Operation not supported" +msgstr "不支援的操作" + #. Translators: This is an error message when #. * trying to find the enclosing (user visible) #. * mount of a file, but none exists. #. -#: gio/gfile.c:1561 +#: gio/gfile.c:1543 msgid "Containing mount does not exist" msgstr "包含了不存在的掛載點" -#: gio/gfile.c:2608 gio/glocalfile.c:2472 +#: gio/gfile.c:2590 gio/glocalfile.c:2430 msgid "Can’t copy over directory" msgstr "不能複製整個目錄" -#: gio/gfile.c:2668 +#: gio/gfile.c:2650 msgid "Can’t copy directory over directory" msgstr "不能將目錄複製到目錄上" -#: gio/gfile.c:2676 +#: gio/gfile.c:2658 msgid "Target file exists" msgstr "目標檔案已存在" -#: gio/gfile.c:2695 +#: gio/gfile.c:2677 msgid "Can’t recursively copy directory" msgstr "不能遞廻複製目錄" -#: gio/gfile.c:2996 +#: gio/gfile.c:2952 msgid "Splice not supported" msgstr "不支援拼接" -#: gio/gfile.c:3000 +#: gio/gfile.c:2956 gio/gfile.c:3001 #, c-format msgid "Error splicing file: %s" msgstr "拼接檔案時發生錯誤:%s" -#: gio/gfile.c:3152 +#: gio/gfile.c:3117 msgid "Copy (reflink/clone) between mounts is not supported" msgstr "不支援在掛載點之間複製 (參照連結/重製)" -#: gio/gfile.c:3156 +#: gio/gfile.c:3121 msgid "Copy (reflink/clone) is not supported or invalid" msgstr "複製 (參照連結/重製) 不支援或無效" -#: gio/gfile.c:3161 +#: gio/gfile.c:3126 msgid "Copy (reflink/clone) is not supported or didn’t work" msgstr "複製 (參照連結/重製) 不支援或無法運作" -#: gio/gfile.c:3226 +#: gio/gfile.c:3190 msgid "Can’t copy special file" msgstr "不能複製特殊的檔案" -#: gio/gfile.c:4035 +#: gio/gfile.c:4003 msgid "Invalid symlink value given" msgstr "提供了無效的符號連結值" -#: gio/gfile.c:4045 glib/gfileutils.c:2362 +#: gio/gfile.c:4013 glib/gfileutils.c:2349 msgid "Symbolic links not supported" msgstr "不支援符號連結" -#: gio/gfile.c:4213 +#: gio/gfile.c:4181 msgid "Trash not supported" msgstr "不支援垃圾桶" -#: gio/gfile.c:4325 +#: gio/gfile.c:4293 #, c-format msgid "File names cannot contain “%c”" msgstr "檔案名稱不能包含「%c」" -#: gio/gfile.c:6806 gio/gvolume.c:364 +#: gio/gfile.c:6774 gio/gvolume.c:364 msgid "volume doesn’t implement mount" msgstr "儲存區尚未實作掛載功能" -#: gio/gfile.c:6920 gio/gfile.c:6968 +#: gio/gfile.c:6888 gio/gfile.c:6936 msgid "No application is registered as handling this file" msgstr "沒有應用程式註冊為用以處理這個檔案" @@ -1398,12 +1386,12 @@ msgstr "檔案列舉器(enumerator)有異常操作" msgid "File enumerator is already closed" msgstr "檔案列舉器(enumerator)已經關閉" -#: gio/gfileicon.c:250 +#: gio/gfileicon.c:236 #, c-format msgid "Can’t handle version %d of GFileIcon encoding" msgstr "不能處理版本為 %d 的 GFileIcon 編碼" -#: gio/gfileicon.c:260 +#: gio/gfileicon.c:246 msgid "Malformed input data for GFileIcon" msgstr "給 GFileIcon 的輸入資料格式不良" @@ -1452,11 +1440,7 @@ msgstr "HTTP 代理伺服器需要核對" msgid "HTTP proxy connection failed: %i" msgstr "HTTP 代理伺服器連線失敗:%i" -#: gio/ghttpproxy.c:266 -msgid "HTTP proxy response too big" -msgstr "HTTP 代理伺服器回應太大" - -#: gio/ghttpproxy.c:283 +#: gio/ghttpproxy.c:269 msgid "HTTP proxy server closed connection unexpectedly." msgstr "HTTP 代理伺服器未預期關閉連線。" @@ -1531,7 +1515,7 @@ msgstr "輸入串流尚未實作讀取" #. Translators: This is an error you get if there is #. * already an operation running against this stream when #. * you try to start one -#: gio/ginputstream.c:1247 gio/giostream.c:310 gio/goutputstream.c:2208 +#: gio/ginputstream.c:1218 gio/giostream.c:310 gio/goutputstream.c:2208 msgid "Stream has outstanding operation" msgstr "串流有異常操作" @@ -1572,62 +1556,58 @@ msgid "Show information about locations" msgstr "顯示位置的相關資訊" #: gio/gio-tool.c:232 -msgid "Launch an application from a desktop file" -msgstr "從 .desktop 檔案執行應用程式" - -#: gio/gio-tool.c:233 msgid "List the contents of locations" msgstr "列出位置的內容" -#: gio/gio-tool.c:234 +#: gio/gio-tool.c:233 msgid "Get or set the handler for a mimetype" msgstr "取得或設定 MIME 類型的處理程式" -#: gio/gio-tool.c:235 +#: gio/gio-tool.c:234 msgid "Create directories" msgstr "建立目錄" -#: gio/gio-tool.c:236 +#: gio/gio-tool.c:235 msgid "Monitor files and directories for changes" msgstr "監控檔案與目錄的變更" -#: gio/gio-tool.c:237 +#: gio/gio-tool.c:236 msgid "Mount or unmount the locations" msgstr "掛載或卸載位置" -#: gio/gio-tool.c:238 +#: gio/gio-tool.c:237 msgid "Move one or more files" msgstr "移動一個或多個檔案" -#: gio/gio-tool.c:239 +#: gio/gio-tool.c:238 msgid "Open files with the default application" msgstr "以預設的應用程式開啟檔案" -#: gio/gio-tool.c:240 +#: gio/gio-tool.c:239 msgid "Rename a file" msgstr "重新命名檔案" -#: gio/gio-tool.c:241 +#: gio/gio-tool.c:240 msgid "Delete one or more files" msgstr "刪除一個或多個檔案" -#: gio/gio-tool.c:242 +#: gio/gio-tool.c:241 msgid "Read from standard input and save" msgstr "從標準輸入讀取並儲存" -#: gio/gio-tool.c:243 +#: gio/gio-tool.c:242 msgid "Set a file attribute" msgstr "設定檔案特性" -#: gio/gio-tool.c:244 +#: gio/gio-tool.c:243 msgid "Move files or directories to the trash" msgstr "將檔案或目錄移至垃圾桶" -#: gio/gio-tool.c:245 +#: gio/gio-tool.c:244 msgid "Lists the contents of locations in a tree" msgstr "以樹狀圖列出位置的內容" -#: gio/gio-tool.c:247 +#: gio/gio-tool.c:246 #, c-format msgid "Use %s to get detailed help.\n" msgstr "使用 %s 以取得詳細的求助。\n" @@ -1637,12 +1617,12 @@ msgid "Error writing to stdout" msgstr "寫入至標準輸出時發生錯誤" #. Translators: commandline placeholder -#: gio/gio-tool-cat.c:133 gio/gio-tool-info.c:340 gio/gio-tool-list.c:172 +#: gio/gio-tool-cat.c:133 gio/gio-tool-info.c:333 gio/gio-tool-list.c:172 #: gio/gio-tool-mkdir.c:48 gio/gio-tool-monitor.c:37 gio/gio-tool-monitor.c:39 #: gio/gio-tool-monitor.c:41 gio/gio-tool-monitor.c:43 -#: gio/gio-tool-monitor.c:204 gio/gio-tool-mount.c:1199 gio/gio-tool-open.c:70 +#: gio/gio-tool-monitor.c:203 gio/gio-tool-mount.c:1199 gio/gio-tool-open.c:70 #: gio/gio-tool-remove.c:48 gio/gio-tool-rename.c:45 gio/gio-tool-set.c:89 -#: gio/gio-tool-trash.c:220 gio/gio-tool-tree.c:239 +#: gio/gio-tool-trash.c:90 gio/gio-tool-tree.c:239 msgid "LOCATION" msgstr "LOCATION" @@ -1660,9 +1640,9 @@ msgstr "" "位置來取代本地端檔案:例如您可以使用類似\n" " smb://server/resource/file.txt 做為位置。" -#: gio/gio-tool-cat.c:162 gio/gio-tool-info.c:371 gio/gio-tool-mkdir.c:76 -#: gio/gio-tool-monitor.c:229 gio/gio-tool-mount.c:1250 gio/gio-tool-open.c:96 -#: gio/gio-tool-remove.c:72 gio/gio-tool-trash.c:303 +#: gio/gio-tool-cat.c:162 gio/gio-tool-info.c:364 gio/gio-tool-mkdir.c:76 +#: gio/gio-tool-monitor.c:228 gio/gio-tool-mount.c:1250 gio/gio-tool-open.c:96 +#: gio/gio-tool-remove.c:72 gio/gio-tool-trash.c:145 msgid "No locations given" msgstr "未提供位置" @@ -1797,24 +1777,24 @@ msgstr "uri: %s\n" msgid "local path: %s\n" msgstr "本機路徑:%s\n" -#: gio/gio-tool-info.c:205 +#: gio/gio-tool-info.c:199 #, c-format msgid "unix mount: %s%s %s %s %s\n" msgstr "unix 掛載:%s%s %s %s %s\n" -#: gio/gio-tool-info.c:286 +#: gio/gio-tool-info.c:279 msgid "Settable attributes:\n" msgstr "可設定特性:\n" -#: gio/gio-tool-info.c:310 +#: gio/gio-tool-info.c:303 msgid "Writable attribute namespaces:\n" msgstr "可寫入特性命名空間:\n" -#: gio/gio-tool-info.c:345 +#: gio/gio-tool-info.c:338 msgid "Show information about locations." msgstr "顯示位置的相關資訊。" -#: gio/gio-tool-info.c:347 +#: gio/gio-tool-info.c:340 msgid "" "gio info is similar to the traditional ls utility, but using GIO\n" "locations instead of local files: for example, you can use something\n" @@ -1828,40 +1808,6 @@ msgstr "" "特性可以使用它們的 GIO 名稱來指定,如 standard::icon\n" "或只使用命名空間,像 unix,或「*」比對所有的屬性" -#. Translators: commandline placeholder -#: gio/gio-tool-launch.c:54 -msgid "DESKTOP-FILE [FILE-ARG …]" -msgstr "DESKTOP-檔案 [檔案-引數 …]" - -#: gio/gio-tool-launch.c:57 -msgid "" -"Launch an application from a desktop file, passing optional filename " -"arguments to it." -msgstr "從桌面檔案啟動應用程式,可以將選擇性的檔案名稱引數傳遞給它。" - -#: gio/gio-tool-launch.c:77 -msgid "No desktop file given" -msgstr "沒有提供桌面檔案" - -#: gio/gio-tool-launch.c:85 -msgid "The launch command is not currently supported on this platform" -msgstr "您的平臺目前沒有支援啟動指令" - -#: gio/gio-tool-launch.c:98 -#, c-format -msgid "Unable to load ‘%s‘: %s" -msgstr "無法載入 ‘%s‘ ︰%s" - -#: gio/gio-tool-launch.c:107 -#, c-format -msgid "Unable to load application information for ‘%s‘" -msgstr "無法載入‘%s‘的應用程式資訊" - -#: gio/gio-tool-launch.c:119 -#, c-format -msgid "Unable to launch application ‘%s’: %s" -msgstr "無法啟動應用程式‘%s’︰%s" - #: gio/gio-tool-list.c:37 gio/gio-tool-tree.c:32 msgid "Show hidden files" msgstr "顯示隱藏檔案" @@ -1999,7 +1945,7 @@ msgstr "回報移動與重新命名為簡單的刪除/建立事件" msgid "Watch for mount events" msgstr "監看掛載事件" -#: gio/gio-tool-monitor.c:209 +#: gio/gio-tool-monitor.c:208 msgid "Monitor files or directories for changes." msgstr "監控檔案或目錄的變更。" @@ -2123,7 +2069,7 @@ msgstr "" "使用註冊為處理該檔案類型的\n" "預設應用程式來開啟檔案。" -#: gio/gio-tool-remove.c:31 gio/gio-tool-trash.c:33 +#: gio/gio-tool-remove.c:31 gio/gio-tool-trash.c:31 msgid "Ignore nonexistent files, never prompt" msgstr "忽略不存在的檔案,永不提示" @@ -2236,47 +2182,13 @@ msgstr "尚未指定值" msgid "Invalid attribute type “%s”" msgstr "無效的特性類型「%s」" -#: gio/gio-tool-trash.c:34 +#: gio/gio-tool-trash.c:32 msgid "Empty the trash" msgstr "清理垃圾桶" -#: gio/gio-tool-trash.c:35 -msgid "List files in the trash with their original locations" -msgstr "列出回收筒中的檔案與它們原始的位置" - -#: gio/gio-tool-trash.c:36 -msgid "" -"Restore a file from trash to its original location (possibly recreating the " -"directory)" -msgstr "將檔案從回收筒還原到其原始位置 (可能會重新建立目錄)" - -#: gio/gio-tool-trash.c:106 -msgid "Unable to find original path" -msgstr "無法找到原始的路徑" - -#: gio/gio-tool-trash.c:123 -msgid "Unable to recreate original location: " -msgstr "無法建立原始位置︰ " - -#: gio/gio-tool-trash.c:136 -msgid "Unable to move file to its original location: " -msgstr "無法將檔案移至其原始位置: " - -#: gio/gio-tool-trash.c:225 -msgid "Move/Restore files or directories to the trash." -msgstr "將檔案或目錄移動/復原至回收筒。" - -#: gio/gio-tool-trash.c:227 -msgid "" -"Note: for --restore switch, if the original location of the trashed file \n" -"already exists, it will not be overwritten unless --force is set." -msgstr "" -"注意:以 --restore 開關而言,如果回收筒中檔案的原始位置 \n" -"已經存在,它將不會被覆蓋,除非設定 --force。" - -#: gio/gio-tool-trash.c:258 -msgid "Location given doesn't start with trash:///" -msgstr "指定的的位置不是以 trash:/// 開頭" +#: gio/gio-tool-trash.c:95 +msgid "Move files or directories to the trash." +msgstr "將檔案或目錄移至垃圾桶。" #: gio/gio-tool-tree.c:33 msgid "Follow symbolic links, mounts and shortcuts" @@ -2910,8 +2822,8 @@ msgstr "讀取檔案 %s 時發生錯誤:%s" msgid "Can’t rename file, filename already exists" msgstr "不能重新命名檔案,該檔案名稱已存在" -#: gio/glocalfile.c:1182 gio/glocalfile.c:2366 gio/glocalfile.c:2394 -#: gio/glocalfile.c:2533 gio/glocalfileoutputstream.c:656 +#: gio/glocalfile.c:1182 gio/glocalfile.c:2324 gio/glocalfile.c:2352 +#: gio/glocalfile.c:2491 gio/glocalfileoutputstream.c:650 msgid "Invalid filename" msgstr "無效的檔案名稱" @@ -2925,91 +2837,91 @@ msgstr "開啟檔案 %s 時發生錯誤:%s" msgid "Error removing file %s: %s" msgstr "移除檔案 %s 時發生錯誤:%s" -#: gio/glocalfile.c:1980 gio/glocalfile.c:1991 +#: gio/glocalfile.c:1969 #, c-format msgid "Error trashing file %s: %s" msgstr "移動檔案 %s 至垃圾桶時發生錯誤:%s" -#: gio/glocalfile.c:2029 +#: gio/glocalfile.c:2010 #, c-format -msgid "Unable to create trash directory %s: %s" -msgstr "無法建立回收筒目錄 %s:%s" +msgid "Unable to create trash dir %s: %s" +msgstr "無法建立垃圾桶目錄 %s:%s" -#: gio/glocalfile.c:2050 +#: gio/glocalfile.c:2030 #, c-format msgid "Unable to find toplevel directory to trash %s" msgstr "無法找到垃圾桶 %s 的頂端層級目錄" -#: gio/glocalfile.c:2058 +#: gio/glocalfile.c:2038 #, c-format msgid "Trashing on system internal mounts is not supported" msgstr "不支援在系統內部掛載點使用垃圾桶" -#: gio/glocalfile.c:2141 gio/glocalfile.c:2169 +#: gio/glocalfile.c:2118 gio/glocalfile.c:2138 #, c-format -msgid "Unable to find or create trash directory %s to trash %s" -msgstr "無法找到或建立回收筒目錄 %s 以回收 %s" +msgid "Unable to find or create trash directory for %s" +msgstr "無法找到或建立 %s 的垃圾桶目錄" -#: gio/glocalfile.c:2215 +#: gio/glocalfile.c:2173 #, c-format msgid "Unable to create trashing info file for %s: %s" msgstr "無法建立 %s 垃圾桶資訊檔案:%s" -#: gio/glocalfile.c:2277 +#: gio/glocalfile.c:2235 #, c-format msgid "Unable to trash file %s across filesystem boundaries" msgstr "無法將檔案 %s 跨檔案系統邊界移至垃圾桶" -#: gio/glocalfile.c:2281 gio/glocalfile.c:2337 +#: gio/glocalfile.c:2239 gio/glocalfile.c:2295 #, c-format msgid "Unable to trash file %s: %s" msgstr "無法將檔案 %s 移至垃圾桶:%s" -#: gio/glocalfile.c:2343 +#: gio/glocalfile.c:2301 #, c-format msgid "Unable to trash file %s" msgstr "無法將檔案 %s 移至垃圾桶" -#: gio/glocalfile.c:2369 +#: gio/glocalfile.c:2327 #, c-format msgid "Error creating directory %s: %s" msgstr "建立目錄 %s 時發生錯誤:%s" -#: gio/glocalfile.c:2398 +#: gio/glocalfile.c:2356 #, c-format msgid "Filesystem does not support symbolic links" msgstr "檔案系統不支援符號連結" -#: gio/glocalfile.c:2401 +#: gio/glocalfile.c:2359 #, c-format msgid "Error making symbolic link %s: %s" msgstr "建立符號連結 %s 時發生錯誤:%s" -#: gio/glocalfile.c:2444 gio/glocalfile.c:2479 gio/glocalfile.c:2536 +#: gio/glocalfile.c:2402 gio/glocalfile.c:2437 gio/glocalfile.c:2494 #, c-format msgid "Error moving file %s: %s" msgstr "移動檔案 %s 時發生錯誤:%s" -#: gio/glocalfile.c:2467 +#: gio/glocalfile.c:2425 msgid "Can’t move directory over directory" msgstr "不能將目錄移動至目錄上" -#: gio/glocalfile.c:2493 gio/glocalfileoutputstream.c:1079 -#: gio/glocalfileoutputstream.c:1093 gio/glocalfileoutputstream.c:1108 -#: gio/glocalfileoutputstream.c:1125 gio/glocalfileoutputstream.c:1139 +#: gio/glocalfile.c:2451 gio/glocalfileoutputstream.c:1039 +#: gio/glocalfileoutputstream.c:1053 gio/glocalfileoutputstream.c:1068 +#: gio/glocalfileoutputstream.c:1085 gio/glocalfileoutputstream.c:1099 msgid "Backup file creation failed" msgstr "建立備份檔案失敗" -#: gio/glocalfile.c:2512 +#: gio/glocalfile.c:2470 #, c-format msgid "Error removing target file: %s" msgstr "移除目標檔案時發生錯誤:%s" -#: gio/glocalfile.c:2526 +#: gio/glocalfile.c:2484 msgid "Move between mounts not supported" msgstr "不支援在掛載點之間移動" -#: gio/glocalfile.c:2700 +#: gio/glocalfile.c:2658 #, c-format msgid "Could not determine the disk usage of %s: %s" msgstr "無法決定 %s 的磁碟使用量:%s" @@ -3031,184 +2943,185 @@ msgstr "無效的延伸特性名稱" msgid "Error setting extended attribute “%s”: %s" msgstr "設定延伸特性「%s」時發生錯誤:%s" -#: gio/glocalfileinfo.c:1709 gio/win32/gwinhttpfile.c:191 +#: gio/glocalfileinfo.c:1666 gio/win32/gwinhttpfile.c:191 msgid " (invalid encoding)" msgstr "(無效的編碼)" -#: gio/glocalfileinfo.c:1868 gio/glocalfileoutputstream.c:943 +#: gio/glocalfileinfo.c:1825 gio/glocalfileoutputstream.c:915 #, c-format msgid "Error when getting information for file “%s”: %s" msgstr "取得檔案「%s」資訊時發生錯誤:%s" -#: gio/glocalfileinfo.c:2134 +#: gio/glocalfileinfo.c:2091 #, c-format msgid "Error when getting information for file descriptor: %s" msgstr "取得檔案描述狀態資訊時發生錯誤:%s" -#: gio/glocalfileinfo.c:2179 +#: gio/glocalfileinfo.c:2136 msgid "Invalid attribute type (uint32 expected)" msgstr "無效的特性類型(應為 uint32 值)" -#: gio/glocalfileinfo.c:2197 +#: gio/glocalfileinfo.c:2154 msgid "Invalid attribute type (uint64 expected)" msgstr "無效的特性類型(應為 uint64 值)" -#: gio/glocalfileinfo.c:2216 gio/glocalfileinfo.c:2235 +#: gio/glocalfileinfo.c:2173 gio/glocalfileinfo.c:2192 msgid "Invalid attribute type (byte string expected)" msgstr "無效的特性類型(應為 byte string 值)" -#: gio/glocalfileinfo.c:2282 +#: gio/glocalfileinfo.c:2239 msgid "Cannot set permissions on symlinks" msgstr "不能設定符號連結的權限" -#: gio/glocalfileinfo.c:2298 +#: gio/glocalfileinfo.c:2255 #, c-format msgid "Error setting permissions: %s" msgstr "設定權限時發生錯誤:%s" -#: gio/glocalfileinfo.c:2349 +#: gio/glocalfileinfo.c:2306 #, c-format msgid "Error setting owner: %s" msgstr "設定擁有者時發生錯誤:%s" -#: gio/glocalfileinfo.c:2372 +#: gio/glocalfileinfo.c:2329 msgid "symlink must be non-NULL" msgstr "符號連結必須為非-NULL" -#: gio/glocalfileinfo.c:2382 gio/glocalfileinfo.c:2401 -#: gio/glocalfileinfo.c:2412 +#: gio/glocalfileinfo.c:2339 gio/glocalfileinfo.c:2358 +#: gio/glocalfileinfo.c:2369 #, c-format msgid "Error setting symlink: %s" msgstr "設定符號連結時發生錯誤:%s" -#: gio/glocalfileinfo.c:2391 +#: gio/glocalfileinfo.c:2348 msgid "Error setting symlink: file is not a symlink" msgstr "設定符號連結時發生錯誤:檔案不是符號連結" -#: gio/glocalfileinfo.c:2463 +#: gio/glocalfileinfo.c:2420 #, c-format msgid "Extra nanoseconds %d for UNIX timestamp %lld are negative" msgstr "UNIX 時間戳 %2$lld 的延伸奈秒 %1$d 是負數" -#: gio/glocalfileinfo.c:2472 +#: gio/glocalfileinfo.c:2429 #, c-format msgid "Extra nanoseconds %d for UNIX timestamp %lld reach 1 second" msgstr "UNIX 時間戳 %2$lld 的延伸奈秒 %1$d 達 1 秒" -#: gio/glocalfileinfo.c:2482 +#: gio/glocalfileinfo.c:2439 #, c-format msgid "UNIX timestamp %lld does not fit into 64 bits" msgstr "UNIX 時間戳 %lld 不能完整放入 64 位元" -#: gio/glocalfileinfo.c:2493 +#: gio/glocalfileinfo.c:2450 #, c-format msgid "UNIX timestamp %lld is outside of the range supported by Windows" msgstr "UNIX 時間戳 %lld 超出 Windows 所支援的範圍" -#: gio/glocalfileinfo.c:2557 +#: gio/glocalfileinfo.c:2514 #, c-format msgid "File name “%s” cannot be converted to UTF-16" msgstr "「%s」檔名無法轉換為 UTF-16" -#: gio/glocalfileinfo.c:2576 +#: gio/glocalfileinfo.c:2533 #, c-format msgid "File “%s” cannot be opened: Windows Error %lu" msgstr "無法開啟「%s」檔案:Windows 錯誤 %lu" -#: gio/glocalfileinfo.c:2589 +#: gio/glocalfileinfo.c:2546 #, c-format msgid "Error setting modification or access time for file “%s”: %lu" msgstr "設定「%s」檔案的修改或存取時間時發生錯誤:%lu" -#: gio/glocalfileinfo.c:2690 +#: gio/glocalfileinfo.c:2647 #, c-format msgid "Error setting modification or access time: %s" msgstr "設定修改或存取時刻時發生錯誤:%s" -#: gio/glocalfileinfo.c:2713 +#: gio/glocalfileinfo.c:2670 msgid "SELinux context must be non-NULL" msgstr "SELinux 情境必須為非-NULL" -#: gio/glocalfileinfo.c:2720 -msgid "SELinux is not enabled on this system" -msgstr "SELinux 在這個系統上並未啟用" - -#: gio/glocalfileinfo.c:2730 +#: gio/glocalfileinfo.c:2685 #, c-format msgid "Error setting SELinux context: %s" msgstr "設定 SELinux 情境時發生錯誤:%s" -#: gio/glocalfileinfo.c:2823 +#: gio/glocalfileinfo.c:2692 +msgid "SELinux is not enabled on this system" +msgstr "SELinux 在這個系統上並未啟用" + +#: gio/glocalfileinfo.c:2784 #, c-format msgid "Setting attribute %s not supported" msgstr "不支援設定特性 %s" -#: gio/glocalfileinputstream.c:163 gio/glocalfileoutputstream.c:801 +#: gio/glocalfileinputstream.c:168 gio/glocalfileoutputstream.c:795 #, c-format msgid "Error reading from file: %s" msgstr "從檔案讀取時發生錯誤:%s" -#: gio/glocalfileinputstream.c:194 gio/glocalfileoutputstream.c:353 -#: gio/glocalfileoutputstream.c:447 -#, c-format -msgid "Error closing file: %s" -msgstr "關閉檔案時發生錯誤:%s" - -#: gio/glocalfileinputstream.c:272 gio/glocalfileoutputstream.c:563 -#: gio/glocalfileoutputstream.c:1157 +#: gio/glocalfileinputstream.c:199 gio/glocalfileinputstream.c:211 +#: gio/glocalfileinputstream.c:225 gio/glocalfileinputstream.c:333 +#: gio/glocalfileoutputstream.c:557 gio/glocalfileoutputstream.c:1117 #, c-format msgid "Error seeking in file: %s" msgstr "在檔案中搜尋時發生錯誤:%s" -#: gio/glocalfilemonitor.c:866 +#: gio/glocalfileinputstream.c:255 gio/glocalfileoutputstream.c:347 +#: gio/glocalfileoutputstream.c:441 +#, c-format +msgid "Error closing file: %s" +msgstr "關閉檔案時發生錯誤:%s" + +#: gio/glocalfilemonitor.c:865 msgid "Unable to find default local file monitor type" msgstr "無法找到預設的本地端檔案監視器類型" -#: gio/glocalfileoutputstream.c:220 gio/glocalfileoutputstream.c:298 -#: gio/glocalfileoutputstream.c:334 gio/glocalfileoutputstream.c:822 +#: gio/glocalfileoutputstream.c:214 gio/glocalfileoutputstream.c:292 +#: gio/glocalfileoutputstream.c:328 gio/glocalfileoutputstream.c:816 #, c-format msgid "Error writing to file: %s" msgstr "寫入至檔案時發生錯誤:%s" -#: gio/glocalfileoutputstream.c:380 +#: gio/glocalfileoutputstream.c:374 #, c-format msgid "Error removing old backup link: %s" msgstr "移除舊備份連結時發生錯誤:%s" -#: gio/glocalfileoutputstream.c:394 gio/glocalfileoutputstream.c:407 +#: gio/glocalfileoutputstream.c:388 gio/glocalfileoutputstream.c:401 #, c-format msgid "Error creating backup copy: %s" msgstr "建立備份複本時發生錯誤:%s" -#: gio/glocalfileoutputstream.c:425 +#: gio/glocalfileoutputstream.c:419 #, c-format msgid "Error renaming temporary file: %s" msgstr "重新命名暫存檔案時發生錯誤:%s" -#: gio/glocalfileoutputstream.c:609 gio/glocalfileoutputstream.c:1208 +#: gio/glocalfileoutputstream.c:603 gio/glocalfileoutputstream.c:1168 #, c-format msgid "Error truncating file: %s" msgstr "截短檔案時發生錯誤:%s" -#: gio/glocalfileoutputstream.c:662 gio/glocalfileoutputstream.c:907 -#: gio/glocalfileoutputstream.c:1189 gio/gsubprocess.c:226 +#: gio/glocalfileoutputstream.c:656 gio/glocalfileoutputstream.c:894 +#: gio/glocalfileoutputstream.c:1149 gio/gsubprocess.c:380 #, c-format msgid "Error opening file “%s”: %s" msgstr "開啟檔案「%s」時發生錯誤:%s" -#: gio/glocalfileoutputstream.c:957 +#: gio/glocalfileoutputstream.c:928 msgid "Target file is a directory" msgstr "目標檔案是一個目錄" -#: gio/glocalfileoutputstream.c:971 +#: gio/glocalfileoutputstream.c:933 msgid "Target file is not a regular file" msgstr "目標檔案不是正規的檔案" -#: gio/glocalfileoutputstream.c:984 +#: gio/glocalfileoutputstream.c:945 msgid "The file was externally modified" msgstr "該檔案已被外部程式修改過" -#: gio/glocalfileoutputstream.c:1173 +#: gio/glocalfileoutputstream.c:1133 #, c-format msgid "Error removing old file: %s" msgstr "移除舊檔案時發生錯誤:%s" @@ -3361,15 +3274,15 @@ msgstr "%s 未實作" msgid "Invalid domain" msgstr "網域無效" -#: gio/gresource.c:681 gio/gresource.c:943 gio/gresource.c:983 -#: gio/gresource.c:1107 gio/gresource.c:1179 gio/gresource.c:1253 -#: gio/gresource.c:1334 gio/gresourcefile.c:476 gio/gresourcefile.c:599 +#: gio/gresource.c:672 gio/gresource.c:931 gio/gresource.c:970 +#: gio/gresource.c:1094 gio/gresource.c:1166 gio/gresource.c:1239 +#: gio/gresource.c:1320 gio/gresourcefile.c:476 gio/gresourcefile.c:599 #: gio/gresourcefile.c:736 #, c-format msgid "The resource at “%s” does not exist" msgstr "「%s」的資源不存在" -#: gio/gresource.c:848 +#: gio/gresource.c:837 #, c-format msgid "The resource at “%s” failed to decompress" msgstr "「%s」的資源無法解壓縮" @@ -3743,7 +3656,7 @@ msgstr "無效的 socket,初始化失敗原因為:%s" msgid "Socket is already closed" msgstr "Socket 已經關閉" -#: gio/gsocket.c:443 gio/gsocket.c:3190 gio/gsocket.c:4420 gio/gsocket.c:4478 +#: gio/gsocket.c:443 gio/gsocket.c:3180 gio/gsocket.c:4403 gio/gsocket.c:4461 msgid "Socket I/O timed out" msgstr "Socket I/O 逾時" @@ -3752,181 +3665,176 @@ msgstr "Socket I/O 逾時" msgid "creating GSocket from fd: %s" msgstr "正在從 fd 建立 GSocket:%s" -#: gio/gsocket.c:607 gio/gsocket.c:671 gio/gsocket.c:678 +#: gio/gsocket.c:607 gio/gsocket.c:661 gio/gsocket.c:668 #, c-format msgid "Unable to create socket: %s" msgstr "無法建立 socket:%s" -#: gio/gsocket.c:671 +#: gio/gsocket.c:661 msgid "Unknown family was specified" msgstr "指定了不明的字族" -#: gio/gsocket.c:678 +#: gio/gsocket.c:668 msgid "Unknown protocol was specified" msgstr "指定了不明的通訊協定" -#: gio/gsocket.c:1169 +#: gio/gsocket.c:1159 #, c-format msgid "Cannot use datagram operations on a non-datagram socket." msgstr "不能在非資料電報 socket 上使用資料電報操作。" -#: gio/gsocket.c:1186 +#: gio/gsocket.c:1176 #, c-format msgid "Cannot use datagram operations on a socket with a timeout set." msgstr "不能在有逾時設定 socket 上使用資料電報操作。" -#: gio/gsocket.c:1993 +#: gio/gsocket.c:1983 #, c-format msgid "could not get local address: %s" msgstr "無法取得本地端位址:%s" -#: gio/gsocket.c:2039 +#: gio/gsocket.c:2029 #, c-format msgid "could not get remote address: %s" msgstr "無法取得遠端位址:%s" -#: gio/gsocket.c:2105 +#: gio/gsocket.c:2095 #, c-format msgid "could not listen: %s" msgstr "無法聽取:%s" -#: gio/gsocket.c:2209 +#: gio/gsocket.c:2199 #, c-format msgid "Error binding to address %s: %s" msgstr "綁定至 %s 位址時發生錯誤:%s" -#: gio/gsocket.c:2385 gio/gsocket.c:2422 gio/gsocket.c:2532 gio/gsocket.c:2557 -#: gio/gsocket.c:2620 gio/gsocket.c:2678 gio/gsocket.c:2696 +#: gio/gsocket.c:2375 gio/gsocket.c:2412 gio/gsocket.c:2522 gio/gsocket.c:2547 +#: gio/gsocket.c:2610 gio/gsocket.c:2668 gio/gsocket.c:2686 #, c-format msgid "Error joining multicast group: %s" msgstr "加入多點廣播群組時發生錯誤:%s" -#: gio/gsocket.c:2386 gio/gsocket.c:2423 gio/gsocket.c:2533 gio/gsocket.c:2558 -#: gio/gsocket.c:2621 gio/gsocket.c:2679 gio/gsocket.c:2697 +#: gio/gsocket.c:2376 gio/gsocket.c:2413 gio/gsocket.c:2523 gio/gsocket.c:2548 +#: gio/gsocket.c:2611 gio/gsocket.c:2669 gio/gsocket.c:2687 #, c-format msgid "Error leaving multicast group: %s" msgstr "離開多點廣播群組時發生錯誤:%s" -#: gio/gsocket.c:2387 +#: gio/gsocket.c:2377 msgid "No support for source-specific multicast" msgstr "不支援指定來源的多點廣播" -#: gio/gsocket.c:2534 +#: gio/gsocket.c:2524 msgid "Unsupported socket family" msgstr "不支援的 socket 家族" -#: gio/gsocket.c:2559 +#: gio/gsocket.c:2549 msgid "source-specific not an IPv4 address" msgstr "指定來源不是 IPv4 位址" -#: gio/gsocket.c:2583 +#: gio/gsocket.c:2573 #, c-format msgid "Interface name too long" msgstr "介面名稱過長" -#: gio/gsocket.c:2596 gio/gsocket.c:2646 +#: gio/gsocket.c:2586 gio/gsocket.c:2636 #, c-format msgid "Interface not found: %s" msgstr "找不到介面:%s" -#: gio/gsocket.c:2622 +#: gio/gsocket.c:2612 msgid "No support for IPv4 source-specific multicast" msgstr "不支援 IPv4 指定來源的多點廣播" -#: gio/gsocket.c:2680 +#: gio/gsocket.c:2670 msgid "No support for IPv6 source-specific multicast" msgstr "不支援 IPv6 指定來源的多點廣播" -#: gio/gsocket.c:2889 +#: gio/gsocket.c:2879 #, c-format msgid "Error accepting connection: %s" msgstr "接受連線時發生錯誤:%s" -#: gio/gsocket.c:3015 +#: gio/gsocket.c:3005 msgid "Connection in progress" msgstr "連線進行中" -#: gio/gsocket.c:3066 +#: gio/gsocket.c:3056 msgid "Unable to get pending error: " msgstr "無法取得未處理的錯誤:" -#: gio/gsocket.c:3255 +#: gio/gsocket.c:3245 #, c-format msgid "Error receiving data: %s" msgstr "接收資料時發生錯誤:%s" -#: gio/gsocket.c:3452 +#: gio/gsocket.c:3442 #, c-format msgid "Error sending data: %s" msgstr "傳送資料時發生錯誤:%s" -#: gio/gsocket.c:3639 +#: gio/gsocket.c:3629 #, c-format msgid "Unable to shutdown socket: %s" msgstr "無法關閉 socket:%s" -#: gio/gsocket.c:3720 +#: gio/gsocket.c:3710 #, c-format msgid "Error closing socket: %s" msgstr "關閉 socket 時發生錯誤:%s" -#: gio/gsocket.c:4413 +#: gio/gsocket.c:4396 #, c-format msgid "Waiting for socket condition: %s" msgstr "等候 socket 情況:%s" -#: gio/gsocket.c:4804 gio/gsocket.c:4820 gio/gsocket.c:4833 -#, c-format -msgid "Unable to send message: %s" -msgstr "無法傳送訊息:%s" - -#: gio/gsocket.c:4805 gio/gsocket.c:4821 gio/gsocket.c:4834 -msgid "Message vectors too large" -msgstr "訊息係數過大" - -#: gio/gsocket.c:4850 gio/gsocket.c:4852 gio/gsocket.c:4999 gio/gsocket.c:5084 -#: gio/gsocket.c:5262 gio/gsocket.c:5302 gio/gsocket.c:5304 +#: gio/gsocket.c:4774 gio/gsocket.c:4776 gio/gsocket.c:4923 gio/gsocket.c:5008 +#: gio/gsocket.c:5186 gio/gsocket.c:5226 gio/gsocket.c:5228 #, c-format msgid "Error sending message: %s" msgstr "傳送訊息時發生錯誤:%s" -#: gio/gsocket.c:5026 +#: gio/gsocket.c:4950 msgid "GSocketControlMessage not supported on Windows" msgstr "視窗不支援 GSocketControlMessage" -#: gio/gsocket.c:5495 gio/gsocket.c:5571 gio/gsocket.c:5797 +#: gio/gsocket.c:5419 gio/gsocket.c:5492 gio/gsocket.c:5718 #, c-format msgid "Error receiving message: %s" msgstr "取回郵件發生錯誤:%s" -#: gio/gsocket.c:6070 gio/gsocket.c:6081 gio/gsocket.c:6127 +#: gio/gsocket.c:5990 gio/gsocket.c:6038 #, c-format msgid "Unable to read socket credentials: %s" msgstr "無法讀取 socket 機密:%s" -#: gio/gsocket.c:6136 +#: gio/gsocket.c:6047 msgid "g_socket_get_credentials not implemented for this OS" msgstr "g_socket_get_credentials 沒有在這個 OS 上實作" -#: gio/gsocketclient.c:191 +#: gio/gsocketclient.c:182 #, c-format msgid "Could not connect to proxy server %s: " msgstr "無法連線到代理伺服器 %s:" -#: gio/gsocketclient.c:205 +#: gio/gsocketclient.c:196 #, c-format msgid "Could not connect to %s: " msgstr "無法連接到 %s:" -#: gio/gsocketclient.c:207 +#: gio/gsocketclient.c:198 msgid "Could not connect: " msgstr "無法連接:" -#: gio/gsocketclient.c:1162 gio/gsocketclient.c:1749 +#: gio/gsocketclient.c:1037 gio/gsocketclient.c:1866 +msgid "Unknown error on connect" +msgstr "連線時有不明的錯誤" + +#: gio/gsocketclient.c:1091 gio/gsocketclient.c:1668 msgid "Proxying over a non-TCP connection is not supported." msgstr "不支援嘗試透過非-TCP 連線使用代理伺服器。" -#: gio/gsocketclient.c:1194 gio/gsocketclient.c:1778 +#: gio/gsocketclient.c:1120 gio/gsocketclient.c:1698 #, c-format msgid "Proxy protocol “%s” is not supported." msgstr "指定的通訊協定「%s」不被支援。" @@ -4055,30 +3963,26 @@ msgstr "暫時無法解析「%s」" msgid "Error resolving “%s”" msgstr "解析「%s」時發生錯誤" -#: gio/gtlscertificate.c:298 +#: gio/gtlscertificate.c:243 msgid "No PEM-encoded private key found" msgstr "找不到 PEM 編碼的私鑰" -#: gio/gtlscertificate.c:308 +#: gio/gtlscertificate.c:253 msgid "Cannot decrypt PEM-encoded private key" msgstr "不能解鎖 PEM 編碼的私鑰" -#: gio/gtlscertificate.c:319 +#: gio/gtlscertificate.c:264 msgid "Could not parse PEM-encoded private key" msgstr "無法解析 PEM 編碼的私鑰" -#: gio/gtlscertificate.c:346 +#: gio/gtlscertificate.c:291 msgid "No PEM-encoded certificate found" msgstr "找到非 PEM 編碼的憑證" -#: gio/gtlscertificate.c:355 +#: gio/gtlscertificate.c:300 msgid "Could not parse PEM-encoded certificate" msgstr "無法解析 PEM 編碼的憑證" -#: gio/gtlscertificate.c:710 -msgid "This GTlsBackend does not support creating PKCS #11 certificates" -msgstr "這個 GTlsBackend 不支援建立does PKCS #11 憑證" - #: gio/gtlspassword.c:111 msgid "" "This is the last chance to enter the password correctly before your access " @@ -4147,24 +4051,24 @@ msgstr "不是預期的控制訊息,卻收到 %d" msgid "Error while disabling SO_PASSCRED: %s" msgstr "停用 SO_PASSCRED 時發生錯誤:%s" -#: gio/gunixinputstream.c:357 gio/gunixinputstream.c:378 +#: gio/gunixinputstream.c:362 gio/gunixinputstream.c:383 #, c-format msgid "Error reading from file descriptor: %s" msgstr "讀取檔案描述狀態時發生錯誤:%s" -#: gio/gunixinputstream.c:411 gio/gunixoutputstream.c:520 +#: gio/gunixinputstream.c:416 gio/gunixoutputstream.c:525 #: gio/gwin32inputstream.c:217 gio/gwin32outputstream.c:204 #, c-format msgid "Error closing file descriptor: %s" msgstr "關閉檔案描述狀態時發生錯誤:%s" -#: gio/gunixmounts.c:2780 gio/gunixmounts.c:2833 +#: gio/gunixmounts.c:2755 gio/gunixmounts.c:2808 msgid "Filesystem root" msgstr "根檔案系統" -#: gio/gunixoutputstream.c:357 gio/gunixoutputstream.c:377 -#: gio/gunixoutputstream.c:464 gio/gunixoutputstream.c:484 -#: gio/gunixoutputstream.c:630 +#: gio/gunixoutputstream.c:362 gio/gunixoutputstream.c:382 +#: gio/gunixoutputstream.c:469 gio/gunixoutputstream.c:489 +#: gio/gunixoutputstream.c:635 #, c-format msgid "Error writing to file descriptor: %s" msgstr "寫入檔案描述狀態時發生錯誤:%s" @@ -4368,25 +4272,25 @@ msgid "The pathname “%s” is not an absolute path" msgstr "路徑名稱「%s」不是絕對路徑" #. Translators: this is the preferred format for expressing the date and the time -#: glib/gdatetime.c:226 +#: glib/gdatetime.c:220 msgctxt "GDateTime" msgid "%a %b %e %H:%M:%S %Y" msgstr "%Y年%m月%d日 (%A) %H時%M分%S秒" #. Translators: this is the preferred format for expressing the date -#: glib/gdatetime.c:229 +#: glib/gdatetime.c:223 msgctxt "GDateTime" msgid "%m/%d/%y" msgstr "%y/%m/%d" #. Translators: this is the preferred format for expressing the time -#: glib/gdatetime.c:232 +#: glib/gdatetime.c:226 msgctxt "GDateTime" msgid "%H:%M:%S" msgstr "%H:%M:%S" #. Translators: this is the preferred format for expressing 12 hour time -#: glib/gdatetime.c:235 +#: glib/gdatetime.c:229 msgctxt "GDateTime" msgid "%I:%M:%S %p" msgstr "%p %I時%M分%S秒" @@ -4407,62 +4311,62 @@ msgstr "%p %I時%M分%S秒" #. * non-European) there is no difference between the standalone and #. * complete date form. #. -#: glib/gdatetime.c:274 +#: glib/gdatetime.c:268 msgctxt "full month name" msgid "January" msgstr "一月" -#: glib/gdatetime.c:276 +#: glib/gdatetime.c:270 msgctxt "full month name" msgid "February" msgstr "二月" -#: glib/gdatetime.c:278 +#: glib/gdatetime.c:272 msgctxt "full month name" msgid "March" msgstr "三月" -#: glib/gdatetime.c:280 +#: glib/gdatetime.c:274 msgctxt "full month name" msgid "April" msgstr "四月" -#: glib/gdatetime.c:282 +#: glib/gdatetime.c:276 msgctxt "full month name" msgid "May" msgstr "五月" -#: glib/gdatetime.c:284 +#: glib/gdatetime.c:278 msgctxt "full month name" msgid "June" msgstr "六月" -#: glib/gdatetime.c:286 +#: glib/gdatetime.c:280 msgctxt "full month name" msgid "July" msgstr "七月" -#: glib/gdatetime.c:288 +#: glib/gdatetime.c:282 msgctxt "full month name" msgid "August" msgstr "八月" -#: glib/gdatetime.c:290 +#: glib/gdatetime.c:284 msgctxt "full month name" msgid "September" msgstr "九月" -#: glib/gdatetime.c:292 +#: glib/gdatetime.c:286 msgctxt "full month name" msgid "October" msgstr "十月" -#: glib/gdatetime.c:294 +#: glib/gdatetime.c:288 msgctxt "full month name" msgid "November" msgstr "十一月" -#: glib/gdatetime.c:296 +#: glib/gdatetime.c:290 msgctxt "full month name" msgid "December" msgstr "十二月" @@ -4484,132 +4388,132 @@ msgstr "十二月" #. * other platform. Here are abbreviated month names in a form #. * appropriate when they are used standalone. #. -#: glib/gdatetime.c:328 +#: glib/gdatetime.c:322 msgctxt "abbreviated month name" msgid "Jan" msgstr "一月" -#: glib/gdatetime.c:330 +#: glib/gdatetime.c:324 msgctxt "abbreviated month name" msgid "Feb" msgstr "二月" -#: glib/gdatetime.c:332 +#: glib/gdatetime.c:326 msgctxt "abbreviated month name" msgid "Mar" msgstr "三月" -#: glib/gdatetime.c:334 +#: glib/gdatetime.c:328 msgctxt "abbreviated month name" msgid "Apr" msgstr "四月" -#: glib/gdatetime.c:336 +#: glib/gdatetime.c:330 msgctxt "abbreviated month name" msgid "May" msgstr "五月" -#: glib/gdatetime.c:338 +#: glib/gdatetime.c:332 msgctxt "abbreviated month name" msgid "Jun" msgstr "六月" -#: glib/gdatetime.c:340 +#: glib/gdatetime.c:334 msgctxt "abbreviated month name" msgid "Jul" msgstr "七月" -#: glib/gdatetime.c:342 +#: glib/gdatetime.c:336 msgctxt "abbreviated month name" msgid "Aug" msgstr "八月" -#: glib/gdatetime.c:344 +#: glib/gdatetime.c:338 msgctxt "abbreviated month name" msgid "Sep" msgstr "九月" -#: glib/gdatetime.c:346 +#: glib/gdatetime.c:340 msgctxt "abbreviated month name" msgid "Oct" msgstr "十月" -#: glib/gdatetime.c:348 +#: glib/gdatetime.c:342 msgctxt "abbreviated month name" msgid "Nov" msgstr "十一月" -#: glib/gdatetime.c:350 +#: glib/gdatetime.c:344 msgctxt "abbreviated month name" msgid "Dec" msgstr "十二月" -#: glib/gdatetime.c:365 +#: glib/gdatetime.c:359 msgctxt "full weekday name" msgid "Monday" msgstr "星期一" -#: glib/gdatetime.c:367 +#: glib/gdatetime.c:361 msgctxt "full weekday name" msgid "Tuesday" msgstr "星期二" -#: glib/gdatetime.c:369 +#: glib/gdatetime.c:363 msgctxt "full weekday name" msgid "Wednesday" msgstr "星期三" -#: glib/gdatetime.c:371 +#: glib/gdatetime.c:365 msgctxt "full weekday name" msgid "Thursday" msgstr "星期四" -#: glib/gdatetime.c:373 +#: glib/gdatetime.c:367 msgctxt "full weekday name" msgid "Friday" msgstr "星期五" -#: glib/gdatetime.c:375 +#: glib/gdatetime.c:369 msgctxt "full weekday name" msgid "Saturday" msgstr "星期六" -#: glib/gdatetime.c:377 +#: glib/gdatetime.c:371 msgctxt "full weekday name" msgid "Sunday" msgstr "星期日" -#: glib/gdatetime.c:392 +#: glib/gdatetime.c:386 msgctxt "abbreviated weekday name" msgid "Mon" msgstr "週一" -#: glib/gdatetime.c:394 +#: glib/gdatetime.c:388 msgctxt "abbreviated weekday name" msgid "Tue" msgstr "週二" -#: glib/gdatetime.c:396 +#: glib/gdatetime.c:390 msgctxt "abbreviated weekday name" msgid "Wed" msgstr "週三" -#: glib/gdatetime.c:398 +#: glib/gdatetime.c:392 msgctxt "abbreviated weekday name" msgid "Thu" msgstr "週四" -#: glib/gdatetime.c:400 +#: glib/gdatetime.c:394 msgctxt "abbreviated weekday name" msgid "Fri" msgstr "週五" -#: glib/gdatetime.c:402 +#: glib/gdatetime.c:396 msgctxt "abbreviated weekday name" msgid "Sat" msgstr "週六" -#: glib/gdatetime.c:404 +#: glib/gdatetime.c:398 msgctxt "abbreviated weekday name" msgid "Sun" msgstr "週日" @@ -4631,62 +4535,62 @@ msgstr "週日" #. * (western European, non-European) there is no difference between the #. * standalone and complete date form. #. -#: glib/gdatetime.c:468 +#: glib/gdatetime.c:462 msgctxt "full month name with day" msgid "January" msgstr "一月" -#: glib/gdatetime.c:470 +#: glib/gdatetime.c:464 msgctxt "full month name with day" msgid "February" msgstr "二月" -#: glib/gdatetime.c:472 +#: glib/gdatetime.c:466 msgctxt "full month name with day" msgid "March" msgstr "三月" -#: glib/gdatetime.c:474 +#: glib/gdatetime.c:468 msgctxt "full month name with day" msgid "April" msgstr "四月" -#: glib/gdatetime.c:476 +#: glib/gdatetime.c:470 msgctxt "full month name with day" msgid "May" msgstr "五月" -#: glib/gdatetime.c:478 +#: glib/gdatetime.c:472 msgctxt "full month name with day" msgid "June" msgstr "六月" -#: glib/gdatetime.c:480 +#: glib/gdatetime.c:474 msgctxt "full month name with day" msgid "July" msgstr "七月" -#: glib/gdatetime.c:482 +#: glib/gdatetime.c:476 msgctxt "full month name with day" msgid "August" msgstr "八月" -#: glib/gdatetime.c:484 +#: glib/gdatetime.c:478 msgctxt "full month name with day" msgid "September" msgstr "九月" -#: glib/gdatetime.c:486 +#: glib/gdatetime.c:480 msgctxt "full month name with day" msgid "October" msgstr "十月" -#: glib/gdatetime.c:488 +#: glib/gdatetime.c:482 msgctxt "full month name with day" msgid "November" msgstr "十一月" -#: glib/gdatetime.c:490 +#: glib/gdatetime.c:484 msgctxt "full month name with day" msgid "December" msgstr "十二月" @@ -4708,74 +4612,74 @@ msgstr "十二月" #. * month names almost ready to copy and paste here. In other systems #. * due to a bug the result is incorrect in some languages. #. -#: glib/gdatetime.c:555 +#: glib/gdatetime.c:549 msgctxt "abbreviated month name with day" msgid "Jan" msgstr "一月" -#: glib/gdatetime.c:557 +#: glib/gdatetime.c:551 msgctxt "abbreviated month name with day" msgid "Feb" msgstr "二月" -#: glib/gdatetime.c:559 +#: glib/gdatetime.c:553 msgctxt "abbreviated month name with day" msgid "Mar" msgstr "三月" -#: glib/gdatetime.c:561 +#: glib/gdatetime.c:555 msgctxt "abbreviated month name with day" msgid "Apr" msgstr "四月" -#: glib/gdatetime.c:563 +#: glib/gdatetime.c:557 msgctxt "abbreviated month name with day" msgid "May" msgstr "五月" -#: glib/gdatetime.c:565 +#: glib/gdatetime.c:559 msgctxt "abbreviated month name with day" msgid "Jun" msgstr "六月" -#: glib/gdatetime.c:567 +#: glib/gdatetime.c:561 msgctxt "abbreviated month name with day" msgid "Jul" msgstr "七月" -#: glib/gdatetime.c:569 +#: glib/gdatetime.c:563 msgctxt "abbreviated month name with day" msgid "Aug" msgstr "八月" -#: glib/gdatetime.c:571 +#: glib/gdatetime.c:565 msgctxt "abbreviated month name with day" msgid "Sep" msgstr "九月" -#: glib/gdatetime.c:573 +#: glib/gdatetime.c:567 msgctxt "abbreviated month name with day" msgid "Oct" msgstr "十月" -#: glib/gdatetime.c:575 +#: glib/gdatetime.c:569 msgctxt "abbreviated month name with day" msgid "Nov" msgstr "十一月" -#: glib/gdatetime.c:577 +#: glib/gdatetime.c:571 msgctxt "abbreviated month name with day" msgid "Dec" msgstr "十二月" #. Translators: 'before midday' indicator -#: glib/gdatetime.c:594 +#: glib/gdatetime.c:588 msgctxt "GDateTime" msgid "AM" msgstr "上午" #. Translators: 'after midday' indicator -#: glib/gdatetime.c:597 +#: glib/gdatetime.c:591 msgctxt "GDateTime" msgid "PM" msgstr "下午" @@ -4806,176 +4710,176 @@ msgstr "檔案「%s」太過巨大" msgid "Failed to read from file “%s”: %s" msgstr "讀取檔案「%s」失敗:%s" -#: glib/gfileutils.c:904 glib/gfileutils.c:979 glib/gfileutils.c:1476 +#: glib/gfileutils.c:902 glib/gfileutils.c:974 glib/gfileutils.c:1466 #, c-format msgid "Failed to open file “%s”: %s" msgstr "開啟檔案「%s」失敗:%s" -#: glib/gfileutils.c:917 +#: glib/gfileutils.c:914 #, c-format msgid "Failed to get attributes of file “%s”: fstat() failed: %s" msgstr "獲取檔案「%s」的特性失敗:fstat() 失敗:%s" -#: glib/gfileutils.c:948 +#: glib/gfileutils.c:944 #, c-format msgid "Failed to open file “%s”: fdopen() failed: %s" msgstr "開啟檔案「%s」失敗:fdopen() 失敗:%s" -#: glib/gfileutils.c:1049 +#: glib/gfileutils.c:1044 #, c-format msgid "Failed to rename file “%s” to “%s”: g_rename() failed: %s" msgstr "檔案名稱由「%s」改為「%s」失敗:g_rename() 失敗:%s" -#: glib/gfileutils.c:1175 +#: glib/gfileutils.c:1169 #, c-format msgid "Failed to write file “%s”: write() failed: %s" msgstr "無法寫入檔案「%s」:write() 失敗:%s" -#: glib/gfileutils.c:1196 +#: glib/gfileutils.c:1189 #, c-format msgid "Failed to write file “%s”: fsync() failed: %s" msgstr "無法寫入檔案「%s」:fsync() 失敗:%s" -#: glib/gfileutils.c:1365 glib/gfileutils.c:1780 +#: glib/gfileutils.c:1357 glib/gfileutils.c:1769 #, c-format msgid "Failed to create file “%s”: %s" msgstr "建立檔案「%s」失敗:%s" -#: glib/gfileutils.c:1410 +#: glib/gfileutils.c:1401 #, c-format msgid "Existing file “%s” could not be removed: g_unlink() failed: %s" msgstr "現存檔案「%s」無法移除:g_unlink() 失敗:%s" -#: glib/gfileutils.c:1745 +#: glib/gfileutils.c:1735 #, c-format msgid "Template “%s” invalid, should not contain a “%s”" msgstr "範本「%s」無效,不應含有「%s」" # (Abel) this is file template for mktemp/mkstemp -#: glib/gfileutils.c:1758 +#: glib/gfileutils.c:1748 #, c-format msgid "Template “%s” doesn’t contain XXXXXX" msgstr "範本「%s」沒有包含 XXXXXX" -#: glib/gfileutils.c:2318 glib/gfileutils.c:2347 +#: glib/gfileutils.c:2306 glib/gfileutils.c:2334 #, c-format msgid "Failed to read the symbolic link “%s”: %s" msgstr "讀取符號連結「%s」失敗:%s" -#: glib/giochannel.c:1405 +#: glib/giochannel.c:1396 #, c-format msgid "Could not open converter from “%s” to “%s”: %s" msgstr "無法開啟將「%s」轉換至「%s」的轉換器:%s" -#: glib/giochannel.c:1758 +#: glib/giochannel.c:1749 msgid "Can’t do a raw read in g_io_channel_read_line_string" msgstr "在 g_io_channel_read_line_string 中無法讀取原始資料" -#: glib/giochannel.c:1805 glib/giochannel.c:2063 glib/giochannel.c:2150 +#: glib/giochannel.c:1796 glib/giochannel.c:2054 glib/giochannel.c:2141 msgid "Leftover unconverted data in read buffer" msgstr "用來讀取資料的緩衝區中仍有未轉換的資料" -#: glib/giochannel.c:1886 glib/giochannel.c:1963 +#: glib/giochannel.c:1877 glib/giochannel.c:1954 msgid "Channel terminates in a partial character" msgstr "在字元未完整之前,輸入管道已經結束" -#: glib/giochannel.c:1949 +#: glib/giochannel.c:1940 msgid "Can’t do a raw read in g_io_channel_read_to_end" msgstr "在 g_io_channel_read_to_end 中無法讀取原始資料" -#: glib/gkeyfile.c:790 +#: glib/gkeyfile.c:789 msgid "Valid key file could not be found in search dirs" msgstr "在資料目錄中找不到有效的鍵檔案" -#: glib/gkeyfile.c:827 +#: glib/gkeyfile.c:826 msgid "Not a regular file" msgstr "不是正規的檔案" -#: glib/gkeyfile.c:1282 +#: glib/gkeyfile.c:1275 #, c-format msgid "" "Key file contains line “%s” which is not a key-value pair, group, or comment" msgstr "鍵檔案中「%s」行並非鍵值配對、群組或註解" -#: glib/gkeyfile.c:1339 +#: glib/gkeyfile.c:1332 #, c-format msgid "Invalid group name: %s" msgstr "無效的群組名稱:%s" -#: glib/gkeyfile.c:1361 +#: glib/gkeyfile.c:1354 msgid "Key file does not start with a group" msgstr "鍵檔案並非以群組開頭" -#: glib/gkeyfile.c:1387 +#: glib/gkeyfile.c:1380 #, c-format msgid "Invalid key name: %s" msgstr "無效的鍵名稱:%s" -#: glib/gkeyfile.c:1414 +#: glib/gkeyfile.c:1407 #, c-format msgid "Key file contains unsupported encoding “%s”" msgstr "鍵檔案包含不支援的編碼「%s」" -#: glib/gkeyfile.c:1663 glib/gkeyfile.c:1836 glib/gkeyfile.c:3289 -#: glib/gkeyfile.c:3353 glib/gkeyfile.c:3483 glib/gkeyfile.c:3615 -#: glib/gkeyfile.c:3761 glib/gkeyfile.c:3996 glib/gkeyfile.c:4063 +#: glib/gkeyfile.c:1650 glib/gkeyfile.c:1823 glib/gkeyfile.c:3276 +#: glib/gkeyfile.c:3340 glib/gkeyfile.c:3470 glib/gkeyfile.c:3602 +#: glib/gkeyfile.c:3748 glib/gkeyfile.c:3977 glib/gkeyfile.c:4044 #, c-format msgid "Key file does not have group “%s”" msgstr "鍵檔案沒有群組「%s」" -#: glib/gkeyfile.c:1791 +#: glib/gkeyfile.c:1778 #, c-format msgid "Key file does not have key “%s” in group “%s”" msgstr "鍵檔案的「%2$s」群組中沒有「%1$s」鍵" -#: glib/gkeyfile.c:1953 glib/gkeyfile.c:2069 +#: glib/gkeyfile.c:1940 glib/gkeyfile.c:2056 #, c-format msgid "Key file contains key “%s” with value “%s” which is not UTF-8" msgstr "鍵檔案包含的「%s」鍵(值為「%s」)並非 UTF-8" -#: glib/gkeyfile.c:1973 glib/gkeyfile.c:2089 glib/gkeyfile.c:2531 +#: glib/gkeyfile.c:1960 glib/gkeyfile.c:2076 glib/gkeyfile.c:2518 #, c-format msgid "" "Key file contains key “%s” which has a value that cannot be interpreted." msgstr "鍵檔案包含的「%s」鍵的值無法解譯。" -#: glib/gkeyfile.c:2749 glib/gkeyfile.c:3118 +#: glib/gkeyfile.c:2736 glib/gkeyfile.c:3105 #, c-format msgid "" "Key file contains key “%s” in group “%s” which has a value that cannot be " "interpreted." msgstr "鍵檔案包含的「%2$s」群組中「%1$s」鍵的值無法解譯。" -#: glib/gkeyfile.c:2827 glib/gkeyfile.c:2904 +#: glib/gkeyfile.c:2814 glib/gkeyfile.c:2891 #, c-format msgid "Key “%s” in group “%s” has value “%s” where %s was expected" msgstr "「%2$s」群組中的「%1$s」鍵包含「%3$s」值,但預期為「%4$s」" -#: glib/gkeyfile.c:4306 +#: glib/gkeyfile.c:4284 msgid "Key file contains escape character at end of line" msgstr "鍵檔案在行尾包含跳出字元" -#: glib/gkeyfile.c:4328 +#: glib/gkeyfile.c:4306 #, c-format msgid "Key file contains invalid escape sequence “%s”" msgstr "鍵檔案含有不正確的「跳出字元」「%s」" -#: glib/gkeyfile.c:4472 +#: glib/gkeyfile.c:4450 #, c-format msgid "Value “%s” cannot be interpreted as a number." msgstr "「%s」值不能被解譯為數字。" -#: glib/gkeyfile.c:4486 +#: glib/gkeyfile.c:4464 #, c-format msgid "Integer value “%s” out of range" msgstr "整數值「%s」超出範圍" -#: glib/gkeyfile.c:4519 +#: glib/gkeyfile.c:4497 #, c-format msgid "Value “%s” cannot be interpreted as a float number." msgstr "「%s」值不能被解譯為浮點數。" -#: glib/gkeyfile.c:4558 +#: glib/gkeyfile.c:4536 #, c-format msgid "Value “%s” cannot be interpreted as a boolean." msgstr "「%s」值不能被解譯為布林值。" @@ -5636,82 +5540,82 @@ msgstr "字串完結前仍沒有對應於 %c 的引號 (字串為「%s」)" msgid "Text was empty (or contained only whitespace)" msgstr "文字是空白的(或只含有空白字元)" -#: glib/gspawn.c:318 +#: glib/gspawn.c:323 #, c-format msgid "Failed to read data from child process (%s)" msgstr "無法從副進程讀取資料 (%s)" -#: glib/gspawn.c:465 +#: glib/gspawn.c:468 #, c-format msgid "Unexpected error in reading data from a child process (%s)" msgstr "從子程序 (%s) 讀取資料時發生未預期的錯誤" -#: glib/gspawn.c:550 +#: glib/gspawn.c:553 #, c-format msgid "Unexpected error in waitpid() (%s)" msgstr "waitpid() 發生未預期的錯誤 (%s)" -#: glib/gspawn.c:1154 glib/gspawn-win32.c:1383 +#: glib/gspawn.c:1061 glib/gspawn-win32.c:1329 #, c-format msgid "Child process exited with code %ld" msgstr "子程序以代碼 %ld 結束" -#: glib/gspawn.c:1162 +#: glib/gspawn.c:1069 #, c-format msgid "Child process killed by signal %ld" msgstr "子程序被信號 %ld 中止" -#: glib/gspawn.c:1169 +#: glib/gspawn.c:1076 #, c-format msgid "Child process stopped by signal %ld" msgstr "子程序被信號 %ld 停止" -#: glib/gspawn.c:1176 +#: glib/gspawn.c:1083 #, c-format msgid "Child process exited abnormally" msgstr "子程序異常結束" -#: glib/gspawn.c:1767 glib/gspawn-win32.c:350 glib/gspawn-win32.c:358 +#: glib/gspawn.c:1532 glib/gspawn-win32.c:350 glib/gspawn-win32.c:358 #, c-format msgid "Failed to read from child pipe (%s)" msgstr "無法從管道讀取資料 (%s)" -#: glib/gspawn.c:2069 +#: glib/gspawn.c:1788 #, c-format msgid "Failed to spawn child process “%s” (%s)" msgstr "無法產生副程序「%s」(%s)" -#: glib/gspawn.c:2186 +#: glib/gspawn.c:1871 #, c-format msgid "Failed to fork (%s)" msgstr "無法衍生進程 (%s)" -#: glib/gspawn.c:2346 glib/gspawn-win32.c:381 +#: glib/gspawn.c:2026 glib/gspawn-win32.c:381 #, c-format msgid "Failed to change to directory “%s” (%s)" msgstr "無法進入目錄「%s」(%s)" -#: glib/gspawn.c:2356 +#: glib/gspawn.c:2036 #, c-format msgid "Failed to execute child process “%s” (%s)" msgstr "無法執行副程序「%s」(%s)" -#: glib/gspawn.c:2366 +#: glib/gspawn.c:2046 #, c-format msgid "Failed to redirect output or input of child process (%s)" msgstr "無法將副進程的輸出或輸入重新導向 (%s)" -#: glib/gspawn.c:2375 +#: glib/gspawn.c:2055 #, c-format msgid "Failed to fork child process (%s)" msgstr "無法衍生副進程 (%s)" -#: glib/gspawn.c:2383 +#: glib/gspawn.c:2063 #, c-format msgid "Unknown error executing child process “%s”" msgstr "執行副程序「%s」時發生不明的錯誤" -#: glib/gspawn.c:2407 +#: glib/gspawn.c:2087 #, c-format msgid "Failed to read enough data from child pid pipe (%s)" msgstr "無法從 child pid pipe 讀取足夠的資料 (%s)" @@ -5735,104 +5639,99 @@ msgstr "無法執行副進程 (%s)" msgid "Invalid program name: %s" msgstr "程式名稱無效:%s" -#: glib/gspawn-win32.c:471 glib/gspawn-win32.c:757 +#: glib/gspawn-win32.c:471 glib/gspawn-win32.c:725 #, c-format msgid "Invalid string in argument vector at %d: %s" msgstr "第 %d 個引數向量中含無效的字串:%s" -#: glib/gspawn-win32.c:482 glib/gspawn-win32.c:772 +#: glib/gspawn-win32.c:482 glib/gspawn-win32.c:740 #, c-format msgid "Invalid string in environment: %s" msgstr "環境變數中的字串無效:%s" -#: glib/gspawn-win32.c:753 +#: glib/gspawn-win32.c:721 #, c-format msgid "Invalid working directory: %s" msgstr "無效的工作目錄:%s" -#: glib/gspawn-win32.c:815 +#: glib/gspawn-win32.c:783 #, c-format msgid "Failed to execute helper program (%s)" msgstr "無法執行協助程式 (%s)" -#: glib/gspawn-win32.c:1042 +#: glib/gspawn-win32.c:1056 msgid "" "Unexpected error in g_io_channel_win32_poll() reading data from a child " "process" msgstr "當 g_io_channel_win32_poll() 從副進程讀取資料時發生無法預計的錯誤" -#: glib/gstrfuncs.c:3338 glib/gstrfuncs.c:3440 +#: glib/gstrfuncs.c:3303 glib/gstrfuncs.c:3405 msgid "Empty string is not a number" msgstr "空字串不是數字" -#: glib/gstrfuncs.c:3362 +#: glib/gstrfuncs.c:3327 #, c-format msgid "“%s” is not a signed number" msgstr "「%s」不是有號數字" -#: glib/gstrfuncs.c:3372 glib/gstrfuncs.c:3476 +#: glib/gstrfuncs.c:3337 glib/gstrfuncs.c:3441 #, c-format msgid "Number “%s” is out of bounds [%s, %s]" msgstr "「%s」數字超出範圍 [%s, %s]" -#: glib/gstrfuncs.c:3466 +#: glib/gstrfuncs.c:3431 #, c-format msgid "“%s” is not an unsigned number" msgstr "「%s」不是無號數字" -#: glib/guri.c:315 +#: glib/guri.c:313 #, no-c-format msgid "Invalid %-encoding in URI" msgstr "URI 中有無效的 %-編碼" -#: glib/guri.c:332 +#: glib/guri.c:330 msgid "Illegal character in URI" msgstr "URI 中有不合規的字元" -#: glib/guri.c:366 +#: glib/guri.c:359 msgid "Non-UTF-8 characters in URI" msgstr "URI 中有非 UTF-8 字元" -#: glib/guri.c:546 +#: glib/guri.c:533 #, c-format msgid "Invalid IPv6 address ‘%.*s’ in URI" msgstr "URI 中有無效的 IPv6 位址「%.*s」" -#: glib/guri.c:601 +#: glib/guri.c:588 #, c-format msgid "Illegal encoded IP address ‘%.*s’ in URI" msgstr "URI 中有不合規的編碼 IP 位址「%.*s」" -#: glib/guri.c:613 -#, c-format -msgid "Illegal internationalized hostname ‘%.*s’ in URI" -msgstr "URI 中有不合規的國際化主機名稱「%.*s」" - -#: glib/guri.c:645 glib/guri.c:657 +#: glib/guri.c:620 glib/guri.c:632 #, c-format msgid "Could not parse port ‘%.*s’ in URI" msgstr "無法解析 URI 中的「%.*s」連接埠" -#: glib/guri.c:664 +#: glib/guri.c:639 #, c-format msgid "Port ‘%.*s’ in URI is out of range" msgstr "URI 中的「%.*s」連接埠超出範圍" -#: glib/guri.c:1224 glib/guri.c:1288 +#: glib/guri.c:1119 glib/guri.c:1183 #, c-format msgid "URI ‘%s’ is not an absolute URI" msgstr "「%s」URI 不是絕對路徑 URI" -#: glib/guri.c:1230 +#: glib/guri.c:1125 #, c-format msgid "URI ‘%s’ has no host component" msgstr "「%s」URI 沒有主機部分" -#: glib/guri.c:1435 +#: glib/guri.c:1330 msgid "URI is not absolute, and no base URI was provided" msgstr "URI 不是絕對路徑,且沒有提供基礎 URI" -#: glib/guri.c:2209 +#: glib/guri.c:2082 msgid "Missing ‘=’ and parameter value" msgstr "缺失「=」與參數值" @@ -5854,170 +5753,170 @@ msgid "Character out of range for UTF-16" msgstr "字元不在 UTF-16 範圍之內" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2767 +#: glib/gutils.c:2759 #, c-format msgid "%.1f kB" msgstr "%.1f kB" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2769 +#: glib/gutils.c:2761 #, c-format msgid "%.1f MB" msgstr "%.1f MB" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2771 +#: glib/gutils.c:2763 #, c-format msgid "%.1f GB" msgstr "%.1f GB" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2773 +#: glib/gutils.c:2765 #, c-format msgid "%.1f TB" msgstr "%.1f TB" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2775 +#: glib/gutils.c:2767 #, c-format msgid "%.1f PB" msgstr "%.1f PB" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2777 +#: glib/gutils.c:2769 #, c-format msgid "%.1f EB" msgstr "%.1f EB" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2781 +#: glib/gutils.c:2773 #, c-format msgid "%.1f KiB" msgstr "%.1f KiB" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2783 +#: glib/gutils.c:2775 #, c-format msgid "%.1f MiB" msgstr "%.1f MiB" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2785 +#: glib/gutils.c:2777 #, c-format msgid "%.1f GiB" msgstr "%.1f GiB" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2787 +#: glib/gutils.c:2779 #, c-format msgid "%.1f TiB" msgstr "%.1f TiB" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2789 +#: glib/gutils.c:2781 #, c-format msgid "%.1f PiB" msgstr "%.1f PiB" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2791 +#: glib/gutils.c:2783 #, c-format msgid "%.1f EiB" msgstr "%.1f EiB" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2795 +#: glib/gutils.c:2787 #, c-format msgid "%.1f kb" msgstr "%.1f kb" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2797 +#: glib/gutils.c:2789 #, c-format msgid "%.1f Mb" msgstr "%.1f Mb" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2799 +#: glib/gutils.c:2791 #, c-format msgid "%.1f Gb" msgstr "%.1f Gb" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2801 +#: glib/gutils.c:2793 #, c-format msgid "%.1f Tb" msgstr "%.1f Tb" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2803 +#: glib/gutils.c:2795 #, c-format msgid "%.1f Pb" msgstr "%.1f Pb" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2805 +#: glib/gutils.c:2797 #, c-format msgid "%.1f Eb" msgstr "%.1f Eb" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2809 +#: glib/gutils.c:2801 #, c-format msgid "%.1f Kib" msgstr "%.1f Kib" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2811 +#: glib/gutils.c:2803 #, c-format msgid "%.1f Mib" msgstr "%.1f Mib" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2813 +#: glib/gutils.c:2805 #, c-format msgid "%.1f Gib" msgstr "%.1f Gib" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2815 +#: glib/gutils.c:2807 #, c-format msgid "%.1f Tib" msgstr "%.1f Tib" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2817 +#: glib/gutils.c:2809 #, c-format msgid "%.1f Pib" msgstr "%.1f Pib" #. Translators: Keep the no-break space between %.1f and the unit symbol -#: glib/gutils.c:2819 +#: glib/gutils.c:2811 #, c-format msgid "%.1f Eib" msgstr "%.1f Eib" -#: glib/gutils.c:2853 glib/gutils.c:2970 +#: glib/gutils.c:2845 glib/gutils.c:2962 #, c-format msgid "%u byte" msgid_plural "%u bytes" msgstr[0] "%u 位元組" -#: glib/gutils.c:2857 +#: glib/gutils.c:2849 #, c-format msgid "%u bit" msgid_plural "%u bits" msgstr[0] "%u 位元" #. Translators: the %s in "%s bytes" will always be replaced by a number. -#: glib/gutils.c:2924 +#: glib/gutils.c:2916 #, c-format msgid "%s byte" msgid_plural "%s bytes" msgstr[0] "%s 位元組" #. Translators: the %s in "%s bits" will always be replaced by a number. -#: glib/gutils.c:2929 +#: glib/gutils.c:2921 #, c-format msgid "%s bit" msgid_plural "%s bits" @@ -6028,42 +5927,36 @@ msgstr[0] "%s 位元" #. * compatibility. Users will not see this string unless a program is using this deprecated function. #. * Please translate as literally as possible. #. -#: glib/gutils.c:2983 +#: glib/gutils.c:2975 #, c-format msgid "%.1f KB" msgstr "%.1f KB" -#: glib/gutils.c:2988 +#: glib/gutils.c:2980 #, c-format msgid "%.1f MB" msgstr "%.1f MB" -#: glib/gutils.c:2993 +#: glib/gutils.c:2985 #, c-format msgid "%.1f GB" msgstr "%.1f GB" -#: glib/gutils.c:2998 +#: glib/gutils.c:2990 #, c-format msgid "%.1f TB" msgstr "%.1f TB" -#: glib/gutils.c:3003 +#: glib/gutils.c:2995 #, c-format msgid "%.1f PB" msgstr "%.1f PB" -#: glib/gutils.c:3008 +#: glib/gutils.c:3000 #, c-format msgid "%.1f EB" msgstr "%.1f EB" -#~ msgid "Unable to load /var/lib/dbus/machine-id or /etc/machine-id: " -#~ msgstr "無法載入 /var/lib/dbus/machine-id 或 /etc/machine-id:" - -#~ msgid "Unknown error on connect" -#~ msgstr "連線時有不明的錯誤" - #~ msgid "Error in address “%s” — the family attribute is malformed" #~ msgstr "位址「%s」有錯誤 — family 屬性的格式不良" @@ -6111,6 +6004,9 @@ msgstr "%.1f EB" #~ msgid "Error: signal must be the fully-qualified name.\n" #~ msgstr "錯誤:信號必須為完全合規定的名稱。\n" +#~ msgid "No files given" +#~ msgstr "尚未指定檔案" + #~ msgid "Error getting writable attributes: %s\n" #~ msgstr "取得可寫入屬性時發生錯誤:%s\n" diff --git a/subprojects/gtk-doc.wrap b/subprojects/gtk-doc.wrap index 79ec37220..0490a03a1 100644 --- a/subprojects/gtk-doc.wrap +++ b/subprojects/gtk-doc.wrap @@ -1,5 +1,5 @@ [wrap-git] directory=gtk-doc url=https://gitlab.gnome.org/GNOME/gtk-doc.git -revision=master +revision=1.33.2 depth=1 diff --git a/subprojects/libpcre.wrap b/subprojects/libpcre.wrap new file mode 100644 index 000000000..e27a198ec --- /dev/null +++ b/subprojects/libpcre.wrap @@ -0,0 +1,11 @@ +[wrap-file] +directory = pcre-8.37 +source_url = https://ftp.pcre.org/pub/pcre/pcre-8.37.tar.bz2 +source_filename = pcre-8.37.tar.bz2 +source_hash = 51679ea8006ce31379fb0860e46dd86665d864b5020fc9cd19e71260eef4789d +patch_filename = pcre_8.37-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/pcre_8.37-2/get_patch +patch_hash = 6b80f72385e1bf06721e26fbc83aced576e9c0d3182d86a55dd173a04050fe26 + +[provide] +libpcre = pcre_dep diff --git a/tests/dirname-test.c b/tests/dirname-test.c index 52a4678f1..81c55d56d 100644 --- a/tests/dirname-test.c +++ b/tests/dirname-test.c @@ -53,7 +53,7 @@ int main (int argc, char *argv[]) { - gint i; + gsize i; struct { gchar *filename; gchar *dirname; @@ -100,9 +100,8 @@ main (int argc, { "a:\\/", "a:\\" }, #endif }; - guint n_dirname_checks = sizeof (dirname_checks) / sizeof (dirname_checks[0]); - for (i = 0; i < n_dirname_checks; i++) + for (i = 0; i < G_N_ELEMENTS (dirname_checks); i++) { gchar *dirname; diff --git a/tests/gio-test.c b/tests/gio-test.c index deffa4d09..6c40632b3 100644 --- a/tests/gio-test.c +++ b/tests/gio-test.c @@ -130,7 +130,8 @@ recv_message (GIOChannel *channel, char buf[BUFSIZE]; guint nbytes; guint nb; - int i, j, seq; + guint j; + int i, seq; GIOError error; error = read_all (fd, channel, (gchar *) &seq, sizeof (seq), &nb); @@ -169,7 +170,7 @@ recv_message (GIOChannel *channel, g_assert (nb == sizeof (nbytes)); g_assert_cmpint (nbytes, <, BUFSIZE); - g_assert (nbytes >= 0 && nbytes < BUFSIZE); + g_assert (nbytes < BUFSIZE); g_debug ("gio-test: ...from %d: %d bytes", fd, nbytes); if (nbytes > 0) { @@ -186,7 +187,7 @@ recv_message (GIOChannel *channel, } for (j = 0; j < nbytes; j++) - g_assert (buf[j] == ' ' + ((nbytes + j) % 95)); + g_assert (buf[j] == ' ' + (char) ((nbytes + j) % 95)); g_debug ("gio-test: ...from %d: OK", fd); } } diff --git a/tests/gobject/defaultiface.c b/tests/gobject/defaultiface.c index eccb79ced..92e45cefb 100644 --- a/tests/gobject/defaultiface.c +++ b/tests/gobject/defaultiface.c @@ -122,7 +122,12 @@ test_dynamic_iface_register (GTypeModule *module) (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) test_dynamic_iface_default_init, - (GClassFinalizeFunc) test_dynamic_iface_default_finalize + (GClassFinalizeFunc) test_dynamic_iface_default_finalize, + NULL, + 0, + 0, + NULL, + NULL }; test_dynamic_iface_type = g_type_module_register_type (module, G_TYPE_INTERFACE, diff --git a/tests/gobject/performance-threaded.c b/tests/gobject/performance-threaded.c index c98541d66..af8cc79b0 100644 --- a/tests/gobject/performance-threaded.c +++ b/tests/gobject/performance-threaded.c @@ -197,7 +197,7 @@ static const PerformanceTest tests[] = { }; static gboolean verbose = FALSE; -static int n_threads = 0; +static guint n_threads = 0; static gboolean list = FALSE; static int test_length = DEFAULT_TEST_TIME; @@ -210,7 +210,7 @@ static GOptionEntry cmd_entries[] = { "Time to run each test in seconds", NULL}, {"list", 'l', 0, G_OPTION_ARG_NONE, &list, "List all available tests and exit", NULL}, - {NULL} + G_OPTION_ENTRY_NULL }; static gpointer @@ -320,7 +320,7 @@ run_test (const PerformanceTest *test) static const PerformanceTest * find_test (const char *name) { - int i; + gsize i; for (i = 0; i < G_N_ELEMENTS (tests); i++) { if (strcmp (tests[i].name, name) == 0) @@ -336,7 +336,7 @@ main (int argc, const PerformanceTest *test; GOptionContext *context; GError *error = NULL; - int i; + gsize i; context = g_option_context_new ("GObject performance tests"); g_option_context_add_main_entries (context, cmd_entries, NULL); @@ -357,9 +357,10 @@ main (int argc, if (argc > 1) { - for (i = 1; i < argc; i++) + int k; + for (k = 1; k < argc; k++) { - test = find_test (argv[i]); + test = find_test (argv[k]); if (test) run_test (test); } diff --git a/tests/gobject/performance.c b/tests/gobject/performance.c index 163be58b4..5208172bd 100644 --- a/tests/gobject/performance.c +++ b/tests/gobject/performance.c @@ -37,7 +37,7 @@ static GOptionEntry cmd_entries[] = { "Print extra information", NULL}, {"seconds", 's', 0, G_OPTION_ARG_INT, &test_length, "Time to run each test in seconds", NULL}, - {NULL} + G_OPTION_ENTRY_NULL }; typedef struct _PerformanceTest PerformanceTest; @@ -1015,7 +1015,7 @@ static PerformanceTest tests[] = { static PerformanceTest * find_test (const char *name) { - int i; + gsize i; for (i = 0; i < G_N_ELEMENTS (tests); i++) { if (strcmp (tests[i].name, name) == 0) @@ -1051,8 +1051,9 @@ main (int argc, } else { - for (i = 0; i < G_N_ELEMENTS (tests); i++) - run_test (&tests[i]); + gsize k; + for (k = 0; k < G_N_ELEMENTS (tests); k++) + run_test (&tests[k]); } return 0; diff --git a/tests/gobject/references.c b/tests/gobject/references.c index 8c1266042..36ff35c63 100644 --- a/tests/gobject/references.c +++ b/tests/gobject/references.c @@ -256,7 +256,8 @@ main (int argc, g_assert (object_destroyed == FALSE); clear_flags (); - g_object_remove_toggle_ref (object, toggle_ref2, GUINT_TO_POINTER (24)); + /* Check that removing a toggle ref with %NULL data works fine. */ + g_object_remove_toggle_ref (object, toggle_ref2, NULL); g_assert (toggle_ref1_weakened == FALSE); g_assert (toggle_ref1_strengthened == FALSE); g_assert (toggle_ref2_weakened == FALSE); diff --git a/tests/gobject/testcommon.h b/tests/gobject/testcommon.h index a5b59b3d3..3e40cca67 100644 --- a/tests/gobject/testcommon.h +++ b/tests/gobject/testcommon.h @@ -40,7 +40,8 @@ prefix ## _get_type (void) \ NULL, /* class_data */ \ sizeof (name), \ 0, /* n_prelocs */ \ - (GInstanceInitFunc) instance_init \ + (GInstanceInitFunc) instance_init, \ + (const GTypeValueTable *) NULL, \ }; \ \ object_type = g_type_register_static (parent_type, \ @@ -72,6 +73,12 @@ prefix ## _get_type (void) \ (GBaseInitFunc) base_init, \ (GBaseFinalizeFunc) NULL, \ (GClassInitFunc) dflt_init, \ + (GClassFinalizeFunc) NULL, \ + (gconstpointer) NULL, \ + (guint16) 0, \ + (guint16) 0, \ + (GInstanceInitFunc) NULL, \ + (const GTypeValueTable*) NULL, \ }; \ \ iface_type = g_type_register_static (G_TYPE_INTERFACE, \ diff --git a/tests/gobject/testgobject.c b/tests/gobject/testgobject.c index df7d4c748..e467abcd4 100644 --- a/tests/gobject/testgobject.c +++ b/tests/gobject/testgobject.c @@ -50,6 +50,13 @@ test_iface_get_type (void) sizeof (TestIfaceClass), (GBaseInitFunc) iface_base_init, /* base_init */ (GBaseFinalizeFunc) iface_base_finalize, /* base_finalize */ + NULL, + NULL, + NULL, + 0, + 0, + NULL, + NULL }; test_iface_type = g_type_register_static (G_TYPE_INTERFACE, "TestIface", &test_iface_info, 0); @@ -178,7 +185,8 @@ test_object_get_type (void) NULL, /* class_data */ sizeof (TestObject), 5, /* n_preallocs */ - (GInstanceInitFunc) test_object_init, + (GInstanceInitFunc) test_object_init, + NULL }; GInterfaceInfo iface_info = { test_object_test_iface_init, NULL, GUINT_TO_POINTER (42) }; @@ -345,7 +353,8 @@ derived_object_get_type (void) NULL, /* class_data */ sizeof (DerivedObject), 5, /* n_preallocs */ - (GInstanceInitFunc) derived_object_init, + (GInstanceInitFunc) derived_object_init, + NULL }; GInterfaceInfo iface_info = { derived_object_test_iface_init, NULL, GUINT_TO_POINTER (87) }; diff --git a/tests/gobject/timeloop-closure.c b/tests/gobject/timeloop-closure.c index c904c2a45..51dd6f105 100644 --- a/tests/gobject/timeloop-closure.c +++ b/tests/gobject/timeloop-closure.c @@ -33,7 +33,7 @@ io_pipe (GIOChannel **channels) } static gboolean -read_all (GIOChannel *channel, char *buf, int len) +read_all (GIOChannel *channel, char *buf, gsize len) { gsize bytes_read = 0; gsize count; @@ -57,7 +57,7 @@ read_all (GIOChannel *channel, char *buf, int len) } static gboolean -write_all (GIOChannel *channel, char *buf, int len) +write_all (GIOChannel *channel, char *buf, gsize len) { gsize bytes_written = 0; gsize count; diff --git a/tests/mainloop-test.c b/tests/mainloop-test.c index 5a3e6c989..be6024a10 100644 --- a/tests/mainloop-test.c +++ b/tests/mainloop-test.c @@ -352,10 +352,10 @@ create_crawler (void) static void cleanup_crawlers (GMainContext *context) { - gint i; + guint i; G_LOCK (crawler_array_lock); - for (i=0; i < crawler_array->len; i++) + for (i = 0; i < crawler_array->len; i++) { if (g_source_get_context (crawler_array->pdata[i]) == context) { diff --git a/tests/memchunks.c b/tests/memchunks.c index fae7c4107..f574ed8b0 100644 --- a/tests/memchunks.c +++ b/tests/memchunks.c @@ -49,7 +49,7 @@ static guint mem_chunk_recursion = 0; /* --- old memchunk prototypes --- */ GMemChunk* old_mem_chunk_new (const gchar *name, - gint atom_size, + gulong atom_size, gulong area_size, gint type); void old_mem_chunk_destroy (GMemChunk *mem_chunk); @@ -129,7 +129,7 @@ static GMemChunk *mem_chunks = NULL; GMemChunk* old_mem_chunk_new (const gchar *name, - gint atom_size, + gulong atom_size, gulong area_size, gint type) { diff --git a/tests/onceinit.c b/tests/onceinit.c index 9788efcbd..4f30739ca 100644 --- a/tests/onceinit.c +++ b/tests/onceinit.c @@ -259,7 +259,7 @@ stress_concurrent_initializers (void *user_data) LIST_256_TEST_INITIALIZERS (stress3), LIST_256_TEST_INITIALIZERS (stress4), }; - int i; + gsize i; /* sync to main thread */ g_mutex_lock (&tmutex); g_mutex_unlock (&tmutex); diff --git a/tests/refcount/objects.c b/tests/refcount/objects.c index 0c471a42b..06b871936 100644 --- a/tests/refcount/objects.c +++ b/tests/refcount/objects.c @@ -115,7 +115,7 @@ run_thread (GTest * test) int main (int argc, char **argv) { - gint i; + guint i; GTest *test1, *test2; GArray *test_threads; const guint n_threads = 5; diff --git a/tests/slice-threadinit.c b/tests/slice-threadinit.c index f29dcbed1..e303aa0b2 100644 --- a/tests/slice-threadinit.c +++ b/tests/slice-threadinit.c @@ -31,7 +31,7 @@ static struct { void *page; void *sample; -} pages[N_PAGES] = { { NULL, }, }; +} pages[N_PAGES] = { { NULL, NULL }, }; static const guint magazine_probes[] = MAGAZINE_PROBES; #define N_MAGAZINE_PROBES G_N_ELEMENTS (magazine_probes) @@ -70,7 +70,7 @@ int main (int argc, char *argv[]) { - int j, n_pages = 0; + gsize j, n_pages = 0; void *mps[N_MAGAZINE_PROBES]; /* probe some magazine sizes */ diff --git a/tests/testgdate.c b/tests/testgdate.c index cc1e7a972..371d8addf 100644 --- a/tests/testgdate.c +++ b/tests/testgdate.c @@ -27,7 +27,9 @@ if (failed) \ } \ else \ ++passed; \ - if ((passed+notpassed) % 10000 == 0) g_print ("."); fflush (stdout); \ +if ((passed+notpassed) % 10000 == 0) \ + g_print ("."); \ +fflush (stdout); \ } G_STMT_END static void diff --git a/tests/testglib.c b/tests/testglib.c index 86c807922..071afdc1d 100644 --- a/tests/testglib.c +++ b/tests/testglib.c @@ -78,7 +78,7 @@ static void glist_test (void) { GList *list = NULL; - guint i; + gint i; for (i = 0; i < 10; i++) list = g_list_append (list, &test_nums[i]); @@ -158,7 +158,7 @@ static void gslist_test (void) { GSList *slist = NULL; - guint i; + gint i; for (i = 0; i < 10; i++) slist = g_slist_append (slist, &test_nums[i]); @@ -299,11 +299,11 @@ gnode_test (void) for (i = 0; i < g_node_n_children (node_B); i++) { node = g_node_nth_child (node_B, i); - g_assert (P2C (node->data) == ('C' + i)); + g_assert (P2C (node->data) == (gchar) ('C' + i)); } for (i = 0; i < g_node_n_children (node_G); i++) - g_assert (g_node_child_position (node_G, g_node_nth_child (node_G, i)) == i); + g_assert (g_node_child_position (node_G, g_node_nth_child (node_G, i)) == (gint) i); /* we have built: A * / \ @@ -1313,7 +1313,7 @@ test_arrays (void) for (i = 0; i < 10000; i++) g_array_append_val (garray, i); for (i = 0; i < 10000; i++) - if (g_array_index (garray, gint, i) != i) + if (g_array_index (garray, gint, i) != (gint) i) g_error ("failure: %d ( %d )", g_array_index (garray, gint, i), i); g_array_free (garray, TRUE); @@ -1321,7 +1321,7 @@ test_arrays (void) for (i = 0; i < 100; i++) g_array_prepend_val (garray, i); for (i = 0; i < 100; i++) - if (g_array_index (garray, gint, i) != (100 - i - 1)) + if (g_array_index (garray, gint, i) != (gint) (100 - i - 1)) g_error ("failure: %d ( %d )", g_array_index (garray, gint, i), 100 - i - 1); g_array_free (garray, TRUE); } diff --git a/tests/thread-test.c b/tests/thread-test.c index 17ac41f7b..883aa5424 100644 --- a/tests/thread-test.c +++ b/tests/thread-test.c @@ -211,7 +211,7 @@ test_g_static_private (void) test_g_static_private_ready = 0; for (i = 0; i < THREADS; i++) - g_assert (GPOINTER_TO_INT (g_thread_join (threads[i])) == i * 3); + g_assert (GPOINTER_TO_UINT (g_thread_join (threads[i])) == i * 3); g_assert (test_g_static_private_counter == 0); } diff --git a/tests/threadpool-test.c b/tests/threadpool-test.c index dfd138212..1612e274e 100644 --- a/tests/threadpool-test.c +++ b/tests/threadpool-test.c @@ -248,7 +248,7 @@ test_thread_sort (gboolean sort) GThreadPool *pool; guint limit; guint max_threads; - gint i; + guint i; limit = MAX_THREADS * 10; @@ -293,8 +293,8 @@ test_thread_sort (gboolean sort) g_thread_pool_unprocessed (pool))); } - g_assert (g_thread_pool_get_max_threads (pool) == max_threads); - g_assert (g_thread_pool_get_num_threads (pool) == g_thread_pool_get_max_threads (pool)); + g_assert (g_thread_pool_get_max_threads (pool) == (gint) max_threads); + g_assert (g_thread_pool_get_num_threads (pool) == (guint) g_thread_pool_get_max_threads (pool)); g_thread_pool_free (pool, TRUE, TRUE); } @@ -337,7 +337,7 @@ test_thread_idle_time (void) { guint limit = 50; guint interval = 10000; - gint i; + guint i; idle_pool = g_thread_pool_new (test_thread_idle_time_entry_func, NULL, diff --git a/tests/timeloop.c b/tests/timeloop.c index 8b5aa3641..40064a140 100644 --- a/tests/timeloop.c +++ b/tests/timeloop.c @@ -32,7 +32,7 @@ io_pipe (GIOChannel **channels) } static gboolean -read_all (GIOChannel *channel, char *buf, int len) +read_all (GIOChannel *channel, char *buf, gsize len) { gsize bytes_read = 0; gsize count; @@ -56,7 +56,7 @@ read_all (GIOChannel *channel, char *buf, int len) } static gboolean -write_all (GIOChannel *channel, char *buf, int len) +write_all (GIOChannel *channel, char *buf, gsize len) { gsize bytes_written = 0; gsize count; diff --git a/tests/unicode-collate.c b/tests/unicode-collate.c index b276a2f67..8de3f60ca 100644 --- a/tests/unicode-collate.c +++ b/tests/unicode-collate.c @@ -74,7 +74,7 @@ int main (int argc, char **argv) } } - if (argc > i) + if (argc > (gint) i) { in = g_io_channel_new_file (argv[i], "r", &error); if (!in) diff --git a/tests/unicode-encoding.c b/tests/unicode-encoding.c index c729b284d..b0603d105 100644 --- a/tests/unicode-encoding.c +++ b/tests/unicode-encoding.c @@ -137,7 +137,7 @@ process (gint line, ucs4_result = g_utf8_to_ucs4 (utf8, -1, &items_read, NULL, &error); - if (!ucs4_result || items_read == strlen (utf8)) + if (!ucs4_result || items_read == (glong) strlen (utf8)) { fail ("line %d: incomplete input not properly detected\n", line); return; @@ -158,7 +158,7 @@ process (gint line, } if (!ucs4_equal (ucs4_result, ucs4) || - items_read != strlen (utf8) || + items_read != (glong) strlen (utf8) || items_written != ucs4_len) { fail ("line %d: results of conversion with status %d to ucs4 do not match expected.\n", line, status); @@ -195,7 +195,7 @@ process (gint line, if (strcmp (utf8_result, utf8) != 0 || items_read != ucs4_len || - items_written != strlen (utf8)) + items_written != (glong) strlen (utf8)) { fail ("line %d: conversion back to utf8 did not match original\n", line); return; @@ -257,7 +257,7 @@ process (gint line, return; } - if (items_read != strlen (utf8) || + if (items_read != (glong) strlen (utf8) || utf16_count (utf16_from_utf8) != items_written) { fail ("line %d: length error in conversion to ucs16\n", line); @@ -291,7 +291,7 @@ process (gint line, } if (items_read != utf16_count (utf16_from_utf8) || - items_written != strlen (utf8)) + items_written != (glong) strlen (utf8)) { fail ("line %d: length error in conversion from ucs16 to utf8\n", line); return; |