summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author Patrick J Volkerding <volkerdi@slackware.com>2024-06-10 19:23:44 +0000
committer Eric Hameleers <alien@slackware.com>2024-06-10 22:00:40 +0200
commit167022426ded1dbe807f8b493e6330412e2d4de1 (patch)
tree5d39e4a289417cc23f7976caba4e76931ecfe4cd
parent5e846dcebfaa9dc5c6d06421b1097b9969c8285e (diff)
downloadcurrent-167022426ded1dbe807f8b493e6330412e2d4de1.tar.gz
current-167022426ded1dbe807f8b493e6330412e2d4de1.tar.xz
Mon Jun 10 19:23:44 UTC 202420240610192344
ap/stow-2.4.0-x86_64-1.txz: Added. Thanks to r1w1s1. ap/texinfo-7.1-x86_64-2.txz: Rebuilt. Recompiled against perl-5.40.0. ap/vim-9.1.0473-x86_64-1.txz: Upgraded. Compiled against perl-5.40.0. d/ccache-4.10-x86_64-2.txz: Rebuilt. Avoid downloading doctest.h at build time. Thanks to lucabon. d/perl-5.40.0-x86_64-1.txz: Upgraded. Upgraded: DBD-mysql-4.052, Path-Tiny-0.146, URI-5.28. d/subversion-1.14.3-x86_64-2.txz: Rebuilt. Recompiled against perl-5.40.0. kde/plasma-workspace-5.27.11.1-x86_64-2.txz: Rebuilt. [PATCH] Fix writing ICEAuthority file. l/glib2-2.80.3-x86_64-1.txz: Upgraded. l/imagemagick-7.1.1_33-x86_64-2.txz: Rebuilt. Recompiled against perl-5.40.0. l/pango-1.54.0-x86_64-1.txz: Upgraded. l/python-packaging-24.1-x86_64-1.txz: Upgraded. n/epic5-2.1.12-x86_64-9.txz: Rebuilt. Recompiled against perl-5.40.0. n/irssi-1.4.5-x86_64-3.txz: Rebuilt. Recompiled against perl-5.40.0. n/net-snmp-5.9.4-x86_64-5.txz: Rebuilt. Recompiled against perl-5.40.0. n/ntp-4.2.8p18-x86_64-3.txz: Rebuilt. Recompiled against perl-5.40.0. n/openldap-2.6.8-x86_64-2.txz: Rebuilt. Recompiled against perl-5.40.0. xap/hexchat-2.16.2-x86_64-3.txz: Rebuilt. Recompiled against perl-5.40.0. xap/pidgin-2.14.13-x86_64-2.txz: Rebuilt. Recompiled against perl-5.40.0. xap/rxvt-unicode-9.31-x86_64-3.txz: Rebuilt. Recompiled against perl-5.40.0. xap/vim-gvim-9.1.0473-x86_64-1.txz: Upgraded. Compiled against perl-5.40.0. xap/xscreensaver-6.09-x86_64-1.txz: Upgraded. xfce/xfce4-power-manager-4.18.4-x86_64-1.txz: Upgraded. xfce/xfce4-session-4.18.4-x86_64-1.txz: Upgraded.
-rw-r--r--ChangeLog.rss54
-rw-r--r--ChangeLog.txt42
-rw-r--r--FILELIST.TXT346
-rwxr-xr-xrecompress.sh2
-rw-r--r--slackware64/ap/maketag5
-rw-r--r--slackware64/ap/maketag.ez5
-rw-r--r--slackware64/ap/tagfile1
-rw-r--r--slackware64/kde/maketag2
-rw-r--r--slackware64/kde/maketag.ez2
-rw-r--r--slackware64/x/maketag6
-rw-r--r--slackware64/x/maketag.ez6
-rw-r--r--source/ap/stow/slack-desc19
-rwxr-xr-xsource/ap/stow/stow.SlackBuild154
-rwxr-xr-xsource/ap/texinfo/texinfo.SlackBuild2
-rwxr-xr-xsource/d/ccache/ccache.SlackBuild12
-rw-r--r--source/d/ccache/doctest.h7106
-rw-r--r--source/d/ccache/doctest.h.url1
-rwxr-xr-xsource/d/perl/perl.SlackBuild10
-rwxr-xr-xsource/d/subversion/subversion.SlackBuild2
-rw-r--r--source/kde/fcitx5-configtool/slack-desc4
-rw-r--r--source/kde/kde/patch/plasma-workspace.patch1
-rw-r--r--source/kde/kde/patch/plasma-workspace/1181acfe30557d6646511df8d98d82589878a570.patch66
-rw-r--r--source/l/glib2/4073.patch290
-rwxr-xr-xsource/l/glib2/glib2.SlackBuild5
-rwxr-xr-xsource/l/imagemagick/imagemagick.SlackBuild2
-rwxr-xr-xsource/l/pango/pango.SlackBuild4
-rwxr-xr-xsource/l/python-packaging/python-packaging.SlackBuild2
-rwxr-xr-xsource/n/epic5/epic5.SlackBuild2
-rwxr-xr-xsource/n/irssi/irssi.SlackBuild2
-rwxr-xr-xsource/n/net-snmp/net-snmp.SlackBuild2
-rwxr-xr-xsource/n/ntp/ntp.SlackBuild2
-rw-r--r--source/n/ntp/ntp.logrotate2
-rwxr-xr-xsource/n/openldap/openldap.SlackBuild2
-rw-r--r--source/x/fcitx5-gtk/slack-desc2
-rw-r--r--source/x/fcitx5-hangul/slack-desc2
-rw-r--r--source/x/fcitx5-kkc/slack-desc4
-rw-r--r--source/x/fcitx5-qt/slack-desc4
-rw-r--r--source/x/fcitx5-sayura/slack-desc2
-rw-r--r--source/x/fcitx5-table-extra/slack-desc4
-rw-r--r--source/x/fcitx5-table-other/slack-desc2
-rw-r--r--source/x/fcitx5-unikey/slack-desc2
-rwxr-xr-xsource/xap/hexchat/hexchat.SlackBuild2
-rwxr-xr-xsource/xap/pidgin/pidgin.SlackBuild2
-rwxr-xr-xsource/xap/rxvt-unicode/rxvt-unicode.SlackBuild2
-rwxr-xr-xsource/xap/xscreensaver/xscreensaver.SlackBuild40
-rw-r--r--source/xap/xscreensaver/xscreensaver.setuid.diff179
46 files changed, 7684 insertions, 726 deletions
diff --git a/ChangeLog.rss b/ChangeLog.rss
index 24dbaef40..17bae5986 100644
--- a/ChangeLog.rss
+++ b/ChangeLog.rss
@@ -11,10 +11,60 @@
<description>Tracking Slackware development in git.</description>
<language>en-us</language>
<id xmlns="http://www.w3.org/2005/Atom">urn:uuid:c964f45e-6732-11e8-bbe5-107b4450212f</id>
- <pubDate>Sun, 9 Jun 2024 18:41:17 GMT</pubDate>
- <lastBuildDate>Sun, 9 Jun 2024 19:04:16 GMT</lastBuildDate>
+ <pubDate>Mon, 10 Jun 2024 19:23:44 GMT</pubDate>
+ <lastBuildDate>Mon, 10 Jun 2024 20:00:33 GMT</lastBuildDate>
<generator>maintain_current_git.sh v 1.17</generator>
<item>
+ <title>Mon, 10 Jun 2024 19:23:44 GMT</title>
+ <pubDate>Mon, 10 Jun 2024 19:23:44 GMT</pubDate>
+ <link>https://git.slackware.nl/current/tag/?h=20240610192344</link>
+ <guid isPermaLink="false">20240610192344</guid>
+ <description>
+ <![CDATA[<pre>
+ap/stow-2.4.0-x86_64-1.txz: Added.
+ Thanks to r1w1s1.
+ap/texinfo-7.1-x86_64-2.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+ap/vim-9.1.0473-x86_64-1.txz: Upgraded.
+ Compiled against perl-5.40.0.
+d/ccache-4.10-x86_64-2.txz: Rebuilt.
+ Avoid downloading doctest.h at build time. Thanks to lucabon.
+d/perl-5.40.0-x86_64-1.txz: Upgraded.
+ Upgraded: DBD-mysql-4.052, Path-Tiny-0.146, URI-5.28.
+d/subversion-1.14.3-x86_64-2.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+kde/plasma-workspace-5.27.11.1-x86_64-2.txz: Rebuilt.
+ [PATCH] Fix writing ICEAuthority file.
+l/glib2-2.80.3-x86_64-1.txz: Upgraded.
+l/imagemagick-7.1.1_33-x86_64-2.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+l/pango-1.54.0-x86_64-1.txz: Upgraded.
+l/python-packaging-24.1-x86_64-1.txz: Upgraded.
+n/epic5-2.1.12-x86_64-9.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+n/irssi-1.4.5-x86_64-3.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+n/net-snmp-5.9.4-x86_64-5.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+n/ntp-4.2.8p18-x86_64-3.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+n/openldap-2.6.8-x86_64-2.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+xap/hexchat-2.16.2-x86_64-3.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+xap/pidgin-2.14.13-x86_64-2.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+xap/rxvt-unicode-9.31-x86_64-3.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+xap/vim-gvim-9.1.0473-x86_64-1.txz: Upgraded.
+ Compiled against perl-5.40.0.
+xap/xscreensaver-6.09-x86_64-1.txz: Upgraded.
+xfce/xfce4-power-manager-4.18.4-x86_64-1.txz: Upgraded.
+xfce/xfce4-session-4.18.4-x86_64-1.txz: Upgraded.
+ </pre>]]>
+ </description>
+ </item>
+ <item>
<title>Sun, 9 Jun 2024 18:41:17 GMT</title>
<pubDate>Sun, 9 Jun 2024 18:41:17 GMT</pubDate>
<link>https://git.slackware.nl/current/tag/?h=20240609184117</link>
diff --git a/ChangeLog.txt b/ChangeLog.txt
index ac477e667..dd1bbe0c1 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,3 +1,45 @@
+Mon Jun 10 19:23:44 UTC 2024
+ap/stow-2.4.0-x86_64-1.txz: Added.
+ Thanks to r1w1s1.
+ap/texinfo-7.1-x86_64-2.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+ap/vim-9.1.0473-x86_64-1.txz: Upgraded.
+ Compiled against perl-5.40.0.
+d/ccache-4.10-x86_64-2.txz: Rebuilt.
+ Avoid downloading doctest.h at build time. Thanks to lucabon.
+d/perl-5.40.0-x86_64-1.txz: Upgraded.
+ Upgraded: DBD-mysql-4.052, Path-Tiny-0.146, URI-5.28.
+d/subversion-1.14.3-x86_64-2.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+kde/plasma-workspace-5.27.11.1-x86_64-2.txz: Rebuilt.
+ [PATCH] Fix writing ICEAuthority file.
+l/glib2-2.80.3-x86_64-1.txz: Upgraded.
+l/imagemagick-7.1.1_33-x86_64-2.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+l/pango-1.54.0-x86_64-1.txz: Upgraded.
+l/python-packaging-24.1-x86_64-1.txz: Upgraded.
+n/epic5-2.1.12-x86_64-9.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+n/irssi-1.4.5-x86_64-3.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+n/net-snmp-5.9.4-x86_64-5.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+n/ntp-4.2.8p18-x86_64-3.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+n/openldap-2.6.8-x86_64-2.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+xap/hexchat-2.16.2-x86_64-3.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+xap/pidgin-2.14.13-x86_64-2.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+xap/rxvt-unicode-9.31-x86_64-3.txz: Rebuilt.
+ Recompiled against perl-5.40.0.
+xap/vim-gvim-9.1.0473-x86_64-1.txz: Upgraded.
+ Compiled against perl-5.40.0.
+xap/xscreensaver-6.09-x86_64-1.txz: Upgraded.
+xfce/xfce4-power-manager-4.18.4-x86_64-1.txz: Upgraded.
+xfce/xfce4-session-4.18.4-x86_64-1.txz: Upgraded.
++--------------------------+
Sun Jun 9 18:41:17 UTC 2024
l/qt6-6.7.1_20240516_6977d02f-x86_64-3.txz: Rebuilt.
Fixed config option: -DINSTALL_MKSPECSDIR=lib${LIBDIRSUFFIX}/qt6/mkspecs
diff --git a/FILELIST.TXT b/FILELIST.TXT
index 5ef126a46..8b66aa340 100644
--- a/FILELIST.TXT
+++ b/FILELIST.TXT
@@ -1,20 +1,20 @@
-Sun Jun 9 18:45:32 UTC 2024
+Mon Jun 10 19:27:41 UTC 2024
Here is the file list for this directory. If you are using a
mirror site and find missing or extra files in the disk
subdirectories, please have the archive administrator refresh
the mirror.
-drwxr-xr-x 12 root root 4096 2024-06-09 18:41 .
+drwxr-xr-x 12 root root 4096 2024-06-10 19:23 .
-rw-r--r-- 1 root root 5767 2022-02-02 22:44 ./ANNOUNCE.15.0
-rw-r--r-- 1 root root 16617 2022-02-02 23:27 ./CHANGES_AND_HINTS.TXT
--rw-r--r-- 1 root root 1156096 2024-06-08 19:47 ./CHECKSUMS.md5
--rw-r--r-- 1 root root 195 2024-06-08 19:47 ./CHECKSUMS.md5.asc
+-rw-r--r-- 1 root root 1156170 2024-06-09 18:45 ./CHECKSUMS.md5
+-rw-r--r-- 1 root root 195 2024-06-09 18:45 ./CHECKSUMS.md5.asc
-rw-r--r-- 1 root root 17976 1994-06-10 02:28 ./COPYING
-rw-r--r-- 1 root root 35147 2007-06-30 04:21 ./COPYING3
-rw-r--r-- 1 root root 19573 2016-06-23 20:08 ./COPYRIGHT.TXT
-rw-r--r-- 1 root root 616 2006-10-02 04:37 ./CRYPTO_NOTICE.TXT
--rw-r--r-- 1 root root 1093286 2024-06-09 18:41 ./ChangeLog.txt
+-rw-r--r-- 1 root root 1094964 2024-06-10 19:23 ./ChangeLog.txt
drwxr-xr-x 3 root root 4096 2013-03-20 22:17 ./EFI
drwxr-xr-x 2 root root 4096 2024-05-30 18:37 ./EFI/BOOT
-rw-r--r-- 1 root root 1187840 2021-06-15 19:16 ./EFI/BOOT/bootx64.efi
@@ -25,9 +25,9 @@ drwxr-xr-x 2 root root 4096 2024-05-30 18:37 ./EFI/BOOT
-rwxr-xr-x 1 root root 2504 2019-07-05 18:54 ./EFI/BOOT/make-grub.sh
-rw-r--r-- 1 root root 10722 2013-09-21 19:02 ./EFI/BOOT/osdetect.cfg
-rw-r--r-- 1 root root 1273 2013-08-12 21:08 ./EFI/BOOT/tools.cfg
--rw-r--r-- 1 root root 1512877 2024-06-08 19:47 ./FILELIST.TXT
+-rw-r--r-- 1 root root 1512968 2024-06-09 18:45 ./FILELIST.TXT
-rw-r--r-- 1 root root 1572 2012-08-29 18:27 ./GPG-KEY
--rw-r--r-- 1 root root 911671 2024-06-09 18:44 ./PACKAGES.TXT
+-rw-r--r-- 1 root root 912355 2024-06-10 19:27 ./PACKAGES.TXT
-rw-r--r-- 1 root root 8034 2022-02-02 03:36 ./README.TXT
-rw-r--r-- 1 root root 3623 2024-05-30 18:22 ./README.initrd
-rw-r--r-- 1 root root 34114 2023-12-11 20:35 ./README_CRYPT.TXT
@@ -662,11 +662,11 @@ drwxr-xr-x 2 root root 4096 2022-02-03 07:02 ./patches
-rw-r--r-- 1 root root 575 2022-02-03 07:02 ./patches/FILE_LIST
-rw-r--r-- 1 root root 14 2022-02-03 07:02 ./patches/MANIFEST.bz2
-rw-r--r-- 1 root root 224 2022-02-03 07:02 ./patches/PACKAGES.TXT
-drwxr-xr-x 17 root root 4096 2024-06-09 18:45 ./slackware64
--rw-r--r-- 1 root root 355643 2024-06-09 18:45 ./slackware64/CHECKSUMS.md5
--rw-r--r-- 1 root root 195 2024-06-09 18:45 ./slackware64/CHECKSUMS.md5.asc
--rw-r--r-- 1 root root 440441 2024-06-09 18:44 ./slackware64/FILE_LIST
--rw-r--r-- 1 root root 4648689 2024-06-09 18:44 ./slackware64/MANIFEST.bz2
+drwxr-xr-x 17 root root 4096 2024-06-10 19:27 ./slackware64
+-rw-r--r-- 1 root root 355842 2024-06-10 19:27 ./slackware64/CHECKSUMS.md5
+-rw-r--r-- 1 root root 195 2024-06-10 19:27 ./slackware64/CHECKSUMS.md5.asc
+-rw-r--r-- 1 root root 440685 2024-06-10 19:26 ./slackware64/FILE_LIST
+-rw-r--r-- 1 root root 4653078 2024-06-10 19:26 ./slackware64/MANIFEST.bz2
lrwxrwxrwx 1 root root 15 2009-08-23 23:34 ./slackware64/PACKAGES.TXT -> ../PACKAGES.TXT
drwxr-xr-x 2 root root 32768 2024-06-08 19:45 ./slackware64/a
-rw-r--r-- 1 root root 327 2022-02-15 18:16 ./slackware64/a/aaa_base-15.1-x86_64-2.txt
@@ -1058,7 +1058,7 @@ drwxr-xr-x 2 root root 32768 2024-06-08 19:45 ./slackware64/a
-rw-r--r-- 1 root root 540 2024-01-15 21:54 ./slackware64/a/zoo-2.10_28-x86_64-1.txt
-rw-r--r-- 1 root root 55448 2024-01-15 21:54 ./slackware64/a/zoo-2.10_28-x86_64-1.txz
-rw-r--r-- 1 root root 163 2024-01-15 21:54 ./slackware64/a/zoo-2.10_28-x86_64-1.txz.asc
-drwxr-xr-x 2 root root 20480 2024-06-07 19:14 ./slackware64/ap
+drwxr-xr-x 2 root root 20480 2024-06-10 19:26 ./slackware64/ap
-rw-r--r-- 1 root root 291 2024-03-14 19:01 ./slackware64/ap/a2ps-4.15.6-x86_64-1.txt
-rw-r--r-- 1 root root 675492 2024-03-14 19:01 ./slackware64/ap/a2ps-4.15.6-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-03-14 19:01 ./slackware64/ap/a2ps-4.15.6-x86_64-1.txz.asc
@@ -1193,8 +1193,8 @@ drwxr-xr-x 2 root root 20480 2024-06-07 19:14 ./slackware64/ap
-rw-r--r-- 1 root root 338 2021-02-13 11:32 ./slackware64/ap/madplay-0.15.2b-x86_64-7.txt
-rw-r--r-- 1 root root 59992 2021-02-13 11:32 ./slackware64/ap/madplay-0.15.2b-x86_64-7.txz
-rw-r--r-- 1 root root 163 2021-02-13 11:32 ./slackware64/ap/madplay-0.15.2b-x86_64-7.txz.asc
--rw-r--r-- 1 root root 6604 2024-04-26 20:12 ./slackware64/ap/maketag
--rw-r--r-- 1 root root 6604 2024-04-26 20:12 ./slackware64/ap/maketag.ez
+-rw-r--r-- 1 root root 6651 2024-06-10 19:21 ./slackware64/ap/maketag
+-rw-r--r-- 1 root root 6651 2024-06-10 19:21 ./slackware64/ap/maketag.ez
-rw-r--r-- 1 root root 532 2024-04-05 17:32 ./slackware64/ap/man-db-2.12.1-x86_64-1.txt
-rw-r--r-- 1 root root 578104 2024-04-05 17:32 ./slackware64/ap/man-db-2.12.1-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-04-05 17:32 ./slackware64/ap/man-db-2.12.1-x86_64-1.txz.asc
@@ -1279,19 +1279,22 @@ drwxr-xr-x 2 root root 20480 2024-06-07 19:14 ./slackware64/ap
-rw-r--r-- 1 root root 584 2023-03-28 18:23 ./slackware64/ap/squashfs-tools-4.6.1-x86_64-1.txt
-rw-r--r-- 1 root root 198020 2023-03-28 18:23 ./slackware64/ap/squashfs-tools-4.6.1-x86_64-1.txz
-rw-r--r-- 1 root root 163 2023-03-28 18:23 ./slackware64/ap/squashfs-tools-4.6.1-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 515 2024-06-10 18:30 ./slackware64/ap/stow-2.4.0-x86_64-1.txt
+-rw-r--r-- 1 root root 103492 2024-06-10 18:30 ./slackware64/ap/stow-2.4.0-x86_64-1.txz
+-rw-r--r-- 1 root root 195 2024-06-10 18:30 ./slackware64/ap/stow-2.4.0-x86_64-1.txz.asc
-rw-r--r-- 1 root root 442 2023-12-30 19:22 ./slackware64/ap/sudo-1.9.15p5-x86_64-1.txt
-rw-r--r-- 1 root root 1307664 2023-12-30 19:22 ./slackware64/ap/sudo-1.9.15p5-x86_64-1.txz
-rw-r--r-- 1 root root 163 2023-12-30 19:22 ./slackware64/ap/sudo-1.9.15p5-x86_64-1.txz.asc
-rw-r--r-- 1 root root 403 2023-12-17 19:42 ./slackware64/ap/sysstat-12.7.5-x86_64-1.txt
-rw-r--r-- 1 root root 378584 2023-12-17 19:42 ./slackware64/ap/sysstat-12.7.5-x86_64-1.txz
-rw-r--r-- 1 root root 163 2023-12-17 19:42 ./slackware64/ap/sysstat-12.7.5-x86_64-1.txz.asc
--rw-r--r-- 1 root root 998 2024-04-26 20:12 ./slackware64/ap/tagfile
+-rw-r--r-- 1 root root 1007 2024-06-10 19:21 ./slackware64/ap/tagfile
-rw-r--r-- 1 root root 495 2021-02-13 11:45 ./slackware64/ap/terminus-font-4.49.1-noarch-3.txt
-rw-r--r-- 1 root root 2309356 2021-02-13 11:45 ./slackware64/ap/terminus-font-4.49.1-noarch-3.txz
-rw-r--r-- 1 root root 163 2021-02-13 11:45 ./slackware64/ap/terminus-font-4.49.1-noarch-3.txz.asc
--rw-r--r-- 1 root root 614 2023-10-18 19:45 ./slackware64/ap/texinfo-7.1-x86_64-1.txt
--rw-r--r-- 1 root root 1726556 2023-10-18 19:45 ./slackware64/ap/texinfo-7.1-x86_64-1.txz
--rw-r--r-- 1 root root 163 2023-10-18 19:45 ./slackware64/ap/texinfo-7.1-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 614 2024-06-10 17:57 ./slackware64/ap/texinfo-7.1-x86_64-2.txt
+-rw-r--r-- 1 root root 1727584 2024-06-10 17:57 ./slackware64/ap/texinfo-7.1-x86_64-2.txz
+-rw-r--r-- 1 root root 195 2024-06-10 17:57 ./slackware64/ap/texinfo-7.1-x86_64-2.txz.asc
-rw-r--r-- 1 root root 368 2024-02-13 18:43 ./slackware64/ap/tmux-3.4-x86_64-1.txt
-rw-r--r-- 1 root root 407740 2024-02-13 18:43 ./slackware64/ap/tmux-3.4-x86_64-1.txz
-rw-r--r-- 1 root root 163 2024-02-13 18:43 ./slackware64/ap/tmux-3.4-x86_64-1.txz.asc
@@ -1304,9 +1307,9 @@ drwxr-xr-x 2 root root 20480 2024-06-07 19:14 ./slackware64/ap
-rw-r--r-- 1 root root 375 2021-02-13 11:46 ./slackware64/ap/vbetool-1.2.2-x86_64-4.txt
-rw-r--r-- 1 root root 14756 2021-02-13 11:46 ./slackware64/ap/vbetool-1.2.2-x86_64-4.txz
-rw-r--r-- 1 root root 163 2021-02-13 11:46 ./slackware64/ap/vbetool-1.2.2-x86_64-4.txz.asc
--rw-r--r-- 1 root root 407 2024-05-26 17:27 ./slackware64/ap/vim-9.1.0446-x86_64-1.txt
--rw-r--r-- 1 root root 8945492 2024-05-26 17:27 ./slackware64/ap/vim-9.1.0446-x86_64-1.txz
--rw-r--r-- 1 root root 195 2024-05-26 17:27 ./slackware64/ap/vim-9.1.0446-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 407 2024-06-10 17:54 ./slackware64/ap/vim-9.1.0473-x86_64-1.txt
+-rw-r--r-- 1 root root 8939880 2024-06-10 17:54 ./slackware64/ap/vim-9.1.0473-x86_64-1.txz
+-rw-r--r-- 1 root root 195 2024-06-10 17:54 ./slackware64/ap/vim-9.1.0473-x86_64-1.txz.asc
-rw-r--r-- 1 root root 604 2023-03-05 21:21 ./slackware64/ap/vorbis-tools-1.4.2-x86_64-4.txt
-rw-r--r-- 1 root root 178980 2023-03-05 21:21 ./slackware64/ap/vorbis-tools-1.4.2-x86_64-4.txz
-rw-r--r-- 1 root root 163 2023-03-05 21:21 ./slackware64/ap/vorbis-tools-1.4.2-x86_64-4.txz.asc
@@ -1322,7 +1325,7 @@ drwxr-xr-x 2 root root 20480 2024-06-07 19:14 ./slackware64/ap
-rw-r--r-- 1 root root 506 2022-05-15 17:09 ./slackware64/ap/zsh-5.9-x86_64-1.txt
-rw-r--r-- 1 root root 3156392 2022-05-15 17:09 ./slackware64/ap/zsh-5.9-x86_64-1.txz
-rw-r--r-- 1 root root 163 2022-05-15 17:09 ./slackware64/ap/zsh-5.9-x86_64-1.txz.asc
-drwxr-xr-x 2 root root 20480 2024-06-07 19:14 ./slackware64/d
+drwxr-xr-x 2 root root 20480 2024-06-10 19:26 ./slackware64/d
-rw-r--r-- 1 root root 360 2024-03-30 21:20 ./slackware64/d/Cython-3.0.10-x86_64-1.txt
-rw-r--r-- 1 root root 4305292 2024-03-30 21:20 ./slackware64/d/Cython-3.0.10-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-03-30 21:20 ./slackware64/d/Cython-3.0.10-x86_64-1.txz.asc
@@ -1347,9 +1350,9 @@ drwxr-xr-x 2 root root 20480 2024-06-07 19:14 ./slackware64/d
-rw-r--r-- 1 root root 662 2023-09-13 18:45 ./slackware64/d/cbindgen-0.26.0-x86_64-1.txt
-rw-r--r-- 1 root root 1417032 2023-09-13 18:45 ./slackware64/d/cbindgen-0.26.0-x86_64-1.txz
-rw-r--r-- 1 root root 163 2023-09-13 18:45 ./slackware64/d/cbindgen-0.26.0-x86_64-1.txz.asc
--rw-r--r-- 1 root root 350 2024-05-31 17:28 ./slackware64/d/ccache-4.10-x86_64-1.txt
--rw-r--r-- 1 root root 590400 2024-05-31 17:28 ./slackware64/d/ccache-4.10-x86_64-1.txz
--rw-r--r-- 1 root root 195 2024-05-31 17:28 ./slackware64/d/ccache-4.10-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 350 2024-06-10 18:39 ./slackware64/d/ccache-4.10-x86_64-2.txt
+-rw-r--r-- 1 root root 590336 2024-06-10 18:39 ./slackware64/d/ccache-4.10-x86_64-2.txz
+-rw-r--r-- 1 root root 195 2024-06-10 18:39 ./slackware64/d/ccache-4.10-x86_64-2.txz.asc
-rw-r--r-- 1 root root 516 2021-02-13 09:10 ./slackware64/d/check-0.15.2-x86_64-3.txt
-rw-r--r-- 1 root root 102104 2021-02-13 09:10 ./slackware64/d/check-0.15.2-x86_64-3.txz
-rw-r--r-- 1 root root 163 2021-02-13 09:10 ./slackware64/d/check-0.15.2-x86_64-3.txz.asc
@@ -1498,9 +1501,9 @@ drwxr-xr-x 2 root root 20480 2024-06-07 19:14 ./slackware64/d
-rw-r--r-- 1 root root 469 2023-04-24 19:58 ./slackware64/d/patchelf-0.18.0-x86_64-1.txt
-rw-r--r-- 1 root root 94892 2023-04-24 19:58 ./slackware64/d/patchelf-0.18.0-x86_64-1.txz
-rw-r--r-- 1 root root 163 2023-04-24 19:58 ./slackware64/d/patchelf-0.18.0-x86_64-1.txz.asc
--rw-r--r-- 1 root root 544 2024-03-18 21:37 ./slackware64/d/perl-5.38.2-x86_64-2.txt
--rw-r--r-- 1 root root 16943804 2024-03-18 21:37 ./slackware64/d/perl-5.38.2-x86_64-2.txz
--rw-r--r-- 1 root root 195 2024-03-18 21:37 ./slackware64/d/perl-5.38.2-x86_64-2.txz.asc
+-rw-r--r-- 1 root root 544 2024-06-10 17:32 ./slackware64/d/perl-5.40.0-x86_64-1.txt
+-rw-r--r-- 1 root root 17561760 2024-06-10 17:32 ./slackware64/d/perl-5.40.0-x86_64-1.txz
+-rw-r--r-- 1 root root 195 2024-06-10 17:32 ./slackware64/d/perl-5.40.0-x86_64-1.txz.asc
-rw-r--r-- 1 root root 444 2021-02-13 10:44 ./slackware64/d/pkg-config-0.29.2-x86_64-4.txt
-rw-r--r-- 1 root root 55712 2021-02-13 10:44 ./slackware64/d/pkg-config-0.29.2-x86_64-4.txz
-rw-r--r-- 1 root root 163 2021-02-13 10:44 ./slackware64/d/pkg-config-0.29.2-x86_64-4.txz.asc
@@ -1552,9 +1555,9 @@ drwxr-xr-x 2 root root 20480 2024-06-07 19:14 ./slackware64/d
-rw-r--r-- 1 root root 547 2024-05-15 22:58 ./slackware64/d/strace-6.9-x86_64-1.txt
-rw-r--r-- 1 root root 473604 2024-05-15 22:58 ./slackware64/d/strace-6.9-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-05-15 22:58 ./slackware64/d/strace-6.9-x86_64-1.txz.asc
--rw-r--r-- 1 root root 547 2023-12-29 20:12 ./slackware64/d/subversion-1.14.3-x86_64-1.txt
--rw-r--r-- 1 root root 4196028 2023-12-29 20:12 ./slackware64/d/subversion-1.14.3-x86_64-1.txz
--rw-r--r-- 1 root root 163 2023-12-29 20:12 ./slackware64/d/subversion-1.14.3-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 547 2024-06-10 17:59 ./slackware64/d/subversion-1.14.3-x86_64-2.txt
+-rw-r--r-- 1 root root 4163400 2024-06-10 17:59 ./slackware64/d/subversion-1.14.3-x86_64-2.txz
+-rw-r--r-- 1 root root 195 2024-06-10 17:59 ./slackware64/d/subversion-1.14.3-x86_64-2.txz.asc
-rw-r--r-- 1 root root 559 2024-02-26 19:46 ./slackware64/d/swig-4.2.1-x86_64-1.txt
-rw-r--r-- 1 root root 2790884 2024-02-26 19:46 ./slackware64/d/swig-4.2.1-x86_64-1.txz
-rw-r--r-- 1 root root 163 2024-02-26 19:46 ./slackware64/d/swig-4.2.1-x86_64-1.txz.asc
@@ -1604,7 +1607,7 @@ drwxr-xr-x 2 root root 4096 2024-05-30 18:40 ./slackware64/k
-rw-r--r-- 1 root root 1169 2024-05-30 18:22 ./slackware64/k/maketag
-rw-r--r-- 1 root root 1169 2024-05-30 18:22 ./slackware64/k/maketag.ez
-rw-r--r-- 1 root root 18 2024-05-30 18:22 ./slackware64/k/tagfile
-drwxr-xr-x 2 root root 86016 2024-06-06 19:25 ./slackware64/kde
+drwxr-xr-x 2 root root 86016 2024-06-10 19:26 ./slackware64/kde
-rw-r--r-- 1 root root 382 2024-02-15 20:27 ./slackware64/kde/akonadi-23.08.5-x86_64-1.txt
-rw-r--r-- 1 root root 2559504 2024-02-15 20:27 ./slackware64/kde/akonadi-23.08.5-x86_64-1.txz
-rw-r--r-- 1 root root 163 2024-02-15 20:27 ./slackware64/kde/akonadi-23.08.5-x86_64-1.txz.asc
@@ -2561,8 +2564,8 @@ drwxr-xr-x 2 root root 86016 2024-06-06 19:25 ./slackware64/kde
-rw-r--r-- 1 root root 216 2024-02-15 20:35 ./slackware64/kde/mailimporter-23.08.5-x86_64-1.txt
-rw-r--r-- 1 root root 252696 2024-02-15 20:35 ./slackware64/kde/mailimporter-23.08.5-x86_64-1.txz
-rw-r--r-- 1 root root 163 2024-02-15 20:35 ./slackware64/kde/mailimporter-23.08.5-x86_64-1.txz.asc
--rw-r--r-- 1 root root 28261 2024-05-31 18:46 ./slackware64/kde/maketag
--rw-r--r-- 1 root root 28261 2024-05-31 18:46 ./slackware64/kde/maketag.ez
+-rw-r--r-- 1 root root 28261 2024-06-10 19:21 ./slackware64/kde/maketag
+-rw-r--r-- 1 root root 28261 2024-06-10 19:21 ./slackware64/kde/maketag.ez
-rw-r--r-- 1 root root 550 2024-02-15 21:31 ./slackware64/kde/marble-23.08.5-x86_64-1.txt
-rw-r--r-- 1 root root 47836816 2024-02-15 21:31 ./slackware64/kde/marble-23.08.5-x86_64-1.txz
-rw-r--r-- 1 root root 163 2024-02-15 21:31 ./slackware64/kde/marble-23.08.5-x86_64-1.txz.asc
@@ -2668,9 +2671,9 @@ drwxr-xr-x 2 root root 86016 2024-06-06 19:25 ./slackware64/kde
-rw-r--r-- 1 root root 424 2023-12-09 18:41 ./slackware64/kde/plasma-wayland-protocols-1.12.0-x86_64-1.txt
-rw-r--r-- 1 root root 43860 2023-12-09 18:41 ./slackware64/kde/plasma-wayland-protocols-1.12.0-x86_64-1.txz
-rw-r--r-- 1 root root 163 2023-12-09 18:41 ./slackware64/kde/plasma-wayland-protocols-1.12.0-x86_64-1.txz.asc
--rw-r--r-- 1 root root 378 2024-03-18 16:56 ./slackware64/kde/plasma-workspace-5.27.11-x86_64-2.txt
--rw-r--r-- 1 root root 19499276 2024-03-18 16:56 ./slackware64/kde/plasma-workspace-5.27.11-x86_64-2.txz
--rw-r--r-- 1 root root 195 2024-03-18 16:56 ./slackware64/kde/plasma-workspace-5.27.11-x86_64-2.txz.asc
+-rw-r--r-- 1 root root 378 2024-06-10 03:00 ./slackware64/kde/plasma-workspace-5.27.11.1-x86_64-2.txt
+-rw-r--r-- 1 root root 19529520 2024-06-10 03:00 ./slackware64/kde/plasma-workspace-5.27.11.1-x86_64-2.txz
+-rw-r--r-- 1 root root 195 2024-06-10 03:00 ./slackware64/kde/plasma-workspace-5.27.11.1-x86_64-2.txz.asc
-rw-r--r-- 1 root root 423 2024-03-06 20:48 ./slackware64/kde/plasma-workspace-wallpapers-5.27.11-noarch-1.txt
-rw-r--r-- 1 root root 94032344 2024-03-06 20:48 ./slackware64/kde/plasma-workspace-wallpapers-5.27.11-noarch-1.txz
-rw-r--r-- 1 root root 195 2024-03-06 20:48 ./slackware64/kde/plasma-workspace-wallpapers-5.27.11-noarch-1.txz.asc
@@ -2706,9 +2709,9 @@ drwxr-xr-x 2 root root 86016 2024-06-06 19:25 ./slackware64/kde
-rw-r--r-- 1 root root 195 2024-03-06 20:52 ./slackware64/kde/qqc2-breeze-style-5.27.11-x86_64-1.txz.asc
-rw-r--r-- 1 root root 498 2024-05-22 18:13 ./slackware64/kde/qqc2-desktop-style-5.116.1-x86_64-1.txt
-rw-r--r-- 1 root root 99760 2024-05-22 18:13 ./slackware64/kde/qqc2-desktop-style-5.116.1-x86_64-1.txz
--rw-r--r-- 1 root root 195 2024-05-22 18:13 ./slackware64/kde/qqc2-desktop-style-5.116.1-x86_64-1.txz.asc
--rw-r--r-- 1 root root 460 2024-02-15 21:32 ./slackware64/kde/rocs-23.08.5-x86_64-1.txt
--rw-r--r-- 1 root root 1591648 2024-02-15 21:32 ./slackware64/kde/rocs-23.08.5-x86_64-1.txz
+-rw-r--r-- 1 root root 195 2024-05-22 18:13 ./slackware64/kde/qqc2-desktop-style-5.116.1-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 460 2024-02-15 21:32 ./slackware64/kde/rocs-23.08.5-x86_64-1.txt
+-rw-r--r-- 1 root root 1591648 2024-02-15 21:32 ./slackware64/kde/rocs-23.08.5-x86_64-1.txz
-rw-r--r-- 1 root root 163 2024-02-15 21:32 ./slackware64/kde/rocs-23.08.5-x86_64-1.txz.asc
-rw-r--r-- 1 root root 275 2024-03-06 20:49 ./slackware64/kde/sddm-kcm-5.27.11-x86_64-1.txt
-rw-r--r-- 1 root root 121684 2024-03-06 20:49 ./slackware64/kde/sddm-kcm-5.27.11-x86_64-1.txz
@@ -2749,7 +2752,7 @@ drwxr-xr-x 2 root root 86016 2024-06-06 19:25 ./slackware64/kde
-rw-r--r-- 1 root root 265 2024-03-06 20:46 ./slackware64/kde/systemsettings-5.27.11-x86_64-1.txt
-rw-r--r-- 1 root root 362752 2024-03-06 20:46 ./slackware64/kde/systemsettings-5.27.11-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-03-06 20:46 ./slackware64/kde/systemsettings-5.27.11-x86_64-1.txz.asc
--rw-r--r-- 1 root root 5778 2024-05-31 18:45 ./slackware64/kde/tagfile
+-rw-r--r-- 1 root root 5778 2024-06-10 19:21 ./slackware64/kde/tagfile
-rw-r--r-- 1 root root 543 2024-05-19 23:46 ./slackware64/kde/threadweaver-5.116.0-x86_64-1.txt
-rw-r--r-- 1 root root 78504 2024-05-19 23:46 ./slackware64/kde/threadweaver-5.116.0-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-05-19 23:46 ./slackware64/kde/threadweaver-5.116.0-x86_64-1.txz.asc
@@ -2774,7 +2777,7 @@ drwxr-xr-x 2 root root 86016 2024-06-06 19:25 ./slackware64/kde
-rw-r--r-- 1 root root 517 2024-02-15 21:47 ./slackware64/kde/zanshin-23.08.5-x86_64-1.txt
-rw-r--r-- 1 root root 686104 2024-02-15 21:47 ./slackware64/kde/zanshin-23.08.5-x86_64-1.txz
-rw-r--r-- 1 root root 163 2024-02-15 21:47 ./slackware64/kde/zanshin-23.08.5-x86_64-1.txz.asc
-drwxr-xr-x 2 root root 102400 2024-06-09 18:44 ./slackware64/l
+drwxr-xr-x 2 root root 102400 2024-06-10 19:26 ./slackware64/l
-rw-r--r-- 1 root root 329 2022-03-06 20:00 ./slackware64/l/GConf-3.2.6-x86_64-8.txt
-rw-r--r-- 1 root root 928144 2022-03-06 20:00 ./slackware64/l/GConf-3.2.6-x86_64-8.txz
-rw-r--r-- 1 root root 163 2022-03-06 20:00 ./slackware64/l/GConf-3.2.6-x86_64-8.txz.asc
@@ -3057,9 +3060,9 @@ drwxr-xr-x 2 root root 102400 2024-06-09 18:44 ./slackware64/l
-rw-r--r-- 1 root root 300 2024-03-19 21:59 ./slackware64/l/glib-networking-2.80.0-x86_64-1.txt
-rw-r--r-- 1 root root 146404 2024-03-19 21:59 ./slackware64/l/glib-networking-2.80.0-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-03-19 21:59 ./slackware64/l/glib-networking-2.80.0-x86_64-1.txz.asc
--rw-r--r-- 1 root root 407 2024-05-25 18:06 ./slackware64/l/glib2-2.80.2-x86_64-2.txt
--rw-r--r-- 1 root root 3932044 2024-05-25 18:06 ./slackware64/l/glib2-2.80.2-x86_64-2.txz
--rw-r--r-- 1 root root 195 2024-05-25 18:06 ./slackware64/l/glib2-2.80.2-x86_64-2.txz.asc
+-rw-r--r-- 1 root root 407 2024-06-10 17:47 ./slackware64/l/glib2-2.80.3-x86_64-1.txt
+-rw-r--r-- 1 root root 3928020 2024-06-10 17:47 ./slackware64/l/glib2-2.80.3-x86_64-1.txz
+-rw-r--r-- 1 root root 195 2024-06-10 17:47 ./slackware64/l/glib2-2.80.3-x86_64-1.txz.asc
-rw-r--r-- 1 root root 313 2024-04-18 18:25 ./slackware64/l/glibc-2.39-x86_64-2.txt
-rw-r--r-- 1 root root 5638944 2024-04-18 18:25 ./slackware64/l/glibc-2.39-x86_64-2.txz
-rw-r--r-- 1 root root 195 2024-04-18 18:25 ./slackware64/l/glibc-2.39-x86_64-2.txz.asc
@@ -3180,9 +3183,9 @@ drwxr-xr-x 2 root root 102400 2024-06-09 18:44 ./slackware64/l
-rw-r--r-- 1 root root 473 2021-02-13 06:52 ./slackware64/l/id3lib-3.8.3-x86_64-4.txt
-rw-r--r-- 1 root root 161400 2021-02-13 06:52 ./slackware64/l/id3lib-3.8.3-x86_64-4.txz
-rw-r--r-- 1 root root 163 2021-02-13 06:52 ./slackware64/l/id3lib-3.8.3-x86_64-4.txz.asc
--rw-r--r-- 1 root root 537 2024-05-26 17:22 ./slackware64/l/imagemagick-7.1.1_33-x86_64-1.txt
--rw-r--r-- 1 root root 8623120 2024-05-26 17:22 ./slackware64/l/imagemagick-7.1.1_33-x86_64-1.txz
--rw-r--r-- 1 root root 195 2024-05-26 17:22 ./slackware64/l/imagemagick-7.1.1_33-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 537 2024-06-10 17:59 ./slackware64/l/imagemagick-7.1.1_33-x86_64-2.txt
+-rw-r--r-- 1 root root 8621932 2024-06-10 17:59 ./slackware64/l/imagemagick-7.1.1_33-x86_64-2.txz
+-rw-r--r-- 1 root root 195 2024-06-10 17:59 ./slackware64/l/imagemagick-7.1.1_33-x86_64-2.txz.asc
-rw-r--r-- 1 root root 399 2023-10-05 20:06 ./slackware64/l/immer-0.8.1-x86_64-1.txt
-rw-r--r-- 1 root root 67400 2023-10-05 20:06 ./slackware64/l/immer-0.8.1-x86_64-1.txz
-rw-r--r-- 1 root root 163 2023-10-05 20:06 ./slackware64/l/immer-0.8.1-x86_64-1.txz.asc
@@ -3706,9 +3709,9 @@ drwxr-xr-x 2 root root 102400 2024-06-09 18:44 ./slackware64/l
-rw-r--r-- 1 root root 446 2024-02-28 18:19 ./slackware64/l/orc-0.4.38-x86_64-1.txt
-rw-r--r-- 1 root root 261056 2024-02-28 18:19 ./slackware64/l/orc-0.4.38-x86_64-1.txz
-rw-r--r-- 1 root root 163 2024-02-28 18:19 ./slackware64/l/orc-0.4.38-x86_64-1.txz.asc
--rw-r--r-- 1 root root 460 2024-03-31 16:43 ./slackware64/l/pango-1.52.2-x86_64-1.txt
--rw-r--r-- 1 root root 434196 2024-03-31 16:43 ./slackware64/l/pango-1.52.2-x86_64-1.txz
--rw-r--r-- 1 root root 195 2024-03-31 16:43 ./slackware64/l/pango-1.52.2-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 460 2024-06-09 19:42 ./slackware64/l/pango-1.54.0-x86_64-1.txt
+-rw-r--r-- 1 root root 438208 2024-06-09 19:42 ./slackware64/l/pango-1.54.0-x86_64-1.txz
+-rw-r--r-- 1 root root 195 2024-06-09 19:42 ./slackware64/l/pango-1.54.0-x86_64-1.txz.asc
-rw-r--r-- 1 root root 186 2024-03-21 19:21 ./slackware64/l/pangomm-2.46.4-x86_64-1.txt
-rw-r--r-- 1 root root 114932 2024-03-21 19:21 ./slackware64/l/pangomm-2.46.4-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-03-21 19:21 ./slackware64/l/pangomm-2.46.4-x86_64-1.txz.asc
@@ -3874,9 +3877,9 @@ drwxr-xr-x 2 root root 102400 2024-06-09 18:44 ./slackware64/l
-rw-r--r-- 1 root root 502 2024-03-29 04:28 ./slackware64/l/python-notify2-0.3.1-x86_64-11.txt
-rw-r--r-- 1 root root 10904 2024-03-29 04:28 ./slackware64/l/python-notify2-0.3.1-x86_64-11.txz
-rw-r--r-- 1 root root 195 2024-03-29 04:28 ./slackware64/l/python-notify2-0.3.1-x86_64-11.txz.asc
--rw-r--r-- 1 root root 333 2024-03-29 04:28 ./slackware64/l/python-packaging-24.0-x86_64-2.txt
--rw-r--r-- 1 root root 100720 2024-03-29 04:28 ./slackware64/l/python-packaging-24.0-x86_64-2.txz
--rw-r--r-- 1 root root 195 2024-03-29 04:28 ./slackware64/l/python-packaging-24.0-x86_64-2.txz.asc
+-rw-r--r-- 1 root root 333 2024-06-10 17:32 ./slackware64/l/python-packaging-24.1-x86_64-1.txt
+-rw-r--r-- 1 root root 98776 2024-06-10 17:32 ./slackware64/l/python-packaging-24.1-x86_64-1.txz
+-rw-r--r-- 1 root root 195 2024-06-10 17:32 ./slackware64/l/python-packaging-24.1-x86_64-1.txz.asc
-rw-r--r-- 1 root root 520 2024-03-29 04:29 ./slackware64/l/python-pathspec-0.12.1-x86_64-2.txt
-rw-r--r-- 1 root root 42580 2024-03-29 04:29 ./slackware64/l/python-pathspec-0.12.1-x86_64-2.txz
-rw-r--r-- 1 root root 195 2024-03-29 04:29 ./slackware64/l/python-pathspec-0.12.1-x86_64-2.txz.asc
@@ -4109,7 +4112,7 @@ drwxr-xr-x 2 root root 102400 2024-06-09 18:44 ./slackware64/l
-rw-r--r-- 1 root root 403 2023-12-11 22:02 ./slackware64/l/zxing-cpp-2.2.1-x86_64-1.txt
-rw-r--r-- 1 root root 773596 2023-12-11 22:02 ./slackware64/l/zxing-cpp-2.2.1-x86_64-1.txz
-rw-r--r-- 1 root root 163 2023-12-11 22:02 ./slackware64/l/zxing-cpp-2.2.1-x86_64-1.txz.asc
-drwxr-xr-x 2 root root 36864 2024-06-08 19:45 ./slackware64/n
+drwxr-xr-x 2 root root 36864 2024-06-10 19:26 ./slackware64/n
-rw-r--r-- 1 root root 357 2023-03-09 19:11 ./slackware64/n/ModemManager-1.20.6-x86_64-1.txt
-rw-r--r-- 1 root root 1517848 2023-03-09 19:11 ./slackware64/n/ModemManager-1.20.6-x86_64-1.txz
-rw-r--r-- 1 root root 163 2023-03-09 19:11 ./slackware64/n/ModemManager-1.20.6-x86_64-1.txz.asc
@@ -4185,9 +4188,9 @@ drwxr-xr-x 2 root root 36864 2024-06-08 19:45 ./slackware64/n
-rw-r--r-- 1 root root 224 2024-05-04 01:49 ./slackware64/n/elm-2.5.8-x86_64-8.txt
-rw-r--r-- 1 root root 312620 2024-05-04 01:49 ./slackware64/n/elm-2.5.8-x86_64-8.txz
-rw-r--r-- 1 root root 195 2024-05-04 01:49 ./slackware64/n/elm-2.5.8-x86_64-8.txz.asc
--rw-r--r-- 1 root root 318 2024-05-04 01:50 ./slackware64/n/epic5-2.1.12-x86_64-8.txt
--rw-r--r-- 1 root root 835668 2024-05-04 01:50 ./slackware64/n/epic5-2.1.12-x86_64-8.txz
--rw-r--r-- 1 root root 195 2024-05-04 01:50 ./slackware64/n/epic5-2.1.12-x86_64-8.txz.asc
+-rw-r--r-- 1 root root 318 2024-06-10 17:58 ./slackware64/n/epic5-2.1.12-x86_64-9.txt
+-rw-r--r-- 1 root root 837224 2024-06-10 17:58 ./slackware64/n/epic5-2.1.12-x86_64-9.txz
+-rw-r--r-- 1 root root 195 2024-06-10 17:58 ./slackware64/n/epic5-2.1.12-x86_64-9.txz.asc
-rw-r--r-- 1 root root 440 2022-08-23 02:53 ./slackware64/n/ethtool-5.19-x86_64-1.txt
-rw-r--r-- 1 root root 182852 2022-08-23 02:53 ./slackware64/n/ethtool-5.19-x86_64-1.txz
-rw-r--r-- 1 root root 163 2022-08-23 02:53 ./slackware64/n/ethtool-5.19-x86_64-1.txz.asc
@@ -4250,9 +4253,9 @@ drwxr-xr-x 2 root root 36864 2024-06-08 19:45 ./slackware64/n
-rw-r--r-- 1 root root 532 2021-02-13 12:08 ./slackware64/n/ipw2200-fw-3.1-fw-3.txt
-rw-r--r-- 1 root root 118880 2021-02-13 12:08 ./slackware64/n/ipw2200-fw-3.1-fw-3.txz
-rw-r--r-- 1 root root 163 2021-02-13 12:08 ./slackware64/n/ipw2200-fw-3.1-fw-3.txz.asc
--rw-r--r-- 1 root root 331 2023-10-21 18:48 ./slackware64/n/irssi-1.4.5-x86_64-2.txt
--rw-r--r-- 1 root root 689848 2023-10-21 18:48 ./slackware64/n/irssi-1.4.5-x86_64-2.txz
--rw-r--r-- 1 root root 163 2023-10-21 18:48 ./slackware64/n/irssi-1.4.5-x86_64-2.txz.asc
+-rw-r--r-- 1 root root 331 2024-06-10 18:07 ./slackware64/n/irssi-1.4.5-x86_64-3.txt
+-rw-r--r-- 1 root root 691712 2024-06-10 18:07 ./slackware64/n/irssi-1.4.5-x86_64-3.txz
+-rw-r--r-- 1 root root 195 2024-06-10 18:07 ./slackware64/n/irssi-1.4.5-x86_64-3.txz.asc
-rw-r--r-- 1 root root 422 2024-05-19 18:49 ./slackware64/n/iw-6.9-x86_64-1.txt
-rw-r--r-- 1 root root 94576 2024-05-19 18:49 ./slackware64/n/iw-6.9-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-05-19 18:49 ./slackware64/n/iw-6.9-x86_64-1.txz.asc
@@ -4348,9 +4351,9 @@ drwxr-xr-x 2 root root 36864 2024-06-08 19:45 ./slackware64/n
-rw-r--r-- 1 root root 369 2024-01-03 19:35 ./slackware64/n/ncftp-3.2.7-x86_64-1.txt
-rw-r--r-- 1 root root 278752 2024-01-03 19:35 ./slackware64/n/ncftp-3.2.7-x86_64-1.txz
-rw-r--r-- 1 root root 163 2024-01-03 19:35 ./slackware64/n/ncftp-3.2.7-x86_64-1.txz.asc
--rw-r--r-- 1 root root 451 2024-05-04 02:06 ./slackware64/n/net-snmp-5.9.4-x86_64-4.txt
--rw-r--r-- 1 root root 1595132 2024-05-04 02:06 ./slackware64/n/net-snmp-5.9.4-x86_64-4.txz
--rw-r--r-- 1 root root 195 2024-05-04 02:06 ./slackware64/n/net-snmp-5.9.4-x86_64-4.txz.asc
+-rw-r--r-- 1 root root 451 2024-06-10 18:08 ./slackware64/n/net-snmp-5.9.4-x86_64-5.txt
+-rw-r--r-- 1 root root 1596760 2024-06-10 18:08 ./slackware64/n/net-snmp-5.9.4-x86_64-5.txz
+-rw-r--r-- 1 root root 195 2024-06-10 18:08 ./slackware64/n/net-snmp-5.9.4-x86_64-5.txz.asc
-rw-r--r-- 1 root root 513 2021-02-13 12:14 ./slackware64/n/net-tools-20181103_0eebece-x86_64-3.txt
-rw-r--r-- 1 root root 130856 2021-02-13 12:14 ./slackware64/n/net-tools-20181103_0eebece-x86_64-3.txz
-rw-r--r-- 1 root root 163 2021-02-13 12:14 ./slackware64/n/net-tools-20181103_0eebece-x86_64-3.txz.asc
@@ -4432,15 +4435,15 @@ drwxr-xr-x 2 root root 36864 2024-06-08 19:45 ./slackware64/n
-rw-r--r-- 1 root root 532 2024-03-29 05:01 ./slackware64/n/nss-pam-ldapd-0.9.12-x86_64-4.txt
-rw-r--r-- 1 root root 170112 2024-03-29 05:01 ./slackware64/n/nss-pam-ldapd-0.9.12-x86_64-4.txz
-rw-r--r-- 1 root root 195 2024-03-29 05:01 ./slackware64/n/nss-pam-ldapd-0.9.12-x86_64-4.txz.asc
--rw-r--r-- 1 root root 562 2024-06-01 18:32 ./slackware64/n/ntp-4.2.8p18-x86_64-2.txt
--rw-r--r-- 1 root root 2057640 2024-06-01 18:32 ./slackware64/n/ntp-4.2.8p18-x86_64-2.txz
--rw-r--r-- 1 root root 195 2024-06-01 18:32 ./slackware64/n/ntp-4.2.8p18-x86_64-2.txz.asc
+-rw-r--r-- 1 root root 562 2024-06-10 18:11 ./slackware64/n/ntp-4.2.8p18-x86_64-3.txt
+-rw-r--r-- 1 root root 2057252 2024-06-10 18:11 ./slackware64/n/ntp-4.2.8p18-x86_64-3.txz
+-rw-r--r-- 1 root root 195 2024-06-10 18:11 ./slackware64/n/ntp-4.2.8p18-x86_64-3.txz.asc
-rw-r--r-- 1 root root 531 2024-03-29 05:01 ./slackware64/n/obexftp-0.24.2-x86_64-12.txt
-rw-r--r-- 1 root root 93792 2024-03-29 05:01 ./slackware64/n/obexftp-0.24.2-x86_64-12.txz
-rw-r--r-- 1 root root 195 2024-03-29 05:01 ./slackware64/n/obexftp-0.24.2-x86_64-12.txz.asc
--rw-r--r-- 1 root root 479 2024-05-22 17:55 ./slackware64/n/openldap-2.6.8-x86_64-1.txt
--rw-r--r-- 1 root root 2548836 2024-05-22 17:55 ./slackware64/n/openldap-2.6.8-x86_64-1.txz
--rw-r--r-- 1 root root 195 2024-05-22 17:55 ./slackware64/n/openldap-2.6.8-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 479 2024-06-10 18:12 ./slackware64/n/openldap-2.6.8-x86_64-2.txt
+-rw-r--r-- 1 root root 2551004 2024-06-10 18:12 ./slackware64/n/openldap-2.6.8-x86_64-2.txz
+-rw-r--r-- 1 root root 195 2024-06-10 18:12 ./slackware64/n/openldap-2.6.8-x86_64-2.txz.asc
-rw-r--r-- 1 root root 535 2021-02-13 12:19 ./slackware64/n/openobex-1.7.2-x86_64-5.txt
-rw-r--r-- 1 root root 171960 2021-02-13 12:19 ./slackware64/n/openobex-1.7.2-x86_64-5.txz
-rw-r--r-- 1 root root 163 2021-02-13 12:19 ./slackware64/n/openobex-1.7.2-x86_64-5.txz.asc
@@ -5081,8 +5084,8 @@ drwxr-xr-x 2 root root 65536 2024-06-09 18:44 ./slackware64/x
-rw-r--r-- 1 root root 357 2024-02-05 19:19 ./slackware64/x/makedepend-1.0.9-x86_64-1.txt
-rw-r--r-- 1 root root 30240 2024-02-05 19:19 ./slackware64/x/makedepend-1.0.9-x86_64-1.txz
-rw-r--r-- 1 root root 163 2024-02-05 19:19 ./slackware64/x/makedepend-1.0.9-x86_64-1.txz.asc
--rw-r--r-- 1 root root 22932 2024-03-20 20:51 ./slackware64/x/maketag
--rw-r--r-- 1 root root 22932 2024-03-20 20:51 ./slackware64/x/maketag.ez
+-rw-r--r-- 1 root root 22932 2024-06-10 19:21 ./slackware64/x/maketag
+-rw-r--r-- 1 root root 22932 2024-06-10 19:21 ./slackware64/x/maketag.ez
-rw-r--r-- 1 root root 485 2024-03-29 05:07 ./slackware64/x/marisa-0.2.6-x86_64-9.txt
-rw-r--r-- 1 root root 161912 2024-03-29 05:07 ./slackware64/x/marisa-0.2.6-x86_64-9.txz
-rw-r--r-- 1 root root 195 2024-03-29 05:07 ./slackware64/x/marisa-0.2.6-x86_64-9.txz.asc
@@ -5149,7 +5152,7 @@ drwxr-xr-x 2 root root 65536 2024-06-09 18:44 ./slackware64/x
-rw-r--r-- 1 root root 249 2022-10-15 19:50 ./slackware64/x/smproxy-1.0.7-x86_64-1.txt
-rw-r--r-- 1 root root 23772 2022-10-15 19:50 ./slackware64/x/smproxy-1.0.7-x86_64-1.txz
-rw-r--r-- 1 root root 163 2022-10-15 19:50 ./slackware64/x/smproxy-1.0.7-x86_64-1.txz.asc
--rw-r--r-- 1 root root 4563 2024-03-20 20:51 ./slackware64/x/tagfile
+-rw-r--r-- 1 root root 4563 2024-06-10 19:21 ./slackware64/x/tagfile
-rw-r--r-- 1 root root 545 2021-02-13 13:01 ./slackware64/x/tibmachuni-font-ttf-1.901b-noarch-5.txt
-rw-r--r-- 1 root root 865084 2021-02-13 13:01 ./slackware64/x/tibmachuni-font-ttf-1.901b-noarch-5.txz
-rw-r--r-- 1 root root 163 2021-02-13 13:01 ./slackware64/x/tibmachuni-font-ttf-1.901b-noarch-5.txz.asc
@@ -5486,9 +5489,9 @@ drwxr-xr-x 2 root root 65536 2024-06-09 18:44 ./slackware64/x
-rw-r--r-- 1 root root 342 2022-10-31 18:09 ./slackware64/x/xsetroot-1.1.3-x86_64-1.txt
-rw-r--r-- 1 root root 21940 2022-10-31 18:09 ./slackware64/x/xsetroot-1.1.3-x86_64-1.txz
-rw-r--r-- 1 root root 163 2022-10-31 18:09 ./slackware64/x/xsetroot-1.1.3-x86_64-1.txz.asc
--rw-r--r-- 1 root root 253 2024-03-04 19:28 ./slackware64/x/xsm-1.0.6-x86_64-1.txt
--rw-r--r-- 1 root root 57288 2024-03-04 19:28 ./slackware64/x/xsm-1.0.6-x86_64-1.txz
--rw-r--r-- 1 root root 163 2024-03-04 19:28 ./slackware64/x/xsm-1.0.6-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 253 2024-03-04 19:28 ./slackware64/x/xsm-1.0.6-x86_64-1.txt
+-rw-r--r-- 1 root root 57288 2024-03-04 19:28 ./slackware64/x/xsm-1.0.6-x86_64-1.txz
+-rw-r--r-- 1 root root 163 2024-03-04 19:28 ./slackware64/x/xsm-1.0.6-x86_64-1.txz.asc
-rw-r--r-- 1 root root 421 2022-12-04 19:50 ./slackware64/x/xstdcmap-1.0.5-x86_64-1.txt
-rw-r--r-- 1 root root 18720 2022-12-04 19:50 ./slackware64/x/xstdcmap-1.0.5-x86_64-1.txz
-rw-r--r-- 1 root root 163 2022-12-04 19:50 ./slackware64/x/xstdcmap-1.0.5-x86_64-1.txz.asc
@@ -5513,7 +5516,7 @@ drwxr-xr-x 2 root root 65536 2024-06-09 18:44 ./slackware64/x
-rw-r--r-- 1 root root 213 2022-07-11 18:36 ./slackware64/x/xwud-1.0.6-x86_64-1.txt
-rw-r--r-- 1 root root 25896 2022-07-11 18:36 ./slackware64/x/xwud-1.0.6-x86_64-1.txz
-rw-r--r-- 1 root root 163 2022-07-11 18:36 ./slackware64/x/xwud-1.0.6-x86_64-1.txz.asc
-drwxr-xr-x 2 root root 16384 2024-06-06 19:25 ./slackware64/xap
+drwxr-xr-x 2 root root 16384 2024-06-10 19:26 ./slackware64/xap
-rw-r--r-- 1 root root 625 2024-05-04 01:48 ./slackware64/xap/MPlayer-20240403-x86_64-2.txt
-rw-r--r-- 1 root root 2705916 2024-05-04 01:48 ./slackware64/xap/MPlayer-20240403-x86_64-2.txz
-rw-r--r-- 1 root root 195 2024-05-04 01:48 ./slackware64/xap/MPlayer-20240403-x86_64-2.txz.asc
@@ -5580,9 +5583,9 @@ drwxr-xr-x 2 root root 16384 2024-06-06 19:25 ./slackware64/xap
-rw-r--r-- 1 root root 369 2021-02-13 13:37 ./slackware64/xap/gv-3.7.4-x86_64-5.txt
-rw-r--r-- 1 root root 207120 2021-02-13 13:37 ./slackware64/xap/gv-3.7.4-x86_64-5.txz
-rw-r--r-- 1 root root 163 2021-02-13 13:37 ./slackware64/xap/gv-3.7.4-x86_64-5.txz.asc
--rw-r--r-- 1 root root 231 2024-03-29 05:07 ./slackware64/xap/hexchat-2.16.2-x86_64-2.txt
--rw-r--r-- 1 root root 1149936 2024-03-29 05:07 ./slackware64/xap/hexchat-2.16.2-x86_64-2.txz
--rw-r--r-- 1 root root 195 2024-03-29 05:07 ./slackware64/xap/hexchat-2.16.2-x86_64-2.txz.asc
+-rw-r--r-- 1 root root 231 2024-06-10 18:11 ./slackware64/xap/hexchat-2.16.2-x86_64-3.txt
+-rw-r--r-- 1 root root 1149992 2024-06-10 18:11 ./slackware64/xap/hexchat-2.16.2-x86_64-3.txz
+-rw-r--r-- 1 root root 195 2024-06-10 18:11 ./slackware64/xap/hexchat-2.16.2-x86_64-3.txz.asc
-rwxr-xr-x 1 root root 2897 2009-06-24 22:06 ./slackware64/xap/install-packages
-rw-r--r-- 1 root root 446 2006-09-18 10:41 ./slackware64/xap/install.end
-rw-r--r-- 1 root root 306 2023-01-09 19:24 ./slackware64/xap/libnma-1.10.6-x86_64-1.txt
@@ -5608,15 +5611,15 @@ drwxr-xr-x 2 root root 16384 2024-06-06 19:25 ./slackware64/xap
-rw-r--r-- 1 root root 479 2024-05-22 21:02 ./slackware64/xap/pavucontrol-6.0-x86_64-1.txt
-rw-r--r-- 1 root root 173128 2024-05-22 21:02 ./slackware64/xap/pavucontrol-6.0-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-05-22 21:02 ./slackware64/xap/pavucontrol-6.0-x86_64-1.txz.asc
--rw-r--r-- 1 root root 457 2024-02-23 18:45 ./slackware64/xap/pidgin-2.14.13-x86_64-1.txt
--rw-r--r-- 1 root root 5799848 2024-02-23 18:45 ./slackware64/xap/pidgin-2.14.13-x86_64-1.txz
--rw-r--r-- 1 root root 163 2024-02-23 18:45 ./slackware64/xap/pidgin-2.14.13-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 457 2024-06-10 18:16 ./slackware64/xap/pidgin-2.14.13-x86_64-2.txt
+-rw-r--r-- 1 root root 5781384 2024-06-10 18:16 ./slackware64/xap/pidgin-2.14.13-x86_64-2.txz
+-rw-r--r-- 1 root root 195 2024-06-10 18:16 ./slackware64/xap/pidgin-2.14.13-x86_64-2.txz.asc
-rw-r--r-- 1 root root 378 2021-02-13 13:40 ./slackware64/xap/rdesktop-1.9.0-x86_64-4.txt
-rw-r--r-- 1 root root 205788 2021-02-13 13:40 ./slackware64/xap/rdesktop-1.9.0-x86_64-4.txz
-rw-r--r-- 1 root root 163 2021-02-13 13:40 ./slackware64/xap/rdesktop-1.9.0-x86_64-4.txz.asc
--rw-r--r-- 1 root root 480 2024-02-20 19:05 ./slackware64/xap/rxvt-unicode-9.31-x86_64-2.txt
--rw-r--r-- 1 root root 898412 2024-02-20 19:05 ./slackware64/xap/rxvt-unicode-9.31-x86_64-2.txz
--rw-r--r-- 1 root root 163 2024-02-20 19:05 ./slackware64/xap/rxvt-unicode-9.31-x86_64-2.txz.asc
+-rw-r--r-- 1 root root 480 2024-06-10 18:12 ./slackware64/xap/rxvt-unicode-9.31-x86_64-3.txt
+-rw-r--r-- 1 root root 918656 2024-06-10 18:12 ./slackware64/xap/rxvt-unicode-9.31-x86_64-3.txz
+-rw-r--r-- 1 root root 195 2024-06-10 18:12 ./slackware64/xap/rxvt-unicode-9.31-x86_64-3.txz.asc
-rw-r--r-- 1 root root 359 2024-05-25 18:14 ./slackware64/xap/sane-1.3.1-x86_64-1.txt
-rw-r--r-- 1 root root 3589520 2024-05-25 18:14 ./slackware64/xap/sane-1.3.1-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-05-25 18:14 ./slackware64/xap/sane-1.3.1-x86_64-1.txz.asc
@@ -5630,9 +5633,9 @@ drwxr-xr-x 2 root root 16384 2024-06-06 19:25 ./slackware64/xap
-rw-r--r-- 1 root root 1356360 2024-01-28 21:04 ./slackware64/xap/ssr-0.4.4-x86_64-2.txz
-rw-r--r-- 1 root root 163 2024-01-28 21:04 ./slackware64/xap/ssr-0.4.4-x86_64-2.txz.asc
-rw-r--r-- 1 root root 684 2024-05-31 18:46 ./slackware64/xap/tagfile
--rw-r--r-- 1 root root 527 2024-05-26 17:28 ./slackware64/xap/vim-gvim-9.1.0446-x86_64-1.txt
--rw-r--r-- 1 root root 1797556 2024-05-26 17:28 ./slackware64/xap/vim-gvim-9.1.0446-x86_64-1.txz
--rw-r--r-- 1 root root 195 2024-05-26 17:28 ./slackware64/xap/vim-gvim-9.1.0446-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 527 2024-06-10 17:55 ./slackware64/xap/vim-gvim-9.1.0473-x86_64-1.txt
+-rw-r--r-- 1 root root 1799812 2024-06-10 17:55 ./slackware64/xap/vim-gvim-9.1.0473-x86_64-1.txz
+-rw-r--r-- 1 root root 195 2024-06-10 17:55 ./slackware64/xap/vim-gvim-9.1.0473-x86_64-1.txz.asc
-rw-r--r-- 1 root root 455 2023-12-05 23:07 ./slackware64/xap/windowmaker-0.96.0-x86_64-2.txt
-rw-r--r-- 1 root root 1782724 2023-12-05 23:07 ./slackware64/xap/windowmaker-0.96.0-x86_64-2.txz
-rw-r--r-- 1 root root 163 2023-12-05 23:07 ./slackware64/xap/windowmaker-0.96.0-x86_64-2.txz.asc
@@ -5669,13 +5672,13 @@ drwxr-xr-x 2 root root 16384 2024-06-06 19:25 ./slackware64/xap
-rw-r--r-- 1 root root 498 2023-12-05 23:08 ./slackware64/xap/xsane-0.999-x86_64-6.txt
-rw-r--r-- 1 root root 1624064 2023-12-05 23:08 ./slackware64/xap/xsane-0.999-x86_64-6.txz
-rw-r--r-- 1 root root 163 2023-12-05 23:08 ./slackware64/xap/xsane-0.999-x86_64-6.txz.asc
--rw-r--r-- 1 root root 463 2024-01-28 21:05 ./slackware64/xap/xscreensaver-6.08-x86_64-2.txt
--rw-r--r-- 1 root root 9231156 2024-01-28 21:05 ./slackware64/xap/xscreensaver-6.08-x86_64-2.txz
--rw-r--r-- 1 root root 163 2024-01-28 21:05 ./slackware64/xap/xscreensaver-6.08-x86_64-2.txz.asc
+-rw-r--r-- 1 root root 463 2024-06-10 17:44 ./slackware64/xap/xscreensaver-6.09-x86_64-1.txt
+-rw-r--r-- 1 root root 9578584 2024-06-10 17:44 ./slackware64/xap/xscreensaver-6.09-x86_64-1.txz
+-rw-r--r-- 1 root root 195 2024-06-10 17:44 ./slackware64/xap/xscreensaver-6.09-x86_64-1.txz.asc
-rw-r--r-- 1 root root 230 2024-05-25 17:29 ./slackware64/xap/xsnow-3.7.9-x86_64-2.txt
-rw-r--r-- 1 root root 1829408 2024-05-25 17:29 ./slackware64/xap/xsnow-3.7.9-x86_64-2.txz
-rw-r--r-- 1 root root 195 2024-05-25 17:29 ./slackware64/xap/xsnow-3.7.9-x86_64-2.txz.asc
-drwxr-xr-x 2 root root 12288 2024-06-09 18:44 ./slackware64/xfce
+drwxr-xr-x 2 root root 12288 2024-06-10 19:26 ./slackware64/xfce
-rw-r--r-- 1 root root 253 2021-10-01 03:27 ./slackware64/xfce/Greybird-3.22.15-noarch-1.txt
-rw-r--r-- 1 root root 189900 2021-10-01 03:27 ./slackware64/xfce/Greybird-3.22.15-noarch-1.txz
-rw-r--r-- 1 root root 163 2021-10-01 03:27 ./slackware64/xfce/Greybird-3.22.15-noarch-1.txz.asc
@@ -5729,9 +5732,9 @@ drwxr-xr-x 2 root root 12288 2024-06-09 18:44 ./slackware64/xfce
-rw-r--r-- 1 root root 640 2023-06-05 18:54 ./slackware64/xfce/xfce4-panel-profiles-1.0.14-x86_64-1.txt
-rw-r--r-- 1 root root 84556 2023-06-05 18:54 ./slackware64/xfce/xfce4-panel-profiles-1.0.14-x86_64-1.txz
-rw-r--r-- 1 root root 163 2023-06-05 18:54 ./slackware64/xfce/xfce4-panel-profiles-1.0.14-x86_64-1.txz.asc
--rw-r--r-- 1 root root 413 2023-11-30 21:13 ./slackware64/xfce/xfce4-power-manager-4.18.3-x86_64-1.txt
--rw-r--r-- 1 root root 533516 2023-11-30 21:13 ./slackware64/xfce/xfce4-power-manager-4.18.3-x86_64-1.txz
--rw-r--r-- 1 root root 163 2023-11-30 21:13 ./slackware64/xfce/xfce4-power-manager-4.18.3-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 413 2024-06-10 17:36 ./slackware64/xfce/xfce4-power-manager-4.18.4-x86_64-1.txt
+-rw-r--r-- 1 root root 534492 2024-06-10 17:36 ./slackware64/xfce/xfce4-power-manager-4.18.4-x86_64-1.txz
+-rw-r--r-- 1 root root 195 2024-06-10 17:36 ./slackware64/xfce/xfce4-power-manager-4.18.4-x86_64-1.txz.asc
-rw-r--r-- 1 root root 598 2023-10-02 18:32 ./slackware64/xfce/xfce4-pulseaudio-plugin-0.4.8-x86_64-1.txt
-rw-r--r-- 1 root root 106620 2023-10-02 18:32 ./slackware64/xfce/xfce4-pulseaudio-plugin-0.4.8-x86_64-1.txz
-rw-r--r-- 1 root root 163 2023-10-02 18:32 ./slackware64/xfce/xfce4-pulseaudio-plugin-0.4.8-x86_64-1.txz.asc
@@ -5741,9 +5744,9 @@ drwxr-xr-x 2 root root 12288 2024-06-09 18:44 ./slackware64/xfce
-rw-r--r-- 1 root root 365 2024-05-29 17:14 ./slackware64/xfce/xfce4-screenshooter-1.10.6-x86_64-1.txt
-rw-r--r-- 1 root root 192864 2024-05-29 17:14 ./slackware64/xfce/xfce4-screenshooter-1.10.6-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-05-29 17:14 ./slackware64/xfce/xfce4-screenshooter-1.10.6-x86_64-1.txz.asc
--rw-r--r-- 1 root root 449 2023-05-29 18:10 ./slackware64/xfce/xfce4-session-4.18.3-x86_64-1.txt
--rw-r--r-- 1 root root 322100 2023-05-29 18:10 ./slackware64/xfce/xfce4-session-4.18.3-x86_64-1.txz
--rw-r--r-- 1 root root 163 2023-05-29 18:10 ./slackware64/xfce/xfce4-session-4.18.3-x86_64-1.txz.asc
+-rw-r--r-- 1 root root 449 2024-06-10 17:39 ./slackware64/xfce/xfce4-session-4.18.4-x86_64-1.txt
+-rw-r--r-- 1 root root 355280 2024-06-10 17:39 ./slackware64/xfce/xfce4-session-4.18.4-x86_64-1.txz
+-rw-r--r-- 1 root root 195 2024-06-10 17:39 ./slackware64/xfce/xfce4-session-4.18.4-x86_64-1.txz.asc
-rw-r--r-- 1 root root 377 2024-06-09 17:08 ./slackware64/xfce/xfce4-settings-4.18.5-x86_64-1.txt
-rw-r--r-- 1 root root 839552 2024-06-09 17:08 ./slackware64/xfce/xfce4-settings-4.18.5-x86_64-1.txz
-rw-r--r-- 1 root root 195 2024-06-09 17:08 ./slackware64/xfce/xfce4-settings-4.18.5-x86_64-1.txz.asc
@@ -5783,11 +5786,11 @@ drwxr-xr-x 2 root root 4096 2024-05-05 18:37 ./slackware64/y
-rw-r--r-- 1 root root 1488844 2024-05-05 17:22 ./slackware64/y/nethack-3.6.7-x86_64-2.txz
-rw-r--r-- 1 root root 195 2024-05-05 17:22 ./slackware64/y/nethack-3.6.7-x86_64-2.txz.asc
-rw-r--r-- 1 root root 26 2020-12-30 21:55 ./slackware64/y/tagfile
-drwxr-xr-x 18 root root 4096 2024-06-09 18:45 ./source
--rw-r--r-- 1 root root 623225 2024-06-09 18:45 ./source/CHECKSUMS.md5
--rw-r--r-- 1 root root 195 2024-06-09 18:45 ./source/CHECKSUMS.md5.asc
--rw-r--r-- 1 root root 868569 2024-06-09 18:45 ./source/FILE_LIST
--rw-r--r-- 1 root root 29354723 2024-06-09 18:45 ./source/MANIFEST.bz2
+drwxr-xr-x 18 root root 4096 2024-06-10 19:27 ./source
+-rw-r--r-- 1 root root 623501 2024-06-10 19:27 ./source/CHECKSUMS.md5
+-rw-r--r-- 1 root root 195 2024-06-10 19:27 ./source/CHECKSUMS.md5.asc
+-rw-r--r-- 1 root root 868971 2024-06-10 19:27 ./source/FILE_LIST
+-rw-r--r-- 1 root root 29350530 2024-06-10 19:27 ./source/MANIFEST.bz2
-rw-r--r-- 1 root root 828 2022-02-02 04:43 ./source/README.TXT
drwxr-xr-x 124 root root 4096 2024-05-23 18:35 ./source/a
-rw-r--r-- 1 root root 339 2023-09-28 19:06 ./source/a/FTBFSlog
@@ -6924,7 +6927,7 @@ drwxr-xr-x 2 root root 4096 2024-05-11 06:35 ./source/a/zoo
-rwxr-xr-x 1 root root 3232 2024-05-11 06:35 ./source/a/zoo/zoo.SlackBuild
-rw-r--r-- 1 root root 249 2024-05-11 06:35 ./source/a/zoo/zoo.gcc14.diff.gz
-rw-r--r-- 1 root root 14984 2015-12-16 15:31 ./source/a/zoo/zoo_2.10-28.debian.tar.xz
-drwxr-xr-x 88 root root 4096 2024-05-24 19:36 ./source/ap
+drwxr-xr-x 89 root root 4096 2024-06-10 18:17 ./source/ap
-rw-r--r-- 1 root root 363 2023-03-01 20:06 ./source/ap/FTBFSlog
drwxr-xr-x 2 root root 4096 2024-03-14 19:01 ./source/ap/a2ps
-rw-r--r-- 1 root root 1806744 2024-03-13 18:12 ./source/ap/a2ps/a2ps-4.15.6.tar.lz
@@ -7458,6 +7461,10 @@ drwxr-xr-x 2 root root 4096 2023-03-28 18:23 ./source/ap/squashfs-tools
-rw-r--r-- 1 root root 1078 2018-09-13 21:00 ./source/ap/squashfs-tools/slack-desc
-rw-r--r-- 1 root root 202913 2023-03-25 20:53 ./source/ap/squashfs-tools/squashfs-tools-4.6.1.tar.lz
-rwxr-xr-- 1 root root 4284 2023-03-20 17:48 ./source/ap/squashfs-tools/squashfs-tools.SlackBuild
+drwxr-xr-x 2 root root 4096 2024-06-10 18:27 ./source/ap/stow
+-rw-r--r-- 1 root root 967 2024-06-10 18:30 ./source/ap/stow/slack-desc
+-rw-r--r-- 1 root root 555921 2024-04-07 21:31 ./source/ap/stow/stow-2.4.0.tar.lz
+-rwxr-xr-x 1 root root 4546 2024-06-10 18:27 ./source/ap/stow/stow.SlackBuild
drwxr-xr-x 2 root root 4096 2023-12-30 19:22 ./source/ap/sudo
-rw-r--r-- 1 root root 275 2004-09-19 00:25 ./source/ap/sudo/doinst.sh.gz
-rw-r--r-- 1 root root 894 2018-02-27 06:12 ./source/ap/sudo/slack-desc
@@ -7481,7 +7488,7 @@ drwxr-xr-x 2 root root 4096 2023-10-18 19:44 ./source/ap/texinfo
-rw-r--r-- 1 root root 1069 2018-02-27 06:12 ./source/ap/texinfo/slack-desc
-rw-r--r-- 1 root root 5545720 2023-10-18 13:51 ./source/ap/texinfo/texinfo-7.1.tar.xz
-rw-r--r-- 1 root root 265 2023-10-18 13:51 ./source/ap/texinfo/texinfo-7.1.tar.xz.sig
--rwxr-xr-x 1 root root 5039 2023-10-18 19:44 ./source/ap/texinfo/texinfo.SlackBuild
+-rwxr-xr-x 1 root root 5039 2024-06-10 17:56 ./source/ap/texinfo/texinfo.SlackBuild
-rw-r--r-- 1 root root 571 2019-09-24 20:23 ./source/ap/texinfo/update-info-dir.8.gz
-rw-r--r-- 1 root root 859 2019-09-24 20:26 ./source/ap/texinfo/update-info-dir.gz
drwxr-xr-x 2 root root 4096 2024-02-13 18:43 ./source/ap/tmux
@@ -7509,14 +7516,14 @@ drwxr-xr-x 2 root root 4096 2021-02-13 05:31 ./source/ap/vbetool
-rw-r--r-- 1 root root 24915 2015-12-20 20:37 ./source/ap/vbetool/vbetool-1.2.2.tar.gz
-rwxr-xr-x 1 root root 3202 2021-02-13 05:31 ./source/ap/vbetool/vbetool.SlackBuild
-rw-r--r-- 1 root root 129 2008-11-24 18:23 ./source/ap/vbetool/vbetool.info
-drwxr-xr-x 2 root root 4096 2024-05-26 17:27 ./source/ap/vim
+drwxr-xr-x 2 root root 4096 2024-06-10 17:54 ./source/ap/vim
-rw-r--r-- 1 root root 299348 2009-07-09 22:03 ./source/ap/vim/ctags-5.8.tar.xz
-rw-r--r-- 1 root root 2768 2022-02-12 08:11 ./source/ap/vim/ctags.use-conventional-unused-marker.patch.gz
-rw-r--r-- 1 root root 505 2022-09-26 18:00 ./source/ap/vim/doinst.sh.gz
-rw-r--r-- 1 root root 8249 2006-01-19 17:01 ./source/ap/vim/gvim.png
-rw-r--r-- 1 root root 858 2023-08-07 19:00 ./source/ap/vim/slack-desc.vim
-rw-r--r-- 1 root root 983 2023-08-07 19:01 ./source/ap/vim/slack-desc.vim-gvim
--rw-r--r-- 1 root root 11504134 2024-05-26 17:26 ./source/ap/vim/vim-9.1.0446.tar.lz
+-rw-r--r-- 1 root root 11520189 2024-06-10 17:53 ./source/ap/vim/vim-9.1.0473.tar.lz
-rwxr-xr-x 1 root root 6289 2024-03-23 17:20 ./source/ap/vim/vim-gvim.SlackBuild
-rwxr-xr-x 1 root root 7680 2024-03-23 17:18 ./source/ap/vim/vim.SlackBuild
-rw-r--r-- 1 root root 76 2022-12-08 18:30 ./source/ap/vim/vim.url
@@ -7614,10 +7621,12 @@ drwxr-xr-x 2 root root 4096 2023-09-13 18:44 ./source/d/cbindgen
-rwxr-xr-x 1 root root 3865 2022-12-07 18:28 ./source/d/cbindgen/cbindgen.SlackBuild
-rwxr-xr-x 1 root root 831 2023-09-13 18:44 ./source/d/cbindgen/fetch-sources.sh
-rw-r--r-- 1 root root 1150 2022-12-07 17:56 ./source/d/cbindgen/slack-desc
-drwxr-xr-x 2 root root 4096 2024-05-31 17:27 ./source/d/ccache
+drwxr-xr-x 2 root root 4096 2024-06-10 18:36 ./source/d/ccache
-rw-r--r-- 1 root root 411272 2024-05-29 20:16 ./source/d/ccache/ccache-4.10.tar.xz
-rw-r--r-- 1 root root 833 2024-05-29 20:16 ./source/d/ccache/ccache-4.10.tar.xz.asc
--rwxr-xr-x 1 root root 3593 2021-08-21 02:56 ./source/d/ccache/ccache.SlackBuild
+-rwxr-xr-x 1 root root 3835 2024-06-10 18:38 ./source/d/ccache/ccache.SlackBuild
+-rw-r--r-- 1 root root 60127 2023-03-15 12:39 ./source/d/ccache/doctest.h.gz
+-rw-r--r-- 1 root root 71 2024-06-10 18:34 ./source/d/ccache/doctest.h.url
-rw-r--r-- 1 root root 804 2018-02-27 06:13 ./source/d/ccache/slack-desc
drwxr-xr-x 2 root root 4096 2022-09-06 18:27 ./source/d/check
-rw-r--r-- 1 root root 220051 2020-08-09 06:12 ./source/d/check/check-0.15.2.tar.lz
@@ -7874,9 +7883,9 @@ drwxr-xr-x 2 root root 4096 2023-04-24 19:57 ./source/d/patchelf
-rw-r--r-- 1 root root 286397 2023-04-23 11:31 ./source/d/patchelf/patchelf-0.18.0.tar.lz
-rwxr-xr-x 1 root root 4424 2022-09-06 18:27 ./source/d/patchelf/patchelf.SlackBuild
-rw-r--r-- 1 root root 925 2018-02-27 06:13 ./source/d/patchelf/slack-desc
-drwxr-xr-x 2 root root 4096 2024-03-18 21:24 ./source/d/perl
+drwxr-xr-x 2 root root 4096 2024-06-10 17:18 ./source/d/perl
-rw-r--r-- 1 root root 37488 2023-08-10 10:19 ./source/d/perl/Authen-SASL-2.1700.tar.gz
--rw-r--r-- 1 root root 161166 2023-10-04 07:10 ./source/d/perl/DBD-mysql-4.051.tar.gz
+-rw-r--r-- 1 root root 162074 2023-12-01 07:13 ./source/d/perl/DBD-mysql-4.052.tar.gz
-rw-r--r-- 1 root root 612372 2020-01-31 19:02 ./source/d/perl/DBI-1.643.tar.gz
-rw-r--r-- 1 root root 15863 2022-05-04 14:32 ./source/d/perl/Devel-CheckLib-1.16.tar.gz
-rw-r--r-- 1 root root 265644 2024-01-22 19:07 ./source/d/perl/IO-Socket-SSL-2.085.tar.gz
@@ -7888,17 +7897,17 @@ drwxr-xr-x 2 root root 4096 2024-03-18 21:24 ./source/d/perl
-rw-r--r-- 1 root root 108583 2023-01-05 20:56 ./source/d/perl/Moo-2.005005.tar.gz
-rw-r--r-- 1 root root 663948 2024-01-08 01:22 ./source/d/perl/Net-SSLeay-1.94.tar.gz
-rw-r--r-- 1 root root 108661 2017-08-04 08:05 ./source/d/perl/Parse-Yapp-1.21.tar.gz
--rw-r--r-- 1 root root 105730 2022-12-01 16:37 ./source/d/perl/Path-Tiny-0.144.tar.gz
+-rw-r--r-- 1 root root 105879 2024-05-08 15:51 ./source/d/perl/Path-Tiny-0.146.tar.gz
-rw-r--r-- 1 root root 35925 2023-01-20 10:28 ./source/d/perl/Sub-Quote-2.006008.tar.gz
-rw-r--r-- 1 root root 515947 2022-08-16 07:02 ./source/d/perl/Template-Toolkit-3.101.tar.gz
-rw-r--r-- 1 root root 85164 2019-01-05 11:57 ./source/d/perl/TermReadKey-2.38.tar.gz
--rw-r--r-- 1 root root 123909 2024-02-09 15:02 ./source/d/perl/URI-5.27.tar.gz
+-rw-r--r-- 1 root root 124581 2024-03-27 01:50 ./source/d/perl/URI-5.28.tar.gz
-rw-r--r-- 1 root root 279029 2023-12-29 00:31 ./source/d/perl/XML-Parser-2.47.tar.gz
-rw-r--r-- 1 root root 78443 2018-03-18 03:19 ./source/d/perl/XML-Simple-2.25.tar.gz
-rw-r--r-- 1 root root 844 2017-01-14 23:40 ./source/d/perl/libnet-3.08-Do-not-create-Net-libnet.cfg.patch.gz
-rw-r--r-- 1 root root 95593 2023-03-20 19:15 ./source/d/perl/libnet-3.15.tar.gz
--rw-r--r-- 1 root root 13296690 2023-11-29 16:10 ./source/d/perl/perl-5.38.2.tar.lz
--rwxr-xr-x 1 root root 19345 2024-03-28 17:51 ./source/d/perl/perl.SlackBuild
+-rw-r--r-- 1 root root 13379306 2024-06-09 20:45 ./source/d/perl/perl-5.40.0.tar.lz
+-rwxr-xr-x 1 root root 19345 2024-06-10 17:20 ./source/d/perl/perl.SlackBuild
-rw-r--r-- 1 root root 606 2008-09-21 00:04 ./source/d/perl/perl.configure.multilib.patch.gz
-rw-r--r-- 1 root root 996 2021-05-21 04:51 ./source/d/perl/slack-desc
drwxr-xr-x 3 root root 4096 2021-02-13 05:31 ./source/d/pkg-config
@@ -8009,7 +8018,7 @@ drwxr-xr-x 2 root root 4096 2023-12-29 20:10 ./source/d/subversion
-rwxr-xr-x 1 root root 211 2020-05-27 22:59 ./source/d/subversion/get-svn-book.sh
-rw-r--r-- 1 root root 1005 2018-07-23 18:17 ./source/d/subversion/slack-desc
-rw-r--r-- 1 root root 6609112 2023-12-28 05:18 ./source/d/subversion/subversion-1.14.3.tar.lz
--rwxr-xr-x 1 root root 6792 2024-05-11 01:54 ./source/d/subversion/subversion.SlackBuild
+-rwxr-xr-x 1 root root 6792 2024-06-10 17:57 ./source/d/subversion/subversion.SlackBuild
-rw-r--r-- 1 root root 470922 2023-12-29 02:00 ./source/d/subversion/svn-book-html.tar.bz2
drwxr-xr-x 2 root root 4096 2024-02-26 19:45 ./source/d/swig
-rw-r--r-- 1 root root 1013 2018-02-27 06:13 ./source/d/swig/slack-desc
@@ -8137,7 +8146,7 @@ drwxr-xr-x 2 root root 4096 2024-06-01 17:14 ./source/kde/fcitx5-configto
-rw-r--r-- 1 root root 310 2024-05-31 15:05 ./source/kde/fcitx5-configtool/fcitx5-configtool-5.1.6.tar.zst.sig
-rwxr-xr-x 1 root root 3471 2024-04-24 17:48 ./source/kde/fcitx5-configtool/fcitx5-configtool.SlackBuild
-rw-r--r-- 1 root root 56 2022-05-19 18:15 ./source/kde/fcitx5-configtool/fcitx5-configtool.url
--rw-r--r-- 1 root root 839 2022-05-19 18:25 ./source/kde/fcitx5-configtool/slack-desc
+-rw-r--r-- 1 root root 839 2024-06-10 00:43 ./source/kde/fcitx5-configtool/slack-desc
drwxr-xr-x 2 root root 4096 2022-05-26 14:29 ./source/kde/fcitx5-theme-breeze
-rw-r--r-- 1 root root 17863 2022-03-03 14:27 ./source/kde/fcitx5-theme-breeze/fcitx5-breeze-prebuilt-2.0.0.tar.lz
-rwxr-xr-x 1 root root 2362 2022-05-26 14:26 ./source/kde/fcitx5-theme-breeze/fcitx5-theme-breeze.SlackBuild
@@ -8755,9 +8764,10 @@ drwxr-xr-x 2 root root 4096 2021-10-26 21:07 ./source/kde/kde/patch/plasm
-rw-r--r-- 1 root root 357 2021-10-26 21:07 ./source/kde/kde/patch/plasma-desktop.patch
-rw-r--r-- 1 root root 840 2020-11-22 01:56 ./source/kde/kde/patch/plasma-desktop/plasma-desktop.default_launcher_tasks.diff
-rw-r--r-- 1 root root 82 2024-03-06 20:39 ./source/kde/kde/patch/plasma-sdk.patch
-drwxr-xr-x 2 root root 4096 2023-02-14 18:09 ./source/kde/kde/patch/plasma-workspace
--rw-r--r-- 1 root root 174 2022-10-13 16:43 ./source/kde/kde/patch/plasma-workspace.patch
+drwxr-xr-x 2 root root 4096 2024-06-10 02:52 ./source/kde/kde/patch/plasma-workspace
+-rw-r--r-- 1 root root 342 2024-06-10 02:54 ./source/kde/kde/patch/plasma-workspace.patch
-rw-r--r-- 1 root root 4390 2023-02-14 18:09 ./source/kde/kde/patch/plasma-workspace/0001-Revert-No-icons-on-the-desktop-by-default.patch
+-rw-r--r-- 1 root root 2591 2024-06-10 02:52 ./source/kde/kde/patch/plasma-workspace/1181acfe30557d6646511df8d98d82589878a570.patch
drwxr-xr-x 2 root root 4096 2020-10-31 22:26 ./source/kde/kde/pkgsrc
-rw-r--r-- 1 root root 4405 2014-06-04 17:32 ./source/kde/kde/plasma_checkout.sh
drwxr-xr-x 6 root root 4096 2024-01-11 19:46 ./source/kde/kde/post-install
@@ -9895,7 +9905,7 @@ drwxr-xr-x 2 root root 4096 2024-05-19 18:05 ./source/kde/kde/src/framewo
-rw-r--r-- 1 root root 488 2024-05-04 16:27 ./source/kde/kde/src/frameworks/syntax-highlighting-5.116.0.tar.xz.sig
-rw-r--r-- 1 root root 1413124 2024-05-04 16:27 ./source/kde/kde/src/frameworks/threadweaver-5.116.0.tar.xz
-rw-r--r-- 1 root root 488 2024-05-04 16:27 ./source/kde/kde/src/frameworks/threadweaver-5.116.0.tar.xz.sig
-drwxr-xr-x 2 root root 12288 2024-06-03 18:40 ./source/kde/kde/src/plasma
+drwxr-xr-x 2 root root 12288 2024-06-10 02:53 ./source/kde/kde/src/plasma
drwxr-xr-x 2 root root 4096 2024-04-23 17:36 ./source/kde/kde/src/plasma-extra
-rwxr-xr-x 1 root root 2071 2020-07-12 21:54 ./source/kde/kde/src/plasma-extra/fetch-wacomtablet.sh
-rw-r--r-- 1 root root 136692 2023-08-16 12:59 ./source/kde/kde/src/plasma-extra/kirigami-addons-0.11.0.tar.xz
@@ -10008,8 +10018,8 @@ drwxr-xr-x 2 root root 4096 2024-04-23 17:36 ./source/kde/kde/src/plasma-
-rw-r--r-- 1 root root 833 2024-03-06 12:26 ./source/kde/kde/src/plasma/plasma-thunderbolt-5.27.11.tar.xz.sig
-rw-r--r-- 1 root root 187204 2024-03-06 12:26 ./source/kde/kde/src/plasma/plasma-vault-5.27.11.tar.xz
-rw-r--r-- 1 root root 833 2024-03-06 12:26 ./source/kde/kde/src/plasma/plasma-vault-5.27.11.tar.xz.sig
--rw-r--r-- 1 root root 19486864 2024-03-06 12:27 ./source/kde/kde/src/plasma/plasma-workspace-5.27.11.tar.xz
--rw-r--r-- 1 root root 833 2024-03-06 12:27 ./source/kde/kde/src/plasma/plasma-workspace-5.27.11.tar.xz.sig
+-rw-r--r-- 1 root root 19490624 2024-05-31 14:38 ./source/kde/kde/src/plasma/plasma-workspace-5.27.11.1.tar.xz
+-rw-r--r-- 1 root root 833 2024-05-31 14:38 ./source/kde/kde/src/plasma/plasma-workspace-5.27.11.1.tar.xz.sig
-rw-r--r-- 1 root root 94029756 2024-03-06 12:28 ./source/kde/kde/src/plasma/plasma-workspace-wallpapers-5.27.11.tar.xz
-rw-r--r-- 1 root root 833 2024-03-06 12:28 ./source/kde/kde/src/plasma/plasma-workspace-wallpapers-5.27.11.tar.xz.sig
-rw-r--r-- 1 root root 45828 2024-03-06 12:28 ./source/kde/kde/src/plasma/plymouth-kcm-5.27.11.tar.xz
@@ -10598,11 +10608,10 @@ drwxr-xr-x 2 root root 4096 2024-03-19 21:59 ./source/l/glib-networking
-rw-r--r-- 1 root root 346080 2001-03-15 14:59 ./source/l/glib/glib-1.2.10.tar.bz2
-rwxr-xr-x 1 root root 5603 2024-05-10 19:59 ./source/l/glib/glib.SlackBuild
-rw-r--r-- 1 root root 754 2018-02-27 06:12 ./source/l/glib/slack-desc
-drwxr-xr-x 2 root root 4096 2024-05-25 17:53 ./source/l/glib2
--rw-r--r-- 1 root root 11240 2024-05-25 17:53 ./source/l/glib2/4073.patch
+drwxr-xr-x 2 root root 4096 2024-06-10 17:46 ./source/l/glib2
-rw-r--r-- 1 root root 516 2011-11-06 22:03 ./source/l/glib2/doinst.sh.gz
--rw-r--r-- 1 root root 5529096 2024-05-08 17:49 ./source/l/glib2/glib-2.80.2.tar.xz
--rwxr-xr-x 1 root root 5472 2024-05-25 17:54 ./source/l/glib2/glib2.SlackBuild
+-rw-r--r-- 1 root root 5542940 2024-06-10 12:01 ./source/l/glib2/glib-2.80.3.tar.xz
+-rwxr-xr-x 1 root root 5398 2024-06-10 17:46 ./source/l/glib2/glib2.SlackBuild
-rw-r--r-- 1 root root 913 2021-09-02 23:31 ./source/l/glib2/libglib2.csh
-rw-r--r-- 1 root root 909 2021-09-01 17:51 ./source/l/glib2/libglib2.sh
-rw-r--r-- 1 root root 860 2018-11-15 04:21 ./source/l/glib2/slack-desc
@@ -10867,7 +10876,7 @@ drwxr-xr-x 2 root root 4096 2024-05-26 17:20 ./source/l/imagemagick
-rw-r--r-- 1 root root 10739656 2024-05-25 12:41 ./source/l/imagemagick/ImageMagick-7.1.1-33.tar.lz
-rw-r--r-- 1 root root 833 2024-05-25 13:43 ./source/l/imagemagick/ImageMagick-7.1.1-33.tar.lz.asc
-rw-r--r-- 1 root root 309 2016-05-17 04:08 ./source/l/imagemagick/doinst.sh.gz
--rwxr-xr-x 1 root root 7417 2024-05-26 17:21 ./source/l/imagemagick/imagemagick.SlackBuild
+-rwxr-xr-x 1 root root 7417 2024-06-10 17:57 ./source/l/imagemagick/imagemagick.SlackBuild
-rw-r--r-- 1 root root 81 2022-11-08 20:07 ./source/l/imagemagick/imagemagick.url
-rw-r--r-- 1 root root 996 2018-02-27 06:12 ./source/l/imagemagick/slack-desc
drwxr-xr-x 2 root root 4096 2023-10-05 19:03 ./source/l/immer
@@ -11769,9 +11778,9 @@ drwxr-xr-x 2 root root 4096 2024-02-28 18:18 ./source/l/orc
-rw-r--r-- 1 root root 833 2024-02-27 16:26 ./source/l/orc/orc-0.4.38.tar.xz.asc
-rwxr-xr-x 1 root root 4532 2022-11-09 20:14 ./source/l/orc/orc.SlackBuild
-rw-r--r-- 1 root root 929 2019-10-17 18:01 ./source/l/orc/slack-desc
-drwxr-xr-x 2 root root 4096 2024-03-31 16:42 ./source/l/pango
--rw-r--r-- 1 root root 1963588 2024-03-31 10:05 ./source/l/pango/pango-1.52.2.tar.xz
--rwxr-xr-x 1 root root 4139 2021-03-27 18:16 ./source/l/pango/pango.SlackBuild
+drwxr-xr-x 2 root root 4096 2024-06-09 19:41 ./source/l/pango
+-rw-r--r-- 1 root root 1963180 2024-06-09 18:11 ./source/l/pango/pango-1.54.0.tar.xz
+-rwxr-xr-x 1 root root 4151 2024-06-09 19:42 ./source/l/pango/pango.SlackBuild
-rw-r--r-- 1 root root 31 2023-11-13 17:35 ./source/l/pango/pango.url
-rw-r--r-- 1 root root 913 2023-11-13 17:36 ./source/l/pango/slack-desc
drwxr-xr-x 2 root root 4096 2024-03-21 19:21 ./source/l/pangomm
@@ -12083,10 +12092,10 @@ drwxr-xr-x 2 root root 4096 2024-03-29 03:06 ./source/l/python-notify2
-rw-r--r-- 1 root root 37 2018-02-23 21:12 ./source/l/python-notify2/notify2.url
-rwxr-xr-x 1 root root 2574 2024-03-29 03:06 ./source/l/python-notify2/python-notify2.SlackBuild
-rw-r--r-- 1 root root 996 2018-02-27 06:12 ./source/l/python-notify2/slack-desc
-drwxr-xr-x 2 root root 4096 2024-03-29 03:06 ./source/l/python-packaging
--rw-r--r-- 1 root root 99084 2024-03-10 09:39 ./source/l/python-packaging/packaging-24.0.tar.lz
+drwxr-xr-x 2 root root 4096 2024-06-10 17:31 ./source/l/python-packaging
+-rw-r--r-- 1 root root 99790 2024-06-09 23:19 ./source/l/python-packaging/packaging-24.1.tar.lz
-rw-r--r-- 1 root root 36 2020-01-25 18:33 ./source/l/python-packaging/packaging.url
--rwxr-xr-x 1 root root 3069 2024-03-29 03:06 ./source/l/python-packaging/python-packaging.SlackBuild
+-rwxr-xr-x 1 root root 3069 2024-06-10 17:32 ./source/l/python-packaging/python-packaging.SlackBuild
-rw-r--r-- 1 root root 829 2018-08-27 18:22 ./source/l/python-packaging/slack-desc
drwxr-xr-x 2 root root 4096 2024-03-29 03:06 ./source/l/python-pathspec
-rw-r--r-- 1 root root 51043 2023-12-10 22:30 ./source/l/python-pathspec/pathspec-0.12.1.tar.gz
@@ -12768,7 +12777,7 @@ drwxr-xr-x 2 root root 4096 2024-05-11 17:24 ./source/n/elm
drwxr-xr-x 2 root root 4096 2024-05-04 00:01 ./source/n/epic5
-rw-r--r-- 1 root root 249636 2005-03-16 01:15 ./source/n/epic5/epic-help-current.tar.xz
-rw-r--r-- 1 root root 891200 2022-06-15 21:33 ./source/n/epic5/epic5-2.1.12.tar.xz
--rwxr-xr-x 1 root root 4286 2024-05-04 00:01 ./source/n/epic5/epic5.SlackBuild
+-rwxr-xr-x 1 root root 4286 2024-06-10 17:58 ./source/n/epic5/epic5.SlackBuild
-rw-r--r-- 1 root root 33 2022-03-28 18:33 ./source/n/epic5/epic5.url
-rw-r--r-- 1 root root 771 2018-02-27 06:13 ./source/n/epic5/slack-desc
drwxr-xr-x 2 root root 4096 2022-08-23 02:53 ./source/n/ethtool
@@ -12893,7 +12902,7 @@ drwxr-xr-x 2 root root 4096 2023-10-03 17:58 ./source/n/irssi
-rw-r--r-- 1 root root 264 2009-07-29 00:34 ./source/n/irssi/doinst.sh.gz
-rw-r--r-- 1 root root 1215688 2023-10-03 07:40 ./source/n/irssi/irssi-1.4.5.tar.xz
-rw-r--r-- 1 root root 195 2023-10-03 07:40 ./source/n/irssi/irssi-1.4.5.tar.xz.asc
--rwxr-xr-x 1 root root 4796 2023-10-21 18:48 ./source/n/irssi/irssi.SlackBuild
+-rwxr-xr-x 1 root root 4796 2024-06-10 18:07 ./source/n/irssi/irssi.SlackBuild
-rw-r--r-- 1 root root 784 2018-02-27 06:13 ./source/n/irssi/slack-desc
drwxr-xr-x 2 root root 4096 2024-05-19 18:49 ./source/n/iw
-rw-r--r-- 1 root root 566 2024-05-17 09:21 ./source/n/iw/iw-6.9.tar.sign
@@ -13075,7 +13084,7 @@ drwxr-xr-x 2 root root 4096 2024-05-04 00:01 ./source/n/net-snmp
-rw-r--r-- 1 root root 1205 2018-07-20 09:39 ./source/n/net-snmp/net-snmp-5.8-modern-rpm-api.patch.gz
-rw-r--r-- 1 root root 876 2018-07-20 09:39 ./source/n/net-snmp/net-snmp-5.8-multilib.patch.gz
-rw-r--r-- 1 root root 3893917 2023-08-15 20:45 ./source/n/net-snmp/net-snmp-5.9.4.tar.lz
--rwxr-xr-x 1 root root 6854 2024-05-04 00:01 ./source/n/net-snmp/net-snmp.SlackBuild
+-rwxr-xr-x 1 root root 6854 2024-06-10 18:07 ./source/n/net-snmp/net-snmp.SlackBuild
-rw-r--r-- 1 root root 43 2018-11-09 20:13 ./source/n/net-snmp/net-snmp.url
-rw-r--r-- 1 root root 981 2021-12-21 18:35 ./source/n/net-snmp/rc.snmpd
-rw-r--r-- 1 root root 907 2018-02-27 06:13 ./source/n/net-snmp/slack-desc
@@ -13314,10 +13323,10 @@ drwxr-xr-x 2 root root 4096 2024-06-01 18:27 ./source/n/ntp
-rw-r--r-- 1 root root 375 2024-06-01 18:27 ./source/n/ntp/doinst.sh.gz
-rw-r--r-- 1 root root 379 2024-06-01 18:26 ./source/n/ntp/ntp
-rw-r--r-- 1 root root 4347475 2024-05-25 07:07 ./source/n/ntp/ntp-4.2.8p18.tar.lz
--rwxr-xr-x 1 root root 6103 2024-06-01 18:30 ./source/n/ntp/ntp.SlackBuild
+-rwxr-xr-x 1 root root 6103 2024-06-10 18:10 ./source/n/ntp/ntp.SlackBuild
-rw-r--r-- 1 root root 2580 2023-06-12 19:06 ./source/n/ntp/ntp.conf
-rw-r--r-- 1 root root 22 1999-10-07 19:50 ./source/n/ntp/ntp.keys
--rw-r--r-- 1 root root 148 2023-06-12 19:06 ./source/n/ntp/ntp.logrotate
+-rw-r--r-- 1 root root 148 2024-06-10 18:10 ./source/n/ntp/ntp.logrotate
-rw-r--r-- 1 root root 31 2023-06-02 18:26 ./source/n/ntp/ntp.url
-rw-r--r-- 1 root root 2483 2018-02-15 11:45 ./source/n/ntp/ntpdate.8.gz
-rw-r--r-- 1 root root 907 2024-06-01 18:32 ./source/n/ntp/rc.ntpd
@@ -13332,7 +13341,7 @@ drwxr-xr-x 2 root root 4096 2017-01-08 20:26 ./source/n/obexftp/patches
drwxr-xr-x 2 root root 4096 2024-05-22 17:54 ./source/n/openldap
-rw-r--r-- 1 root root 484 2020-05-15 06:01 ./source/n/openldap/doinst.sh.gz
-rw-r--r-- 1 root root 4090422 2024-05-21 20:02 ./source/n/openldap/openldap-2.6.8.tar.lz
--rwxr-xr-x 1 root root 8120 2024-05-11 00:30 ./source/n/openldap/openldap.SlackBuild
+-rwxr-xr-x 1 root root 8120 2024-06-10 18:11 ./source/n/openldap/openldap.SlackBuild
-rw-r--r-- 1 root root 53 2020-01-31 18:55 ./source/n/openldap/openldap.url
-rw-r--r-- 1 root root 1526 2020-05-15 04:53 ./source/n/openldap/rc.openldap
-rw-r--r-- 1 root root 934 2020-05-15 00:38 ./source/n/openldap/slack-desc
@@ -13836,19 +13845,19 @@ drwxr-xr-x 2 root root 4096 2024-04-23 17:17 ./source/x/fcitx5-gtk
-rw-r--r-- 1 root root 310 2024-04-23 08:00 ./source/x/fcitx5-gtk/fcitx5-gtk-5.1.3.tar.zst.sig
-rwxr-xr-x 1 root root 3384 2024-04-23 17:17 ./source/x/fcitx5-gtk/fcitx5-gtk.SlackBuild
-rw-r--r-- 1 root root 49 2022-05-19 18:02 ./source/x/fcitx5-gtk/fcitx5-gtk.url
--rw-r--r-- 1 root root 766 2022-05-19 18:04 ./source/x/fcitx5-gtk/slack-desc
+-rw-r--r-- 1 root root 766 2024-06-10 00:43 ./source/x/fcitx5-gtk/slack-desc
drwxr-xr-x 2 root root 4096 2024-06-01 17:10 ./source/x/fcitx5-hangul
-rw-r--r-- 1 root root 49058 2024-05-31 15:05 ./source/x/fcitx5-hangul/fcitx5-hangul-5.1.4.tar.zst
-rw-r--r-- 1 root root 310 2024-05-31 15:05 ./source/x/fcitx5-hangul/fcitx5-hangul-5.1.4.tar.zst.sig
-rwxr-xr-x 1 root root 3357 2024-04-23 17:22 ./source/x/fcitx5-hangul/fcitx5-hangul.SlackBuild
-rw-r--r-- 1 root root 52 2022-05-21 10:16 ./source/x/fcitx5-hangul/fcitx5-hangul.url
--rw-r--r-- 1 root root 756 2022-05-21 10:16 ./source/x/fcitx5-hangul/slack-desc
+-rw-r--r-- 1 root root 757 2024-06-10 00:43 ./source/x/fcitx5-hangul/slack-desc
drwxr-xr-x 2 root root 4096 2024-06-01 17:10 ./source/x/fcitx5-kkc
-rw-r--r-- 1 root root 55708 2024-05-31 15:05 ./source/x/fcitx5-kkc/fcitx5-kkc-5.1.4.tar.zst
-rw-r--r-- 1 root root 310 2024-05-31 15:05 ./source/x/fcitx5-kkc/fcitx5-kkc-5.1.4.tar.zst.sig
-rwxr-xr-x 1 root root 3373 2024-04-23 17:24 ./source/x/fcitx5-kkc/fcitx5-kkc.SlackBuild
-rw-r--r-- 1 root root 49 2022-05-21 10:20 ./source/x/fcitx5-kkc/fcitx5-kkc.url
--rw-r--r-- 1 root root 810 2022-05-21 10:20 ./source/x/fcitx5-kkc/slack-desc
+-rw-r--r-- 1 root root 811 2024-06-10 00:44 ./source/x/fcitx5-kkc/slack-desc
drwxr-xr-x 2 root root 4096 2024-04-23 17:18 ./source/x/fcitx5-m17n
-rw-r--r-- 1 root root 28422 2024-04-23 08:00 ./source/x/fcitx5-m17n/fcitx5-m17n-5.1.1.tar.zst
-rw-r--r-- 1 root root 310 2024-04-23 08:00 ./source/x/fcitx5-m17n/fcitx5-m17n-5.1.1.tar.zst.sig
@@ -13860,38 +13869,38 @@ drwxr-xr-x 2 root root 4096 2024-04-23 17:19 ./source/x/fcitx5-qt
-rw-r--r-- 1 root root 310 2024-04-23 08:00 ./source/x/fcitx5-qt/fcitx5-qt-5.1.6.tar.zst.sig
-rwxr-xr-x 1 root root 3582 2024-06-09 18:37 ./source/x/fcitx5-qt/fcitx5-qt.SlackBuild
-rw-r--r-- 1 root root 48 2022-05-15 15:20 ./source/x/fcitx5-qt/fcitx5-qt.url
--rw-r--r-- 1 root root 716 2022-05-15 15:22 ./source/x/fcitx5-qt/slack-desc
+-rw-r--r-- 1 root root 716 2024-06-10 00:44 ./source/x/fcitx5-qt/slack-desc
drwxr-xr-x 2 root root 4096 2024-04-23 17:20 ./source/x/fcitx5-sayura
-rw-r--r-- 1 root root 25363 2024-04-23 08:00 ./source/x/fcitx5-sayura/fcitx5-sayura-5.1.2.tar.zst
-rw-r--r-- 1 root root 310 2024-04-23 08:00 ./source/x/fcitx5-sayura/fcitx5-sayura-5.1.2.tar.zst.sig
-rwxr-xr-x 1 root root 3357 2024-04-23 17:20 ./source/x/fcitx5-sayura/fcitx5-sayura.SlackBuild
-rw-r--r-- 1 root root 52 2022-05-21 10:24 ./source/x/fcitx5-sayura/fcitx5-sayura.url
--rw-r--r-- 1 root root 786 2022-05-21 10:25 ./source/x/fcitx5-sayura/slack-desc
+-rw-r--r-- 1 root root 787 2024-06-10 00:44 ./source/x/fcitx5-sayura/slack-desc
drwxr-xr-x 2 root root 4096 2024-06-01 17:13 ./source/x/fcitx5-table-extra
-rw-r--r-- 1 root root 13837895 2024-05-31 15:05 ./source/x/fcitx5-table-extra/fcitx5-table-extra-5.1.6.tar.zst
-rw-r--r-- 1 root root 310 2024-05-31 15:05 ./source/x/fcitx5-table-extra/fcitx5-table-extra-5.1.6.tar.zst.sig
-rwxr-xr-x 1 root root 3376 2024-04-23 17:27 ./source/x/fcitx5-table-extra/fcitx5-table-extra.SlackBuild
-rw-r--r-- 1 root root 57 2022-05-21 10:31 ./source/x/fcitx5-table-extra/fcitx5-table-extra.url
--rw-r--r-- 1 root root 909 2022-05-21 10:32 ./source/x/fcitx5-table-extra/slack-desc
+-rw-r--r-- 1 root root 910 2024-06-10 00:44 ./source/x/fcitx5-table-extra/slack-desc
drwxr-xr-x 2 root root 4096 2024-06-01 17:12 ./source/x/fcitx5-table-other
-rw-r--r-- 1 root root 532361 2024-05-31 15:05 ./source/x/fcitx5-table-other/fcitx5-table-other-5.1.3.tar.zst
-rw-r--r-- 1 root root 310 2024-05-31 15:05 ./source/x/fcitx5-table-other/fcitx5-table-other-5.1.3.tar.zst.sig
-rwxr-xr-x 1 root root 3376 2024-04-23 17:26 ./source/x/fcitx5-table-other/fcitx5-table-other.SlackBuild
-rw-r--r-- 1 root root 57 2022-05-21 10:35 ./source/x/fcitx5-table-other/fcitx5-table-other.url
--rw-r--r-- 1 root root 912 2022-05-21 10:36 ./source/x/fcitx5-table-other/slack-desc
+-rw-r--r-- 1 root root 913 2024-06-10 00:45 ./source/x/fcitx5-table-other/slack-desc
drwxr-xr-x 2 root root 4096 2024-04-23 17:21 ./source/x/fcitx5-unikey
-rw-r--r-- 1 root root 114482 2024-04-23 08:00 ./source/x/fcitx5-unikey/fcitx5-unikey-5.1.4.tar.zst
-rw-r--r-- 1 root root 310 2024-04-23 08:00 ./source/x/fcitx5-unikey/fcitx5-unikey-5.1.4.tar.zst.sig
-rwxr-xr-x 1 root root 3377 2024-04-23 17:21 ./source/x/fcitx5-unikey/fcitx5-unikey.SlackBuild
-rw-r--r-- 1 root root 52 2022-05-21 10:28 ./source/x/fcitx5-unikey/fcitx5-unikey.url
--rw-r--r-- 1 root root 799 2022-05-21 10:28 ./source/x/fcitx5-unikey/slack-desc
+-rw-r--r-- 1 root root 800 2024-06-10 00:45 ./source/x/fcitx5-unikey/slack-desc
-rw-r--r-- 1 root root 132 2022-05-15 15:12 ./source/x/fcitx5/doinst.sh.gz
-rw-r--r-- 1 root root 8309913 2024-05-31 15:05 ./source/x/fcitx5/fcitx5-5.1.10_dict.tar.zst
-rw-r--r-- 1 root root 310 2024-05-31 15:05 ./source/x/fcitx5/fcitx5-5.1.10_dict.tar.zst.sig
-rwxr-xr-x 1 root root 554 2022-05-15 15:11 ./source/x/fcitx5/fcitx5-autostart
-rwxr-xr-x 1 root root 3846 2024-04-23 17:10 ./source/x/fcitx5/fcitx5.SlackBuild
-rw-r--r-- 1 root root 45 2022-05-15 14:21 ./source/x/fcitx5/fcitx5.url
--rw-r--r-- 1 root root 1002 2022-05-15 14:21 ./source/x/fcitx5/slack-desc
+-rw-r--r-- 1 root root 1002 2024-06-10 00:45 ./source/x/fcitx5/slack-desc
drwxr-xr-x 3 root root 4096 2021-02-13 05:32 ./source/x/fontconfig
-rw-r--r-- 1 root root 139 2013-02-28 21:07 ./source/x/fontconfig/doinst.sh.gz
drwxr-xr-x 2 root root 4096 2020-05-19 17:42 ./source/x/fontconfig/fedora-patches
@@ -15268,14 +15277,14 @@ drwxr-xr-x 2 root root 4096 2024-04-17 18:00 ./source/x/x11/src/lib
-rw-r--r-- 1 root root 265596 2022-12-04 22:07 ./source/x/x11/src/lib/libXcomposite-0.4.6.tar.xz
-rw-r--r-- 1 root root 289536 2024-03-02 21:01 ./source/x/x11/src/lib/libXcursor-1.2.2.tar.xz
-rw-r--r-- 1 root root 257532 2022-12-04 23:12 ./source/x/x11/src/lib/libXdamage-1.1.6.tar.xz
--rw-r--r-- 1 root root 297596 2024-03-02 21:37 ./source/x/x11/src/lib/libXdmcp-1.1.5.tar.xz
--rw-r--r-- 1 root root 212200 2010-10-31 16:46 ./source/x/x11/src/lib/libXevie-1.0.3.tar.xz
--rw-r--r-- 1 root root 341092 2024-02-04 21:43 ./source/x/x11/src/lib/libXext-1.3.6.tar.xz
--rw-r--r-- 1 root root 265636 2023-04-09 20:32 ./source/x/x11/src/lib/libXfixes-6.0.1.tar.xz
--rw-r--r-- 1 root root 446848 2022-08-26 23:26 ./source/x/x11/src/lib/libXfont2-2.0.6.tar.xz
--rw-r--r-- 1 root root 189140 2009-10-13 20:47 ./source/x/x11/src/lib/libXfontcache-1.0.5.tar.xz
--rw-r--r-- 1 root root 311664 2023-04-17 19:32 ./source/x/x11/src/lib/libXft-2.3.8.tar.xz
--rw-r--r-- 1 root root 404252 2023-05-04 05:10 ./source/x/x11/src/lib/libXi-1.8.1.tar.xz
+-rw-r--r-- 1 root root 297596 2024-03-02 21:37 ./source/x/x11/src/lib/libXdmcp-1.1.5.tar.xz
+-rw-r--r-- 1 root root 212200 2010-10-31 16:46 ./source/x/x11/src/lib/libXevie-1.0.3.tar.xz
+-rw-r--r-- 1 root root 341092 2024-02-04 21:43 ./source/x/x11/src/lib/libXext-1.3.6.tar.xz
+-rw-r--r-- 1 root root 265636 2023-04-09 20:32 ./source/x/x11/src/lib/libXfixes-6.0.1.tar.xz
+-rw-r--r-- 1 root root 446848 2022-08-26 23:26 ./source/x/x11/src/lib/libXfont2-2.0.6.tar.xz
+-rw-r--r-- 1 root root 189140 2009-10-13 20:47 ./source/x/x11/src/lib/libXfontcache-1.0.5.tar.xz
+-rw-r--r-- 1 root root 311664 2023-04-17 19:32 ./source/x/x11/src/lib/libXft-2.3.8.tar.xz
+-rw-r--r-- 1 root root 404252 2023-05-04 05:10 ./source/x/x11/src/lib/libXi-1.8.1.tar.xz
-rw-r--r-- 1 root root 260272 2022-10-29 02:14 ./source/x/x11/src/lib/libXinerama-1.1.5.tar.xz
-rw-r--r-- 1 root root 364888 2024-04-16 20:03 ./source/x/x11/src/lib/libXmu-1.2.1.tar.xz
-rw-r--r-- 1 root root 280924 2022-09-12 20:50 ./source/x/x11/src/lib/libXp-1.0.4.tar.xz
@@ -15525,7 +15534,7 @@ drwxr-xr-x 2 root root 4096 2021-02-13 05:32 ./source/xap/gv
drwxr-xr-x 2 root root 4096 2024-03-29 03:06 ./source/xap/hexchat
-rw-r--r-- 1 root root 172 2014-06-01 17:08 ./source/xap/hexchat/doinst.sh.gz
-rw-r--r-- 1 root root 1352304 2024-02-07 12:18 ./source/xap/hexchat/hexchat-2.16.2.tar.xz
--rwxr-xr-x 1 root root 3783 2024-03-29 03:06 ./source/xap/hexchat/hexchat.SlackBuild
+-rwxr-xr-x 1 root root 3783 2024-06-10 18:11 ./source/xap/hexchat/hexchat.SlackBuild
-rw-r--r-- 1 root root 83 2024-02-07 18:41 ./source/xap/hexchat/hexchat.url
-rw-r--r-- 1 root root 718 2018-02-27 06:13 ./source/xap/hexchat/slack-desc
drwxr-xr-x 2 root root 4096 2023-01-09 19:24 ./source/xap/libnma
@@ -15599,7 +15608,7 @@ drwxr-xr-x 2 root root 4096 2024-02-23 18:42 ./source/xap/pidgin
-rw-r--r-- 1 root root 355 2012-05-02 03:59 ./source/xap/pidgin/fix-gmain_h-compile-error.diff.gz
-rw-r--r-- 1 root root 6113471 2024-02-23 11:40 ./source/xap/pidgin/pidgin-2.14.13.tar.lz
-rw-r--r-- 1 root root 604129 2010-05-18 16:51 ./source/xap/pidgin/pidgin-encryption-3.1.tar.gz
--rwxr-xr-x 1 root root 7660 2024-05-11 18:53 ./source/xap/pidgin/pidgin.SlackBuild
+-rwxr-xr-x 1 root root 7660 2024-06-10 18:14 ./source/xap/pidgin/pidgin.SlackBuild
-rw-r--r-- 1 root root 911 2021-04-30 17:42 ./source/xap/pidgin/slack-desc
drwxr-xr-x 2 root root 4096 2021-02-13 05:32 ./source/xap/rdesktop
-rw-r--r-- 1 root root 282274 2019-10-11 08:22 ./source/xap/rdesktop/rdesktop-1.9.0.tar.lz
@@ -15608,7 +15617,7 @@ drwxr-xr-x 2 root root 4096 2021-02-13 05:32 ./source/xap/rdesktop
drwxr-xr-x 2 root root 4096 2024-02-20 19:03 ./source/xap/rxvt-unicode
-rw-r--r-- 1 root root 222 2018-03-31 17:18 ./source/xap/rxvt-unicode/rxvt-unicode-256color.desktop
-rw-r--r-- 1 root root 715318 2023-01-02 22:42 ./source/xap/rxvt-unicode/rxvt-unicode-9.31.tar.lz
--rwxr-xr-x 1 root root 5547 2024-02-20 19:04 ./source/xap/rxvt-unicode/rxvt-unicode.SlackBuild
+-rwxr-xr-x 1 root root 5547 2024-06-10 18:12 ./source/xap/rxvt-unicode/rxvt-unicode.SlackBuild
-rw-r--r-- 1 root root 207 2018-03-31 17:17 ./source/xap/rxvt-unicode/rxvt-unicode.desktop
-rw-r--r-- 1 root root 229 2023-07-08 18:38 ./source/xap/rxvt-unicode/rxvt-unicode.perl5.38.0.diff.gz
-rw-r--r-- 1 root root 38 2023-07-20 18:32 ./source/xap/rxvt-unicode/rxvt-unicode.url
@@ -15785,18 +15794,17 @@ drwxr-xr-x 2 root root 4096 2023-12-05 20:57 ./source/xap/xsane
-rw-r--r-- 1 root root 12822 2015-03-26 16:54 ./source/xap/xsane/xsane-0.999-snprintf-update.patch.gz
-rw-r--r-- 1 root root 1878344 2013-06-04 15:48 ./source/xap/xsane/xsane-0.999.tar.xz
-rwxr-xr-x 1 root root 5120 2024-05-12 05:15 ./source/xap/xsane/xsane.SlackBuild
-drwxr-xr-x 2 root root 4096 2024-01-28 20:02 ./source/xap/xscreensaver
+drwxr-xr-x 2 root root 4096 2024-06-10 17:43 ./source/xap/xscreensaver
-rw-r--r-- 1 root root 280 2020-02-07 00:37 ./source/xap/xscreensaver/doinst.sh.gz
-rwxr-xr-x 1 root root 616 2017-12-24 07:25 ./source/xap/xscreensaver/dump.android.osx.sources.sh
-rw-r--r-- 1 root root 2868 2008-10-17 04:30 ./source/xap/xscreensaver/setuid.c.gz
-rw-r--r-- 1 root root 923 2018-02-27 06:13 ./source/xap/xscreensaver/slack-desc
--rw-r--r-- 1 root root 9955050 2023-10-11 00:41 ./source/xap/xscreensaver/xscreensaver-6.08.tar.lz
+-rw-r--r-- 1 root root 10714481 2024-06-08 18:28 ./source/xap/xscreensaver/xscreensaver-6.09.tar.lz
-rw-r--r-- 1 root root 16569 2011-01-30 03:18 ./source/xap/xscreensaver/xscreensaver-getimage-file-5.14
--rwxr-xr-x 1 root root 6008 2024-01-28 20:02 ./source/xap/xscreensaver/xscreensaver.SlackBuild
+-rwxr-xr-x 1 root root 5012 2024-06-10 17:43 ./source/xap/xscreensaver/xscreensaver.SlackBuild
-rw-r--r-- 1 root root 285 2022-12-12 19:21 ./source/xap/xscreensaver/xscreensaver.electricsheep.diff.gz
-rw-r--r-- 1 root root 504 2023-09-01 19:01 ./source/xap/xscreensaver/xscreensaver.no.expiration.date.diff.gz
-rw-r--r-- 1 root root 50 2014-07-26 21:13 ./source/xap/xscreensaver/xscreensaver.pam
--rw-r--r-- 1 root root 1763 2008-10-17 04:32 ./source/xap/xscreensaver/xscreensaver.setuid.diff.gz
drwxr-xr-x 2 root root 4096 2024-05-25 17:29 ./source/xap/xsnow
-rw-r--r-- 1 root root 683 2020-12-24 22:16 ./source/xap/xsnow/slack-desc
-rw-r--r-- 1 root root 627930 2024-03-28 10:12 ./source/xap/xsnow/xsnow-3.7.9.tar.lz
@@ -15890,10 +15898,10 @@ drwxr-xr-x 2 root root 4096 2023-06-05 18:35 ./source/xfce/xfce4-panel-pro
-rw-r--r-- 1 root root 1321596 2024-02-29 14:07 ./source/xfce/xfce4-panel/xfce4-panel-4.18.6.tar.lz
-rwxr-xr-x 1 root root 4782 2021-02-25 19:35 ./source/xfce/xfce4-panel/xfce4-panel.SlackBuild
-rw-r--r-- 1 root root 52 2022-12-17 20:44 ./source/xfce/xfce4-panel/xfce4-panel.url
-drwxr-xr-x 2 root root 4096 2023-11-30 21:03 ./source/xfce/xfce4-power-manager
+drwxr-xr-x 2 root root 4096 2024-06-10 17:35 ./source/xfce/xfce4-power-manager
-rw-r--r-- 1 root root 172 2009-05-30 01:47 ./source/xfce/xfce4-power-manager/doinst.sh.gz
-rw-r--r-- 1 root root 880 2020-11-25 21:10 ./source/xfce/xfce4-power-manager/slack-desc
--rw-r--r-- 1 root root 960183 2023-11-30 15:46 ./source/xfce/xfce4-power-manager/xfce4-power-manager-4.18.3.tar.lz
+-rw-r--r-- 1 root root 959810 2024-06-09 15:43 ./source/xfce/xfce4-power-manager/xfce4-power-manager-4.18.4.tar.lz
-rwxr-xr-x 1 root root 4138 2022-12-17 20:46 ./source/xfce/xfce4-power-manager/xfce4-power-manager.SlackBuild
-rw-r--r-- 1 root root 60 2022-12-17 20:45 ./source/xfce/xfce4-power-manager/xfce4-power-manager.url
drwxr-xr-x 2 root root 4096 2023-10-02 18:31 ./source/xfce/xfce4-pulseaudio-plugin
@@ -15916,10 +15924,10 @@ drwxr-xr-x 2 root root 4096 2024-05-29 17:13 ./source/xfce/xfce4-screensho
-rw-r--r-- 1 root root 625245 2024-05-28 21:25 ./source/xfce/xfce4-screenshooter/xfce4-screenshooter-1.10.6.tar.lz
-rwxr-xr-x 1 root root 4395 2022-11-21 20:13 ./source/xfce/xfce4-screenshooter/xfce4-screenshooter.SlackBuild
-rw-r--r-- 1 root root 59 2022-12-21 19:11 ./source/xfce/xfce4-screenshooter/xfce4-screenshooter.url
-drwxr-xr-x 2 root root 4096 2023-05-29 18:09 ./source/xfce/xfce4-session
+drwxr-xr-x 2 root root 4096 2024-06-10 17:37 ./source/xfce/xfce4-session
-rw-r--r-- 1 root root 910 2018-02-27 06:13 ./source/xfce/xfce4-session/slack-desc
-rw-r--r-- 1 root root 338 2020-12-19 05:09 ./source/xfce/xfce4-session/use-xfss-by-default-in-xfce.patch.gz
--rw-r--r-- 1 root root 723900 2023-05-29 15:48 ./source/xfce/xfce4-session/xfce4-session-4.18.3.tar.lz
+-rw-r--r-- 1 root root 761641 2024-06-09 15:40 ./source/xfce/xfce4-session/xfce4-session-4.18.4.tar.lz
-rwxr-xr-x 1 root root 4906 2022-12-17 20:34 ./source/xfce/xfce4-session/xfce4-session.SlackBuild
-rw-r--r-- 1 root root 53 2022-12-17 20:33 ./source/xfce/xfce4-session/xfce4-session.url
drwxr-xr-x 2 root root 4096 2024-06-09 17:07 ./source/xfce/xfce4-settings
diff --git a/recompress.sh b/recompress.sh
index 9b5444ec1..1742fe317 100755
--- a/recompress.sh
+++ b/recompress.sh
@@ -20,6 +20,7 @@ gzip ./extra/source/bash-completion/fixup-sh-script-completions.diff
gzip ./source/d/clisp/clisp.link.libgnu.whole-archive.diff
gzip ./source/d/clisp/clisp.c_data.compact_empty_buckets.diff
gzip ./source/d/autoconf/doinst.sh
+gzip ./source/d/ccache/doctest.h
gzip ./source/d/pmake/pmake_1.111-1.diff
gzip ./source/d/pmake/pmake.txt
gzip ./source/d/pmake/pmake.strerror.strdup.diff
@@ -971,7 +972,6 @@ gzip ./source/xap/audacious/doinst.sh
gzip ./source/xap/xscreensaver/setuid.c
gzip ./source/xap/xscreensaver/xscreensaver.electricsheep.diff
gzip ./source/xap/xscreensaver/doinst.sh
-gzip ./source/xap/xscreensaver/xscreensaver.setuid.diff
gzip ./source/xap/xscreensaver/xscreensaver.no.expiration.date.diff
gzip ./source/xap/gnuchess/eboard.assert.diff
gzip ./source/xap/gnuchess/eboard.png16.diff
diff --git a/slackware64/ap/maketag b/slackware64/ap/maketag
index 6aea26be1..bda10f2e0 100644
--- a/slackware64/ap/maketag
+++ b/slackware64/ap/maketag
@@ -83,6 +83,7 @@ done." 22 72 12 \
"sox" "Sound utilities" "on" \
"sqlite" "A small SQL database server and library" "on" \
"squashfs-tools" "Squashed read-only filesystem for Linux" "on" \
+"stow" "symlink farm manager" "on" \
"sudo" "Allow special users limited root access" "on" \
"sysstat" "System performance monitoring tools" "on" \
"terminus-font" "a clean fixed width font" "on" \
@@ -102,7 +103,7 @@ if [ $? = 1 -o $? = 255 ]; then
rm -f $TMP/SeTpkgs
> $TMP/SeTnewtag
for pkg in \
-a2ps acct alsa-utils amp at bc bpe cdparanoia cdrdao cdrtools cups cups-browsed cups-filters dash dc3dd ddrescue diffstat diffutils dmapi dmidecode dvd+rw-tools enscript flac ghostscript ghostscript-fonts-std gphoto2 groff gutenprint hplip htop inxi ispell itstool jed joe jove ksh93 libx86 linuxdoc-tools lm_sensors lsof lsscsi lxc madplay man-db man-pages mariadb mc moc most mpg123 nano neofetch normalize nvme-cli opus-tools pamixer powertop qpdf radeontool rdfind rpm rzip sc sc-im screen seejpeg slackpkg soma sox sqlite squashfs-tools sudo sysstat terminus-font texinfo tmux undervolt usbmuxd vbetool vim vorbis-tools xfsdump xmltoman xorriso zsh \
+a2ps acct alsa-utils amp at bc bpe cdparanoia cdrdao cdrtools cups cups-browsed cups-filters dash dc3dd ddrescue diffstat diffutils dmapi dmidecode dvd+rw-tools enscript flac ghostscript ghostscript-fonts-std gphoto2 groff gutenprint hplip htop inxi ispell itstool jed joe jove ksh93 libx86 linuxdoc-tools lm_sensors lsof lsscsi lxc madplay man-db man-pages mariadb mc moc most mpg123 nano neofetch normalize nvme-cli opus-tools pamixer powertop qpdf radeontool rdfind rpm rzip sc sc-im screen seejpeg slackpkg soma sox sqlite squashfs-tools stow sudo sysstat terminus-font texinfo tmux undervolt usbmuxd vbetool vim vorbis-tools xfsdump xmltoman xorriso zsh \
; do
echo "$pkg: SKP" >> $TMP/SeTnewtag
done
@@ -110,7 +111,7 @@ a2ps acct alsa-utils amp at bc bpe cdparanoia cdrdao cdrtools cups cups-browsed
fi
cat /dev/null > $TMP/SeTnewtag
for PACKAGE in \
-a2ps acct alsa-utils amp at bc bpe cdparanoia cdrdao cdrtools cups cups-browsed cups-filters dash dc3dd ddrescue diffstat diffutils dmapi dmidecode dvd+rw-tools enscript flac ghostscript ghostscript-fonts-std gphoto2 groff gutenprint hplip htop inxi ispell itstool jed joe jove ksh93 libx86 linuxdoc-tools lm_sensors lsof lsscsi lxc madplay man-db man-pages mariadb mc moc most mpg123 nano neofetch normalize nvme-cli opus-tools pamixer powertop qpdf radeontool rdfind rpm rzip sc sc-im screen seejpeg slackpkg soma sox sqlite squashfs-tools sudo sysstat terminus-font texinfo tmux undervolt usbmuxd vbetool vim vorbis-tools xfsdump xmltoman xorriso zsh \
+a2ps acct alsa-utils amp at bc bpe cdparanoia cdrdao cdrtools cups cups-browsed cups-filters dash dc3dd ddrescue diffstat diffutils dmapi dmidecode dvd+rw-tools enscript flac ghostscript ghostscript-fonts-std gphoto2 groff gutenprint hplip htop inxi ispell itstool jed joe jove ksh93 libx86 linuxdoc-tools lm_sensors lsof lsscsi lxc madplay man-db man-pages mariadb mc moc most mpg123 nano neofetch normalize nvme-cli opus-tools pamixer powertop qpdf radeontool rdfind rpm rzip sc sc-im screen seejpeg slackpkg soma sox sqlite squashfs-tools stow sudo sysstat terminus-font texinfo tmux undervolt usbmuxd vbetool vim vorbis-tools xfsdump xmltoman xorriso zsh \
; do
if grep "\(^\| \)$PACKAGE\( \|$\)" $TMP/SeTpkgs 1> /dev/null 2> /dev/null ; then
echo "$PACKAGE: ADD" >> $TMP/SeTnewtag
diff --git a/slackware64/ap/maketag.ez b/slackware64/ap/maketag.ez
index 6aea26be1..bda10f2e0 100644
--- a/slackware64/ap/maketag.ez
+++ b/slackware64/ap/maketag.ez
@@ -83,6 +83,7 @@ done." 22 72 12 \
"sox" "Sound utilities" "on" \
"sqlite" "A small SQL database server and library" "on" \
"squashfs-tools" "Squashed read-only filesystem for Linux" "on" \
+"stow" "symlink farm manager" "on" \
"sudo" "Allow special users limited root access" "on" \
"sysstat" "System performance monitoring tools" "on" \
"terminus-font" "a clean fixed width font" "on" \
@@ -102,7 +103,7 @@ if [ $? = 1 -o $? = 255 ]; then
rm -f $TMP/SeTpkgs
> $TMP/SeTnewtag
for pkg in \
-a2ps acct alsa-utils amp at bc bpe cdparanoia cdrdao cdrtools cups cups-browsed cups-filters dash dc3dd ddrescue diffstat diffutils dmapi dmidecode dvd+rw-tools enscript flac ghostscript ghostscript-fonts-std gphoto2 groff gutenprint hplip htop inxi ispell itstool jed joe jove ksh93 libx86 linuxdoc-tools lm_sensors lsof lsscsi lxc madplay man-db man-pages mariadb mc moc most mpg123 nano neofetch normalize nvme-cli opus-tools pamixer powertop qpdf radeontool rdfind rpm rzip sc sc-im screen seejpeg slackpkg soma sox sqlite squashfs-tools sudo sysstat terminus-font texinfo tmux undervolt usbmuxd vbetool vim vorbis-tools xfsdump xmltoman xorriso zsh \
+a2ps acct alsa-utils amp at bc bpe cdparanoia cdrdao cdrtools cups cups-browsed cups-filters dash dc3dd ddrescue diffstat diffutils dmapi dmidecode dvd+rw-tools enscript flac ghostscript ghostscript-fonts-std gphoto2 groff gutenprint hplip htop inxi ispell itstool jed joe jove ksh93 libx86 linuxdoc-tools lm_sensors lsof lsscsi lxc madplay man-db man-pages mariadb mc moc most mpg123 nano neofetch normalize nvme-cli opus-tools pamixer powertop qpdf radeontool rdfind rpm rzip sc sc-im screen seejpeg slackpkg soma sox sqlite squashfs-tools stow sudo sysstat terminus-font texinfo tmux undervolt usbmuxd vbetool vim vorbis-tools xfsdump xmltoman xorriso zsh \
; do
echo "$pkg: SKP" >> $TMP/SeTnewtag
done
@@ -110,7 +111,7 @@ a2ps acct alsa-utils amp at bc bpe cdparanoia cdrdao cdrtools cups cups-browsed
fi
cat /dev/null > $TMP/SeTnewtag
for PACKAGE in \
-a2ps acct alsa-utils amp at bc bpe cdparanoia cdrdao cdrtools cups cups-browsed cups-filters dash dc3dd ddrescue diffstat diffutils dmapi dmidecode dvd+rw-tools enscript flac ghostscript ghostscript-fonts-std gphoto2 groff gutenprint hplip htop inxi ispell itstool jed joe jove ksh93 libx86 linuxdoc-tools lm_sensors lsof lsscsi lxc madplay man-db man-pages mariadb mc moc most mpg123 nano neofetch normalize nvme-cli opus-tools pamixer powertop qpdf radeontool rdfind rpm rzip sc sc-im screen seejpeg slackpkg soma sox sqlite squashfs-tools sudo sysstat terminus-font texinfo tmux undervolt usbmuxd vbetool vim vorbis-tools xfsdump xmltoman xorriso zsh \
+a2ps acct alsa-utils amp at bc bpe cdparanoia cdrdao cdrtools cups cups-browsed cups-filters dash dc3dd ddrescue diffstat diffutils dmapi dmidecode dvd+rw-tools enscript flac ghostscript ghostscript-fonts-std gphoto2 groff gutenprint hplip htop inxi ispell itstool jed joe jove ksh93 libx86 linuxdoc-tools lm_sensors lsof lsscsi lxc madplay man-db man-pages mariadb mc moc most mpg123 nano neofetch normalize nvme-cli opus-tools pamixer powertop qpdf radeontool rdfind rpm rzip sc sc-im screen seejpeg slackpkg soma sox sqlite squashfs-tools stow sudo sysstat terminus-font texinfo tmux undervolt usbmuxd vbetool vim vorbis-tools xfsdump xmltoman xorriso zsh \
; do
if grep "\(^\| \)$PACKAGE\( \|$\)" $TMP/SeTpkgs 1> /dev/null 2> /dev/null ; then
echo "$PACKAGE: ADD" >> $TMP/SeTnewtag
diff --git a/slackware64/ap/tagfile b/slackware64/ap/tagfile
index e0329165e..ba651eb24 100644
--- a/slackware64/ap/tagfile
+++ b/slackware64/ap/tagfile
@@ -70,6 +70,7 @@ soma:REC
sox:REC
sqlite:OPT
squashfs-tools:REC
+stow:REC
sudo:OPT
sysstat:OPT
terminus-font:REC
diff --git a/slackware64/kde/maketag b/slackware64/kde/maketag
index 0f7fe262e..6d5eeaed2 100644
--- a/slackware64/kde/maketag
+++ b/slackware64/kde/maketag
@@ -57,7 +57,7 @@ to install. Press ENTER when you are done." \
"eventviews" "library for creating events" "on" \
"extra-cmake-modules" "extra KDE CMake modules" "on" \
"falkon" "KDE web browser" "on" \
-"fcitx5-configtool" "Plasma config module for Fcitx5" "on" \
+"fcitx5-configtool" "Plasma config module for fcitx5" "on" \
"fcitx5-theme-breeze" "Fcitx5 breeze theme" "on" \
"ffmpegthumbs" "video thumbnail generator using ffmpeg" "on" \
"filelight" "file system monitor" "on" \
diff --git a/slackware64/kde/maketag.ez b/slackware64/kde/maketag.ez
index 0f7fe262e..6d5eeaed2 100644
--- a/slackware64/kde/maketag.ez
+++ b/slackware64/kde/maketag.ez
@@ -57,7 +57,7 @@ to install. Press ENTER when you are done." \
"eventviews" "library for creating events" "on" \
"extra-cmake-modules" "extra KDE CMake modules" "on" \
"falkon" "KDE web browser" "on" \
-"fcitx5-configtool" "Plasma config module for Fcitx5" "on" \
+"fcitx5-configtool" "Plasma config module for fcitx5" "on" \
"fcitx5-theme-breeze" "Fcitx5 breeze theme" "on" \
"ffmpegthumbs" "video thumbnail generator using ffmpeg" "on" \
"filelight" "file system monitor" "on" \
diff --git a/slackware64/x/maketag b/slackware64/x/maketag
index 555deff5d..8176b3a15 100644
--- a/slackware64/x/maketag
+++ b/slackware64/x/maketag
@@ -27,11 +27,11 @@ Press ENTER when you are done." \
"fcitx5" "Input Method Framework" "on" \
"fcitx5-anthy" "Anthy wrapper for fcitx5" "on" \
"fcitx5-chinese-addons" "Chinese related addon for fcitx5" "on" \
-"fcitx5-gtk" "Gtk IM Module for Fcitx5" "on" \
+"fcitx5-gtk" "Gtk IM Module for fcitx5" "on" \
"fcitx5-hangul" "Hangul wrapper for fcitx5" "on" \
-"fcitx5-kkc" "Japanese Kana Kanji Engine for Fcitx5" "on" \
+"fcitx5-kkc" "Japanese Kana Kanji Engine for fcitx5" "on" \
"fcitx5-m17n" "m17n input method engine wrapper for fcitx5" "on" \
-"fcitx5-qt" "Qt IM Module for Fcitx5" "on" \
+"fcitx5-qt" "Qt IM Module for fcitx5" "on" \
"fcitx5-sayura" "Sinhala input method for fcitx5" "on" \
"fcitx5-table-extra" "Extra tables for fcitx5" "on" \
"fcitx5-table-other" "Other tables for fcitx5" "on" \
diff --git a/slackware64/x/maketag.ez b/slackware64/x/maketag.ez
index 555deff5d..8176b3a15 100644
--- a/slackware64/x/maketag.ez
+++ b/slackware64/x/maketag.ez
@@ -27,11 +27,11 @@ Press ENTER when you are done." \
"fcitx5" "Input Method Framework" "on" \
"fcitx5-anthy" "Anthy wrapper for fcitx5" "on" \
"fcitx5-chinese-addons" "Chinese related addon for fcitx5" "on" \
-"fcitx5-gtk" "Gtk IM Module for Fcitx5" "on" \
+"fcitx5-gtk" "Gtk IM Module for fcitx5" "on" \
"fcitx5-hangul" "Hangul wrapper for fcitx5" "on" \
-"fcitx5-kkc" "Japanese Kana Kanji Engine for Fcitx5" "on" \
+"fcitx5-kkc" "Japanese Kana Kanji Engine for fcitx5" "on" \
"fcitx5-m17n" "m17n input method engine wrapper for fcitx5" "on" \
-"fcitx5-qt" "Qt IM Module for Fcitx5" "on" \
+"fcitx5-qt" "Qt IM Module for fcitx5" "on" \
"fcitx5-sayura" "Sinhala input method for fcitx5" "on" \
"fcitx5-table-extra" "Extra tables for fcitx5" "on" \
"fcitx5-table-other" "Other tables for fcitx5" "on" \
diff --git a/source/ap/stow/slack-desc b/source/ap/stow/slack-desc
new file mode 100644
index 000000000..9c2a9f33d
--- /dev/null
+++ b/source/ap/stow/slack-desc
@@ -0,0 +1,19 @@
+# HOW TO EDIT THIS FILE:
+# The "handy ruler" below makes it easier to edit a package description. Line
+# up the first '|' above the ':' following the base package name, and the '|'
+# on the right side marks the last column you can put a character in. You must
+# make exactly 11 lines for the formatting to be correct. It's also
+# customary to leave one space after the ':'.
+
+ |-----handy-ruler------------------------------------------------------|
+stow: stow (symlink farm manager)
+stow:
+stow: GNU Stow is a symlink farm manager which takes distinct sets of
+stow: software and/or data located in separate directories on the
+stow: filesystem, and makes them all appear to be installed in a single
+stow: directory tree. Stow helps to administer, upgrade, install, and remove
+stow: files in independent software packages without confusing them with
+stow: other files sharing the same file system space.
+stow:
+stow: Homepage: https://www.gnu.org/software/stow/
+stow:
diff --git a/source/ap/stow/stow.SlackBuild b/source/ap/stow/stow.SlackBuild
new file mode 100755
index 000000000..f82f49d93
--- /dev/null
+++ b/source/ap/stow/stow.SlackBuild
@@ -0,0 +1,154 @@
+#!/bin/bash
+
+# Copyright 2024 Patrick J. Volkerding, Sebeka, Minnesota, USA
+# All rights reserved.
+#
+# Redistribution and use of this script, with or without modification, is
+# permitted provided that the following conditions are met:
+#
+# 1. Redistributions of this script must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+
+cd $(dirname $0) ; CWD=$(pwd)
+
+PKGNAM=stow
+VERSION=${VERSION:-$(echo $PKGNAM-*.tar.?z | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
+BUILD=${BUILD:-1}
+
+# Automatically determine the architecture we're building on:
+if [ -z "$ARCH" ]; then
+ case "$(uname -m)" in
+ i?86) ARCH=i586 ;;
+ arm*) readelf /usr/bin/file -A | egrep -q "Tag_CPU.*[4,5]" && ARCH=arm || ARCH=armv7hl ;;
+ # Unless $ARCH is already set, use uname -m for all other archs:
+ *) ARCH=$(uname -m) ;;
+ esac
+ export ARCH
+fi
+
+# If the variable PRINT_PACKAGE_NAME is set, then this script will report what
+# the name of the created package would be, and then exit. This information
+# could be useful to other scripts.
+if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
+ echo "$PKGNAM-$VERSION-$ARCH-$BUILD.txz"
+ exit 0
+fi
+
+NUMJOBS=${NUMJOBS:-" -j $(expr $(nproc) + 1) "}
+
+if [ "$ARCH" = "i586" ]; then
+ SLKCFLAGS="-O2 -march=i586 -mtune=i686"
+ LIBDIRSUFFIX=""
+elif [ "$ARCH" = "i686" ]; then
+ SLKCFLAGS="-O2 -march=i686"
+ LIBDIRSUFFIX=""
+elif [ "$ARCH" = "s390" ]; then
+ SLKCFLAGS="-O2"
+ LIBDIRSUFFIX=""
+elif [ "$ARCH" = "x86_64" ]; then
+ SLKCFLAGS="-O2 -fPIC"
+ LIBDIRSUFFIX="64"
+elif [ "$ARCH" = "armv7hl" ]; then
+ SLKCFLAGS="-O3 -march=armv7-a -mfpu=vfpv3-d16"
+ LIBDIRSUFFIX=""
+else
+ SLKCFLAGS="-O2"
+ LIBDIRSUFFIX=""
+fi
+
+TMP=${TMP:-/tmp}
+PKG=$TMP/package-$PKGNAM
+
+rm -rf $PKG
+mkdir -p $TMP $PKG
+
+cd $TMP
+rm -rf $PKGNAM-$VERSION
+tar xvf $CWD/$PKGNAM-$VERSION.tar.?z || exit 1
+cd $PKGNAM-$VERSION || exit 1
+
+chown -R root:root .
+find . \
+ \( -perm 777 -o -perm 775 -o -perm 711 -o -perm 555 -o -perm 511 \) \
+ -exec chmod 755 {} \+ -o \
+ \( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \
+ -exec chmod 644 {} \+
+
+# Configure, build, and install:
+if [ ! -r configure ]; then
+ if [ -x ./autogen.sh ]; then
+ NOCONFIGURE=1 ./autogen.sh
+ else
+ autoreconf -vif
+ fi
+fi
+CFLAGS="$SLKCFLAGS" \
+CXXFLAGS="$SLKCFLAGS" \
+./configure \
+ --prefix=/usr \
+ --libdir=/usr/lib${LIBDIRSUFFIX} \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --docdir=/usr/doc/$PKGNAM-$VERSION \
+ --mandir=/usr/man \
+ --infodir=/usr/info \
+ --disable-static \
+ --build=$ARCH-slackware-linux || exit 1
+make $NUMJOBS || make || exit 1
+make install DESTDIR=$PKG || exit 1
+
+# Don't ship .la files:
+rm -f $PKG/{,usr/}lib${LIBDIRSUFFIX}/*.la
+
+# Strip binaries:
+find $PKG | xargs file | grep -e "executable" -e "shared object" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
+
+# Compress manual pages:
+find $PKG/usr/man -type f -exec gzip -9 {} \+
+for i in $( find $PKG/usr/man -type l ) ; do
+ ln -s $( readlink $i ).gz $i.gz
+ rm $i
+done
+
+# Compress info files, if any:
+if [ -d $PKG/usr/info ]; then
+ ( cd $PKG/usr/info
+ rm -f dir
+ gzip -9 *
+ )
+fi
+
+# We'll take care of this, thanks
+rm -rf $PKG/usr/doc
+
+# Add a documentation directory:
+mkdir -p $PKG/usr/doc/${PKGNAM}-$VERSION
+cp -a \
+ ChangeLog INSTALL* README* \
+ doc/manual-split \
+ $PKG/usr/doc/${PKGNAM}-$VERSION
+
+# If there's a ChangeLog, installing at least part of the recent history
+# is useful, but don't let it get totally out of control:
+if [ -r ChangeLog ]; then
+ DOCSDIR=$(echo $PKG/usr/doc/${PKGNAM}-$VERSION)
+ cat ChangeLog | head -n 1000 > $DOCSDIR/ChangeLog
+ touch -r ChangeLog $DOCSDIR/ChangeLog
+fi
+
+mkdir -p $PKG/install
+cat $CWD/slack-desc > $PKG/install/slack-desc
+
+cd $PKG
+/sbin/makepkg -l y -c n $TMP/$PKGNAM-$VERSION-$ARCH-$BUILD.txz
diff --git a/source/ap/texinfo/texinfo.SlackBuild b/source/ap/texinfo/texinfo.SlackBuild
index cba119234..8cfa29cdb 100755
--- a/source/ap/texinfo/texinfo.SlackBuild
+++ b/source/ap/texinfo/texinfo.SlackBuild
@@ -24,7 +24,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=texinfo
VERSION=${VERSION:-$(echo $PKGNAM-*.tar.xz | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
-BUILD=${BUILD:-1}
+BUILD=${BUILD:-2}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
diff --git a/source/d/ccache/ccache.SlackBuild b/source/d/ccache/ccache.SlackBuild
index 1c4406bd6..b8f4dd5af 100755
--- a/source/d/ccache/ccache.SlackBuild
+++ b/source/d/ccache/ccache.SlackBuild
@@ -1,6 +1,6 @@
#!/bin/bash
-# Copyright 2008, 2009, 2010, 2011, 2017, 2018, 2020 Patrick J. Volkerding, Sebeka, MN, USA
+# Copyright 2008, 2009, 2010, 2011, 2017, 2018, 2020, 2024 Patrick J. Volkerding, Sebeka, MN, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
@@ -24,7 +24,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=ccache
VERSION=${VERSION:-$(echo $PKGNAM-*.tar.xz | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
-BUILD=${BUILD:-1}
+BUILD=${BUILD:-2}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
@@ -63,10 +63,15 @@ find . \
\( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \
-exec chmod 644 {} \+
+# Add doctest include file to avoid downloading it, and then use unshare -n
+# below to make sure that doesn't happen.
+mkdir doctest
+zcat $CWD/doctest.h.gz > doctest/doctest.h
+
# Configure, build, and install:
mkdir cmake-build
cd cmake-build
- cmake \
+ unshare -n cmake \
-DCMAKE_C_FLAGS="$SLKCFLAGS" \
-DCMAKE_CXX_FLAGS="$SLKCFLAGS" \
-DCMAKE_INSTALL_PREFIX=/usr \
@@ -74,6 +79,7 @@ cd cmake-build
-DDOC_INSTALL_DIR="doc" \
-DCMAKE_INSTALL_MANDIR=/usr/man \
-DREDIS_STORAGE_BACKEND=OFF \
+ -DDOCTEST_INCLUDE_DIR=$TMP/ccache-$VERSION \
.. || exit 1
make $NUMJOBS || make || exit 1
make install DESTDIR=$PKG || exit 1
diff --git a/source/d/ccache/doctest.h b/source/d/ccache/doctest.h
new file mode 100644
index 000000000..5c754cde0
--- /dev/null
+++ b/source/d/ccache/doctest.h
@@ -0,0 +1,7106 @@
+// ====================================================================== lgtm [cpp/missing-header-guard]
+// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! ==
+// ======================================================================
+//
+// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD
+//
+// Copyright (c) 2016-2023 Viktor Kirilov
+//
+// Distributed under the MIT Software License
+// See accompanying file LICENSE.txt or copy at
+// https://opensource.org/licenses/MIT
+//
+// The documentation can be found at the library's page:
+// https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md
+//
+// =================================================================================================
+// =================================================================================================
+// =================================================================================================
+//
+// The library is heavily influenced by Catch - https://github.com/catchorg/Catch2
+// which uses the Boost Software License - Version 1.0
+// see here - https://github.com/catchorg/Catch2/blob/master/LICENSE.txt
+//
+// The concept of subcases (sections in Catch) and expression decomposition are from there.
+// Some parts of the code are taken directly:
+// - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<>
+// - the Approx() helper class for floating point comparison
+// - colors in the console
+// - breaking into a debugger
+// - signal / SEH handling
+// - timer
+// - XmlWriter class - thanks to Phil Nash for allowing the direct reuse (AKA copy/paste)
+//
+// The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest
+// which uses the Boost Software License - Version 1.0
+// see here - https://github.com/martinmoene/lest/blob/master/LICENSE.txt
+//
+// =================================================================================================
+// =================================================================================================
+// =================================================================================================
+
+#ifndef DOCTEST_LIBRARY_INCLUDED
+#define DOCTEST_LIBRARY_INCLUDED
+
+// =================================================================================================
+// == VERSION ======================================================================================
+// =================================================================================================
+
+#define DOCTEST_VERSION_MAJOR 2
+#define DOCTEST_VERSION_MINOR 4
+#define DOCTEST_VERSION_PATCH 11
+
+// util we need here
+#define DOCTEST_TOSTR_IMPL(x) #x
+#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x)
+
+#define DOCTEST_VERSION_STR \
+ DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \
+ DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \
+ DOCTEST_TOSTR(DOCTEST_VERSION_PATCH)
+
+#define DOCTEST_VERSION \
+ (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
+
+// =================================================================================================
+// == COMPILER VERSION =============================================================================
+// =================================================================================================
+
+// ideas for the version stuff are taken from here: https://github.com/cxxstuff/cxx_detect
+
+#ifdef _MSC_VER
+#define DOCTEST_CPLUSPLUS _MSVC_LANG
+#else
+#define DOCTEST_CPLUSPLUS __cplusplus
+#endif
+
+#define DOCTEST_COMPILER(MAJOR, MINOR, PATCH) ((MAJOR)*10000000 + (MINOR)*100000 + (PATCH))
+
+// GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because of clang-cl...
+#if defined(_MSC_VER) && defined(_MSC_FULL_VER)
+#if _MSC_VER == _MSC_FULL_VER / 10000
+#define DOCTEST_MSVC DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000)
+#else // MSVC
+#define DOCTEST_MSVC \
+ DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000)
+#endif // MSVC
+#endif // MSVC
+#if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
+#define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \
+ !defined(__INTEL_COMPILER)
+#define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#endif // GCC
+#if defined(__INTEL_COMPILER)
+#define DOCTEST_ICC DOCTEST_COMPILER(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
+#endif // ICC
+
+#ifndef DOCTEST_MSVC
+#define DOCTEST_MSVC 0
+#endif // DOCTEST_MSVC
+#ifndef DOCTEST_CLANG
+#define DOCTEST_CLANG 0
+#endif // DOCTEST_CLANG
+#ifndef DOCTEST_GCC
+#define DOCTEST_GCC 0
+#endif // DOCTEST_GCC
+#ifndef DOCTEST_ICC
+#define DOCTEST_ICC 0
+#endif // DOCTEST_ICC
+
+// =================================================================================================
+// == COMPILER WARNINGS HELPERS ====================================================================
+// =================================================================================================
+
+#if DOCTEST_CLANG && !DOCTEST_ICC
+#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
+#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push")
+#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w)
+#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop")
+#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w)
+#else // DOCTEST_CLANG
+#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+#define DOCTEST_CLANG_SUPPRESS_WARNING(w)
+#define DOCTEST_CLANG_SUPPRESS_WARNING_POP
+#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w)
+#endif // DOCTEST_CLANG
+
+#if DOCTEST_GCC
+#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
+#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push")
+#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w)
+#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop")
+#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \
+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w)
+#else // DOCTEST_GCC
+#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+#define DOCTEST_GCC_SUPPRESS_WARNING(w)
+#define DOCTEST_GCC_SUPPRESS_WARNING_POP
+#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w)
+#endif // DOCTEST_GCC
+
+#if DOCTEST_MSVC
+#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push))
+#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w))
+#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop))
+#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w)
+#else // DOCTEST_MSVC
+#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+#define DOCTEST_MSVC_SUPPRESS_WARNING(w)
+#define DOCTEST_MSVC_SUPPRESS_WARNING_POP
+#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w)
+#endif // DOCTEST_MSVC
+
+// =================================================================================================
+// == COMPILER WARNINGS ============================================================================
+// =================================================================================================
+
+// both the header and the implementation suppress all of these,
+// so it only makes sense to aggregate them like so
+#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \
+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \
+ \
+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \
+ \
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
+ /* these 4 also disabled globally via cmake: */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \
+ /* common ones */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \
+ /* static analysis */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */
+
+#define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP \
+ DOCTEST_GCC_SUPPRESS_WARNING_POP \
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH
+
+DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated")
+
+DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo")
+
+DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted
+
+#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */
+
+#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+// =================================================================================================
+// == FEATURE DETECTION ============================================================================
+// =================================================================================================
+
+// general compiler feature support table: https://en.cppreference.com/w/cpp/compiler_support
+// MSVC C++11 feature support table: https://msdn.microsoft.com/en-us/library/hh567368.aspx
+// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html
+// MSVC version table:
+// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
+// MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022)
+// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019)
+// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017)
+// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
+// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
+// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
+// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
+// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
+// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
+
+// Universal Windows Platform support
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+#define DOCTEST_CONFIG_NO_WINDOWS_SEH
+#endif // WINAPI_FAMILY
+#if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
+#define DOCTEST_CONFIG_WINDOWS_SEH
+#endif // MSVC
+#if defined(DOCTEST_CONFIG_NO_WINDOWS_SEH) && defined(DOCTEST_CONFIG_WINDOWS_SEH)
+#undef DOCTEST_CONFIG_WINDOWS_SEH
+#endif // DOCTEST_CONFIG_NO_WINDOWS_SEH
+
+#if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \
+ !defined(__EMSCRIPTEN__) && !defined(__wasi__)
+#define DOCTEST_CONFIG_POSIX_SIGNALS
+#endif // _WIN32
+#if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS)
+#undef DOCTEST_CONFIG_POSIX_SIGNALS
+#endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) \
+ || defined(__wasi__)
+#define DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // no exceptions
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+#define DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+
+#if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS)
+#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+
+#ifdef __wasi__
+#define DOCTEST_CONFIG_NO_MULTITHREADING
+#endif
+
+#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_CONFIG_IMPLEMENT)
+#define DOCTEST_CONFIG_IMPLEMENT
+#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#if DOCTEST_MSVC
+#define DOCTEST_SYMBOL_EXPORT __declspec(dllexport)
+#define DOCTEST_SYMBOL_IMPORT __declspec(dllimport)
+#else // MSVC
+#define DOCTEST_SYMBOL_EXPORT __attribute__((dllexport))
+#define DOCTEST_SYMBOL_IMPORT __attribute__((dllimport))
+#endif // MSVC
+#else // _WIN32
+#define DOCTEST_SYMBOL_EXPORT __attribute__((visibility("default")))
+#define DOCTEST_SYMBOL_IMPORT
+#endif // _WIN32
+
+#ifdef DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+#ifdef DOCTEST_CONFIG_IMPLEMENT
+#define DOCTEST_INTERFACE DOCTEST_SYMBOL_EXPORT
+#else // DOCTEST_CONFIG_IMPLEMENT
+#define DOCTEST_INTERFACE DOCTEST_SYMBOL_IMPORT
+#endif // DOCTEST_CONFIG_IMPLEMENT
+#else // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+#define DOCTEST_INTERFACE
+#endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+
+// needed for extern template instantiations
+// see https://github.com/fmtlib/fmt/issues/2228
+#if DOCTEST_MSVC
+#define DOCTEST_INTERFACE_DECL
+#define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE
+#else // DOCTEST_MSVC
+#define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE
+#define DOCTEST_INTERFACE_DEF
+#endif // DOCTEST_MSVC
+
+#define DOCTEST_EMPTY
+
+#if DOCTEST_MSVC
+#define DOCTEST_NOINLINE __declspec(noinline)
+#define DOCTEST_UNUSED
+#define DOCTEST_ALIGNMENT(x)
+#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0)
+#define DOCTEST_NOINLINE
+#define DOCTEST_UNUSED
+#define DOCTEST_ALIGNMENT(x)
+#else
+#define DOCTEST_NOINLINE __attribute__((noinline))
+#define DOCTEST_UNUSED __attribute__((unused))
+#define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x)))
+#endif
+
+#ifdef DOCTEST_CONFIG_NO_CONTRADICTING_INLINE
+#define DOCTEST_INLINE_NOINLINE inline
+#else
+#define DOCTEST_INLINE_NOINLINE inline DOCTEST_NOINLINE
+#endif
+
+#ifndef DOCTEST_NORETURN
+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_NORETURN
+#else // DOCTEST_MSVC
+#define DOCTEST_NORETURN [[noreturn]]
+#endif // DOCTEST_MSVC
+#endif // DOCTEST_NORETURN
+
+#ifndef DOCTEST_NOEXCEPT
+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_NOEXCEPT
+#else // DOCTEST_MSVC
+#define DOCTEST_NOEXCEPT noexcept
+#endif // DOCTEST_MSVC
+#endif // DOCTEST_NOEXCEPT
+
+#ifndef DOCTEST_CONSTEXPR
+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_CONSTEXPR const
+#define DOCTEST_CONSTEXPR_FUNC inline
+#else // DOCTEST_MSVC
+#define DOCTEST_CONSTEXPR constexpr
+#define DOCTEST_CONSTEXPR_FUNC constexpr
+#endif // DOCTEST_MSVC
+#endif // DOCTEST_CONSTEXPR
+
+#ifndef DOCTEST_NO_SANITIZE_INTEGER
+#if DOCTEST_CLANG >= DOCTEST_COMPILER(3, 7, 0)
+#define DOCTEST_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer")))
+#else
+#define DOCTEST_NO_SANITIZE_INTEGER
+#endif
+#endif // DOCTEST_NO_SANITIZE_INTEGER
+
+// =================================================================================================
+// == FEATURE DETECTION END ========================================================================
+// =================================================================================================
+
+#define DOCTEST_DECLARE_INTERFACE(name) \
+ virtual ~name(); \
+ name() = default; \
+ name(const name&) = delete; \
+ name(name&&) = delete; \
+ name& operator=(const name&) = delete; \
+ name& operator=(name&&) = delete;
+
+#define DOCTEST_DEFINE_INTERFACE(name) \
+ name::~name() = default;
+
+// internal macros for string concatenation and anonymous variable name generation
+#define DOCTEST_CAT_IMPL(s1, s2) s1##s2
+#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2)
+#ifdef __COUNTER__ // not standard and may be missing for some compilers
+#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__)
+#else // __COUNTER__
+#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__)
+#endif // __COUNTER__
+
+#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+#define DOCTEST_REF_WRAP(x) x&
+#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+#define DOCTEST_REF_WRAP(x) x
+#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+
+// not using __APPLE__ because... this is how Catch does it
+#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
+#define DOCTEST_PLATFORM_MAC
+#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
+#define DOCTEST_PLATFORM_IPHONE
+#elif defined(_WIN32)
+#define DOCTEST_PLATFORM_WINDOWS
+#elif defined(__wasi__)
+#define DOCTEST_PLATFORM_WASI
+#else // DOCTEST_PLATFORM
+#define DOCTEST_PLATFORM_LINUX
+#endif // DOCTEST_PLATFORM
+
+namespace doctest { namespace detail {
+ static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; }
+}}
+
+#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \
+ static const int var = doctest::detail::consume(&var, __VA_ARGS__); \
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+
+#ifndef DOCTEST_BREAK_INTO_DEBUGGER
+// should probably take a look at https://github.com/scottt/debugbreak
+#ifdef DOCTEST_PLATFORM_LINUX
+#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
+// Break at the location of the failing check if possible
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler)
+#else
+#include <signal.h>
+#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP)
+#endif
+#elif defined(DOCTEST_PLATFORM_MAC)
+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386)
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler)
+#elif defined(__ppc__) || defined(__ppc64__)
+// https://www.cocoawithlove.com/2008/03/break-into-debugger.html
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n": : : "memory","r0","r3","r4") // NOLINT(hicpp-no-assembler)
+#else
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT(hicpp-no-assembler)
+#endif
+#elif DOCTEST_MSVC
+#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
+#elif defined(__MINGW32__)
+DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls")
+extern "C" __declspec(dllimport) void __stdcall DebugBreak();
+DOCTEST_GCC_SUPPRESS_WARNING_POP
+#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
+#else // linux
+#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast<void>(0))
+#endif // linux
+#endif // DOCTEST_BREAK_INTO_DEBUGGER
+
+// this is kept here for backwards compatibility since the config option was changed
+#ifdef DOCTEST_CONFIG_USE_IOSFWD
+#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
+#define DOCTEST_CONFIG_USE_STD_HEADERS
+#endif
+#endif // DOCTEST_CONFIG_USE_IOSFWD
+
+// for clang - always include ciso646 (which drags some std stuff) because
+// we want to check if we are using libc++ with the _LIBCPP_VERSION macro in
+// which case we don't want to forward declare stuff from std - for reference:
+// https://github.com/doctest/doctest/issues/126
+// https://github.com/doctest/doctest/issues/356
+#if DOCTEST_CLANG
+#include <ciso646>
+#endif // clang
+
+#ifdef _LIBCPP_VERSION
+#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
+#define DOCTEST_CONFIG_USE_STD_HEADERS
+#endif
+#endif // _LIBCPP_VERSION
+
+#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
+#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
+#include <cstddef>
+#include <ostream>
+#include <istream>
+DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
+#else // DOCTEST_CONFIG_USE_STD_HEADERS
+
+// Forward declaring 'X' in namespace std is not permitted by the C++ Standard.
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643)
+
+namespace std { // NOLINT(cert-dcl58-cpp)
+typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using)
+typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using)
+template <class charT>
+struct char_traits;
+template <>
+struct char_traits<char>;
+template <class charT, class traits>
+class basic_ostream; // NOLINT(fuchsia-virtual-inheritance)
+typedef basic_ostream<char, char_traits<char>> ostream; // NOLINT(modernize-use-using)
+template<class traits>
+// NOLINTNEXTLINE
+basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char*);
+template <class charT, class traits>
+class basic_istream;
+typedef basic_istream<char, char_traits<char>> istream; // NOLINT(modernize-use-using)
+template <class... Types>
+class tuple;
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
+template <class Ty>
+class allocator;
+template <class Elem, class Traits, class Alloc>
+class basic_string;
+using string = basic_string<char, char_traits<char>, allocator<char>>;
+#endif // VS 2019
+} // namespace std
+
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+#endif // DOCTEST_CONFIG_USE_STD_HEADERS
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#include <type_traits>
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+namespace doctest {
+
+using std::size_t;
+
+DOCTEST_INTERFACE extern bool is_running_in_test;
+
+#ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE
+#define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned
+#endif
+
+// A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length
+// of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for:
+// - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128)
+// - if small - capacity left before going on the heap - using the lowest 5 bits
+// - if small - 2 bits are left unused - the second and third highest ones
+// - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator)
+// and the "is small" bit remains "0" ("as well as the capacity left") so its OK
+// Idea taken from this lecture about the string implementation of facebook/folly - fbstring
+// https://www.youtube.com/watch?v=kPR8h4-qZdk
+// TODO:
+// - optimizations - like not deleting memory unnecessarily in operator= and etc.
+// - resize/reserve/clear
+// - replace
+// - back/front
+// - iterator stuff
+// - find & friends
+// - push_back/pop_back
+// - assign/insert/erase
+// - relational operators as free functions - taking const char* as one of the params
+class DOCTEST_INTERFACE String
+{
+public:
+ using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE;
+
+private:
+ static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members
+ static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members
+
+ struct view // len should be more than sizeof(view) - because of the final byte for flags
+ {
+ char* ptr;
+ size_type size;
+ size_type capacity;
+ };
+
+ union
+ {
+ char buf[len]; // NOLINT(*-avoid-c-arrays)
+ view data;
+ };
+
+ char* allocate(size_type sz);
+
+ bool isOnStack() const noexcept { return (buf[last] & 128) == 0; }
+ void setOnHeap() noexcept;
+ void setLast(size_type in = last) noexcept;
+ void setSize(size_type sz) noexcept;
+
+ void copy(const String& other);
+
+public:
+ static DOCTEST_CONSTEXPR size_type npos = static_cast<size_type>(-1);
+
+ String() noexcept;
+ ~String();
+
+ // cppcheck-suppress noExplicitConstructor
+ String(const char* in);
+ String(const char* in, size_type in_size);
+
+ String(std::istream& in, size_type in_size);
+
+ String(const String& other);
+ String& operator=(const String& other);
+
+ String& operator+=(const String& other);
+
+ String(String&& other) noexcept;
+ String& operator=(String&& other) noexcept;
+
+ char operator[](size_type i) const;
+ char& operator[](size_type i);
+
+ // the only functions I'm willing to leave in the interface - available for inlining
+ const char* c_str() const { return const_cast<String*>(this)->c_str(); } // NOLINT
+ char* c_str() {
+ if (isOnStack()) {
+ return reinterpret_cast<char*>(buf);
+ }
+ return data.ptr;
+ }
+
+ size_type size() const;
+ size_type capacity() const;
+
+ String substr(size_type pos, size_type cnt = npos) &&;
+ String substr(size_type pos, size_type cnt = npos) const &;
+
+ size_type find(char ch, size_type pos = 0) const;
+ size_type rfind(char ch, size_type pos = npos) const;
+
+ int compare(const char* other, bool no_case = false) const;
+ int compare(const String& other, bool no_case = false) const;
+
+friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in);
+};
+
+DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs);
+
+DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs);
+DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs);
+DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs);
+DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs);
+DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs);
+DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs);
+
+class DOCTEST_INTERFACE Contains {
+public:
+ explicit Contains(const String& string);
+
+ bool checkWith(const String& other) const;
+
+ String string;
+};
+
+DOCTEST_INTERFACE String toString(const Contains& in);
+
+DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs);
+DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs);
+DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs);
+DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs);
+
+namespace Color {
+ enum Enum
+ {
+ None = 0,
+ White,
+ Red,
+ Green,
+ Blue,
+ Cyan,
+ Yellow,
+ Grey,
+
+ Bright = 0x10,
+
+ BrightRed = Bright | Red,
+ BrightGreen = Bright | Green,
+ LightGrey = Bright | Grey,
+ BrightWhite = Bright | White
+ };
+
+ DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code);
+} // namespace Color
+
+namespace assertType {
+ enum Enum
+ {
+ // macro traits
+
+ is_warn = 1,
+ is_check = 2 * is_warn,
+ is_require = 2 * is_check,
+
+ is_normal = 2 * is_require,
+ is_throws = 2 * is_normal,
+ is_throws_as = 2 * is_throws,
+ is_throws_with = 2 * is_throws_as,
+ is_nothrow = 2 * is_throws_with,
+
+ is_false = 2 * is_nothrow,
+ is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types
+
+ is_eq = 2 * is_unary,
+ is_ne = 2 * is_eq,
+
+ is_lt = 2 * is_ne,
+ is_gt = 2 * is_lt,
+
+ is_ge = 2 * is_gt,
+ is_le = 2 * is_ge,
+
+ // macro types
+
+ DT_WARN = is_normal | is_warn,
+ DT_CHECK = is_normal | is_check,
+ DT_REQUIRE = is_normal | is_require,
+
+ DT_WARN_FALSE = is_normal | is_false | is_warn,
+ DT_CHECK_FALSE = is_normal | is_false | is_check,
+ DT_REQUIRE_FALSE = is_normal | is_false | is_require,
+
+ DT_WARN_THROWS = is_throws | is_warn,
+ DT_CHECK_THROWS = is_throws | is_check,
+ DT_REQUIRE_THROWS = is_throws | is_require,
+
+ DT_WARN_THROWS_AS = is_throws_as | is_warn,
+ DT_CHECK_THROWS_AS = is_throws_as | is_check,
+ DT_REQUIRE_THROWS_AS = is_throws_as | is_require,
+
+ DT_WARN_THROWS_WITH = is_throws_with | is_warn,
+ DT_CHECK_THROWS_WITH = is_throws_with | is_check,
+ DT_REQUIRE_THROWS_WITH = is_throws_with | is_require,
+
+ DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn,
+ DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check,
+ DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require,
+
+ DT_WARN_NOTHROW = is_nothrow | is_warn,
+ DT_CHECK_NOTHROW = is_nothrow | is_check,
+ DT_REQUIRE_NOTHROW = is_nothrow | is_require,
+
+ DT_WARN_EQ = is_normal | is_eq | is_warn,
+ DT_CHECK_EQ = is_normal | is_eq | is_check,
+ DT_REQUIRE_EQ = is_normal | is_eq | is_require,
+
+ DT_WARN_NE = is_normal | is_ne | is_warn,
+ DT_CHECK_NE = is_normal | is_ne | is_check,
+ DT_REQUIRE_NE = is_normal | is_ne | is_require,
+
+ DT_WARN_GT = is_normal | is_gt | is_warn,
+ DT_CHECK_GT = is_normal | is_gt | is_check,
+ DT_REQUIRE_GT = is_normal | is_gt | is_require,
+
+ DT_WARN_LT = is_normal | is_lt | is_warn,
+ DT_CHECK_LT = is_normal | is_lt | is_check,
+ DT_REQUIRE_LT = is_normal | is_lt | is_require,
+
+ DT_WARN_GE = is_normal | is_ge | is_warn,
+ DT_CHECK_GE = is_normal | is_ge | is_check,
+ DT_REQUIRE_GE = is_normal | is_ge | is_require,
+
+ DT_WARN_LE = is_normal | is_le | is_warn,
+ DT_CHECK_LE = is_normal | is_le | is_check,
+ DT_REQUIRE_LE = is_normal | is_le | is_require,
+
+ DT_WARN_UNARY = is_normal | is_unary | is_warn,
+ DT_CHECK_UNARY = is_normal | is_unary | is_check,
+ DT_REQUIRE_UNARY = is_normal | is_unary | is_require,
+
+ DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn,
+ DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check,
+ DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require,
+ };
+} // namespace assertType
+
+DOCTEST_INTERFACE const char* assertString(assertType::Enum at);
+DOCTEST_INTERFACE const char* failureString(assertType::Enum at);
+DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file);
+
+struct DOCTEST_INTERFACE TestCaseData
+{
+ String m_file; // the file in which the test was registered (using String - see #350)
+ unsigned m_line; // the line where the test was registered
+ const char* m_name; // name of the test case
+ const char* m_test_suite; // the test suite in which the test was added
+ const char* m_description;
+ bool m_skip;
+ bool m_no_breaks;
+ bool m_no_output;
+ bool m_may_fail;
+ bool m_should_fail;
+ int m_expected_failures;
+ double m_timeout;
+};
+
+struct DOCTEST_INTERFACE AssertData
+{
+ // common - for all asserts
+ const TestCaseData* m_test_case;
+ assertType::Enum m_at;
+ const char* m_file;
+ int m_line;
+ const char* m_expr;
+ bool m_failed;
+
+ // exception-related - for all asserts
+ bool m_threw;
+ String m_exception;
+
+ // for normal asserts
+ String m_decomp;
+
+ // for specific exception-related asserts
+ bool m_threw_as;
+ const char* m_exception_type;
+
+ class DOCTEST_INTERFACE StringContains {
+ private:
+ Contains content;
+ bool isContains;
+
+ public:
+ StringContains(const String& str) : content(str), isContains(false) { }
+ StringContains(Contains cntn) : content(static_cast<Contains&&>(cntn)), isContains(true) { }
+
+ bool check(const String& str) { return isContains ? (content == str) : (content.string == str); }
+
+ operator const String&() const { return content.string; }
+
+ const char* c_str() const { return content.string.c_str(); }
+ } m_exception_string;
+
+ AssertData(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const StringContains& exception_string);
+};
+
+struct DOCTEST_INTERFACE MessageData
+{
+ String m_string;
+ const char* m_file;
+ int m_line;
+ assertType::Enum m_severity;
+};
+
+struct DOCTEST_INTERFACE SubcaseSignature
+{
+ String m_name;
+ const char* m_file;
+ int m_line;
+
+ bool operator==(const SubcaseSignature& other) const;
+ bool operator<(const SubcaseSignature& other) const;
+};
+
+struct DOCTEST_INTERFACE IContextScope
+{
+ DOCTEST_DECLARE_INTERFACE(IContextScope)
+ virtual void stringify(std::ostream*) const = 0;
+};
+
+namespace detail {
+ struct DOCTEST_INTERFACE TestCase;
+} // namespace detail
+
+struct ContextOptions //!OCLINT too many fields
+{
+ std::ostream* cout = nullptr; // stdout stream
+ String binary_name; // the test binary name
+
+ const detail::TestCase* currentTest = nullptr;
+
+ // == parameters from the command line
+ String out; // output filename
+ String order_by; // how tests should be ordered
+ unsigned rand_seed; // the seed for rand ordering
+
+ unsigned first; // the first (matching) test to be executed
+ unsigned last; // the last (matching) test to be executed
+
+ int abort_after; // stop tests after this many failed assertions
+ int subcase_filter_levels; // apply the subcase filters for the first N levels
+
+ bool success; // include successful assertions in output
+ bool case_sensitive; // if filtering should be case sensitive
+ bool exit; // if the program should be exited after the tests are ran/whatever
+ bool duration; // print the time duration of each test case
+ bool minimal; // minimal console output (only test failures)
+ bool quiet; // no console output
+ bool no_throw; // to skip exceptions-related assertion macros
+ bool no_exitcode; // if the framework should return 0 as the exitcode
+ bool no_run; // to not run the tests at all (can be done with an "*" exclude)
+ bool no_intro; // to not print the intro of the framework
+ bool no_version; // to not print the version of the framework
+ bool no_colors; // if output to the console should be colorized
+ bool force_colors; // forces the use of colors even when a tty cannot be detected
+ bool no_breaks; // to not break into the debugger
+ bool no_skip; // don't skip test cases which are marked to be skipped
+ bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x):
+ bool no_path_in_filenames; // if the path to files should be removed from the output
+ bool no_line_numbers; // if source code line numbers should be omitted from the output
+ bool no_debug_output; // no output in the debug console when a debugger is attached
+ bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!!
+ bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!!
+
+ bool help; // to print the help
+ bool version; // to print the version
+ bool count; // if only the count of matching tests is to be retrieved
+ bool list_test_cases; // to list all tests matching the filters
+ bool list_test_suites; // to list all suites matching the filters
+ bool list_reporters; // lists all registered reporters
+};
+
+namespace detail {
+ namespace types {
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ using namespace std;
+#else
+ template <bool COND, typename T = void>
+ struct enable_if { };
+
+ template <typename T>
+ struct enable_if<true, T> { using type = T; };
+
+ struct true_type { static DOCTEST_CONSTEXPR bool value = true; };
+ struct false_type { static DOCTEST_CONSTEXPR bool value = false; };
+
+ template <typename T> struct remove_reference { using type = T; };
+ template <typename T> struct remove_reference<T&> { using type = T; };
+ template <typename T> struct remove_reference<T&&> { using type = T; };
+
+ template <typename T> struct is_rvalue_reference : false_type { };
+ template <typename T> struct is_rvalue_reference<T&&> : true_type { };
+
+ template<typename T> struct remove_const { using type = T; };
+ template <typename T> struct remove_const<const T> { using type = T; };
+
+ // Compiler intrinsics
+ template <typename T> struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); };
+ template <typename T> struct underlying_type { using type = __underlying_type(T); };
+
+ template <typename T> struct is_pointer : false_type { };
+ template <typename T> struct is_pointer<T*> : true_type { };
+
+ template <typename T> struct is_array : false_type { };
+ // NOLINTNEXTLINE(*-avoid-c-arrays)
+ template <typename T, size_t SIZE> struct is_array<T[SIZE]> : true_type { };
+#endif
+ }
+
+ // <utility>
+ template <typename T>
+ T&& declval();
+
+ template <class T>
+ DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference<T>::type& t) DOCTEST_NOEXCEPT {
+ return static_cast<T&&>(t);
+ }
+
+ template <class T>
+ DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference<T>::type&& t) DOCTEST_NOEXCEPT {
+ return static_cast<T&&>(t);
+ }
+
+ template <typename T>
+ struct deferred_false : types::false_type { };
+
+// MSVS 2015 :(
+#if !DOCTEST_CLANG && defined(_MSC_VER) && _MSC_VER <= 1900
+ template <typename T, typename = void>
+ struct has_global_insertion_operator : types::false_type { };
+
+ template <typename T>
+ struct has_global_insertion_operator<T, decltype(::operator<<(declval<std::ostream&>(), declval<const T&>()), void())> : types::true_type { };
+
+ template <typename T, typename = void>
+ struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator<T>::value; };
+
+ template <typename T, bool global>
+ struct insert_hack;
+
+ template <typename T>
+ struct insert_hack<T, true> {
+ static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); }
+ };
+
+ template <typename T>
+ struct insert_hack<T, false> {
+ static void insert(std::ostream& os, const T& t) { operator<<(os, t); }
+ };
+
+ template <typename T>
+ using insert_hack_t = insert_hack<T, has_global_insertion_operator<T>::value>;
+#else
+ template <typename T, typename = void>
+ struct has_insertion_operator : types::false_type { };
+#endif
+
+ template <typename T>
+ struct has_insertion_operator<T, decltype(operator<<(declval<std::ostream&>(), declval<const T&>()), void())> : types::true_type { };
+
+ template <typename T>
+ struct should_stringify_as_underlying_type {
+ static DOCTEST_CONSTEXPR bool value = detail::types::is_enum<T>::value && !doctest::detail::has_insertion_operator<T>::value;
+ };
+
+ DOCTEST_INTERFACE std::ostream* tlssPush();
+ DOCTEST_INTERFACE String tlssPop();
+
+ template <bool C>
+ struct StringMakerBase {
+ template <typename T>
+ static String convert(const DOCTEST_REF_WRAP(T)) {
+#ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES
+ static_assert(deferred_false<T>::value, "No stringification detected for type T. See string conversion manual");
+#endif
+ return "{?}";
+ }
+ };
+
+ template <typename T>
+ struct filldata;
+
+ template <typename T>
+ void filloss(std::ostream* stream, const T& in) {
+ filldata<T>::fill(stream, in);
+ }
+
+ template <typename T, size_t N>
+ void filloss(std::ostream* stream, const T (&in)[N]) { // NOLINT(*-avoid-c-arrays)
+ // T[N], T(&)[N], T(&&)[N] have same behaviour.
+ // Hence remove reference.
+ filloss<typename types::remove_reference<decltype(in)>::type>(stream, in);
+ }
+
+ template <typename T>
+ String toStream(const T& in) {
+ std::ostream* stream = tlssPush();
+ filloss(stream, in);
+ return tlssPop();
+ }
+
+ template <>
+ struct StringMakerBase<true> {
+ template <typename T>
+ static String convert(const DOCTEST_REF_WRAP(T) in) {
+ return toStream(in);
+ }
+ };
+} // namespace detail
+
+template <typename T>
+struct StringMaker : public detail::StringMakerBase<
+ detail::has_insertion_operator<T>::value || detail::types::is_pointer<T>::value || detail::types::is_array<T>::value>
+{};
+
+#ifndef DOCTEST_STRINGIFY
+#ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY
+#define DOCTEST_STRINGIFY(...) toString(toString(__VA_ARGS__))
+#else
+#define DOCTEST_STRINGIFY(...) toString(__VA_ARGS__)
+#endif
+#endif
+
+template <typename T>
+String toString() {
+#if DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 && DOCTEST_ICC == 0
+ String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString<TYPE>(void)
+ String::size_type beginPos = ret.find('<');
+ return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast<String::size_type>(sizeof(">(void)")));
+#else
+ String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE]
+ String::size_type begin = ret.find('=') + 2;
+ return ret.substr(begin, ret.size() - begin - 1);
+#endif
+}
+
+template <typename T, typename detail::types::enable_if<!detail::should_stringify_as_underlying_type<T>::value, bool>::type = true>
+String toString(const DOCTEST_REF_WRAP(T) value) {
+ return StringMaker<T>::convert(value);
+}
+
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+DOCTEST_INTERFACE String toString(const char* in);
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
+DOCTEST_INTERFACE String toString(const std::string& in);
+#endif // VS 2019
+
+DOCTEST_INTERFACE String toString(String in);
+
+DOCTEST_INTERFACE String toString(std::nullptr_t);
+
+DOCTEST_INTERFACE String toString(bool in);
+
+DOCTEST_INTERFACE String toString(float in);
+DOCTEST_INTERFACE String toString(double in);
+DOCTEST_INTERFACE String toString(double long in);
+
+DOCTEST_INTERFACE String toString(char in);
+DOCTEST_INTERFACE String toString(char signed in);
+DOCTEST_INTERFACE String toString(char unsigned in);
+DOCTEST_INTERFACE String toString(short in);
+DOCTEST_INTERFACE String toString(short unsigned in);
+DOCTEST_INTERFACE String toString(signed in);
+DOCTEST_INTERFACE String toString(unsigned in);
+DOCTEST_INTERFACE String toString(long in);
+DOCTEST_INTERFACE String toString(long unsigned in);
+DOCTEST_INTERFACE String toString(long long in);
+DOCTEST_INTERFACE String toString(long long unsigned in);
+
+template <typename T, typename detail::types::enable_if<detail::should_stringify_as_underlying_type<T>::value, bool>::type = true>
+String toString(const DOCTEST_REF_WRAP(T) value) {
+ using UT = typename detail::types::underlying_type<T>::type;
+ return (DOCTEST_STRINGIFY(static_cast<UT>(value)));
+}
+
+namespace detail {
+ template <typename T>
+ struct filldata
+ {
+ static void fill(std::ostream* stream, const T& in) {
+#if defined(_MSC_VER) && _MSC_VER <= 1900
+ insert_hack_t<T>::insert(*stream, in);
+#else
+ operator<<(*stream, in);
+#endif
+ }
+ };
+
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866)
+// NOLINTBEGIN(*-avoid-c-arrays)
+ template <typename T, size_t N>
+ struct filldata<T[N]> {
+ static void fill(std::ostream* stream, const T(&in)[N]) {
+ *stream << "[";
+ for (size_t i = 0; i < N; i++) {
+ if (i != 0) { *stream << ", "; }
+ *stream << (DOCTEST_STRINGIFY(in[i]));
+ }
+ *stream << "]";
+ }
+ };
+// NOLINTEND(*-avoid-c-arrays)
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ // Specialized since we don't want the terminating null byte!
+// NOLINTBEGIN(*-avoid-c-arrays)
+ template <size_t N>
+ struct filldata<const char[N]> {
+ static void fill(std::ostream* stream, const char (&in)[N]) {
+ *stream << String(in, in[N - 1] ? N : N - 1);
+ } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
+ };
+// NOLINTEND(*-avoid-c-arrays)
+
+ template <>
+ struct filldata<const void*> {
+ static void fill(std::ostream* stream, const void* in);
+ };
+
+ template <typename T>
+ struct filldata<T*> {
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180)
+ static void fill(std::ostream* stream, const T* in) {
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast")
+ filldata<const void*>::fill(stream,
+#if DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0)
+ reinterpret_cast<const void*>(in)
+#else
+ *reinterpret_cast<const void* const*>(&in)
+#endif
+ );
+DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ }
+ };
+}
+
+struct DOCTEST_INTERFACE Approx
+{
+ Approx(double value);
+
+ Approx operator()(double value) const;
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template <typename T>
+ explicit Approx(const T& value,
+ typename detail::types::enable_if<std::is_constructible<double, T>::value>::type* =
+ static_cast<T*>(nullptr)) {
+ *this = static_cast<double>(value);
+ }
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ Approx& epsilon(double newEpsilon);
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template <typename T>
+ typename std::enable_if<std::is_constructible<double, T>::value, Approx&>::type epsilon(
+ const T& newEpsilon) {
+ m_epsilon = static_cast<double>(newEpsilon);
+ return *this;
+ }
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ Approx& scale(double newScale);
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template <typename T>
+ typename std::enable_if<std::is_constructible<double, T>::value, Approx&>::type scale(
+ const T& newScale) {
+ m_scale = static_cast<double>(newScale);
+ return *this;
+ }
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ // clang-format off
+ DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx & rhs);
+ DOCTEST_INTERFACE friend bool operator==(const Approx & lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx & rhs);
+ DOCTEST_INTERFACE friend bool operator!=(const Approx & lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx & rhs);
+ DOCTEST_INTERFACE friend bool operator<=(const Approx & lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx & rhs);
+ DOCTEST_INTERFACE friend bool operator>=(const Approx & lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator< (double lhs, const Approx & rhs);
+ DOCTEST_INTERFACE friend bool operator< (const Approx & lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx & rhs);
+ DOCTEST_INTERFACE friend bool operator> (const Approx & lhs, double rhs);
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#define DOCTEST_APPROX_PREFIX \
+ template <typename T> friend typename std::enable_if<std::is_constructible<double, T>::value, bool>::type
+
+ DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(static_cast<double>(lhs), rhs); }
+ DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); }
+ DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); }
+ DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); }
+ DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) < rhs.m_value || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast<double>(rhs) || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) > rhs.m_value || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast<double>(rhs) || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) < rhs.m_value && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast<double>(rhs) && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) > rhs.m_value && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast<double>(rhs) && lhs != rhs; }
+#undef DOCTEST_APPROX_PREFIX
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ // clang-format on
+
+ double m_epsilon;
+ double m_scale;
+ double m_value;
+};
+
+DOCTEST_INTERFACE String toString(const Approx& in);
+
+DOCTEST_INTERFACE const ContextOptions* getContextOptions();
+
+template <typename F>
+struct DOCTEST_INTERFACE_DECL IsNaN
+{
+ F value; bool flipped;
+ IsNaN(F f, bool flip = false) : value(f), flipped(flip) { }
+ IsNaN<F> operator!() const { return { value, !flipped }; }
+ operator bool() const;
+};
+#ifndef __MINGW32__
+extern template struct DOCTEST_INTERFACE_DECL IsNaN<float>;
+extern template struct DOCTEST_INTERFACE_DECL IsNaN<double>;
+extern template struct DOCTEST_INTERFACE_DECL IsNaN<long double>;
+#endif
+DOCTEST_INTERFACE String toString(IsNaN<float> in);
+DOCTEST_INTERFACE String toString(IsNaN<double> in);
+DOCTEST_INTERFACE String toString(IsNaN<double long> in);
+
+#ifndef DOCTEST_CONFIG_DISABLE
+
+namespace detail {
+ // clang-format off
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ template<class T> struct decay_array { using type = T; };
+ template<class T, unsigned N> struct decay_array<T[N]> { using type = T*; };
+ template<class T> struct decay_array<T[]> { using type = T*; };
+
+ template<class T> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 1; };
+ template<> struct not_char_pointer<char*> { static DOCTEST_CONSTEXPR int value = 0; };
+ template<> struct not_char_pointer<const char*> { static DOCTEST_CONSTEXPR int value = 0; };
+
+ template<class T> struct can_use_op : public not_char_pointer<typename decay_array<T>::type> {};
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ // clang-format on
+
+ struct DOCTEST_INTERFACE TestFailureException
+ {
+ };
+
+ DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at);
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ DOCTEST_NORETURN
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ DOCTEST_INTERFACE void throwException();
+
+ struct DOCTEST_INTERFACE Subcase
+ {
+ SubcaseSignature m_signature;
+ bool m_entered = false;
+
+ Subcase(const String& name, const char* file, int line);
+ Subcase(const Subcase&) = delete;
+ Subcase(Subcase&&) = delete;
+ Subcase& operator=(const Subcase&) = delete;
+ Subcase& operator=(Subcase&&) = delete;
+ ~Subcase();
+
+ operator bool() const;
+
+ private:
+ bool checkFilters();
+ };
+
+ template <typename L, typename R>
+ String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs));
+ }
+
+#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
+DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
+#endif
+
+// This will check if there is any way it could find a operator like member or friend and uses it.
+// If not it doesn't find the operator or if the operator at global scope is defined after
+// this template, the template won't be instantiated due to SFINAE. Once the template is not
+// instantiated it can look for global operator using normal conversions.
+#ifdef __NVCC__
+#define SFINAE_OP(ret,op) ret
+#else
+#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval<L>() op doctest::detail::declval<R>()),ret{})
+#endif
+
+#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \
+ template <typename R> \
+ DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \
+ bool res = op_macro(doctest::detail::forward<const L>(lhs), doctest::detail::forward<R>(rhs)); \
+ if(m_at & assertType::is_false) \
+ res = !res; \
+ if(!res || doctest::getContextOptions()->success) \
+ return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \
+ return Result(res); \
+ }
+
+ // more checks could be added - like in Catch:
+ // https://github.com/catchorg/Catch2/pull/1480/files
+ // https://github.com/catchorg/Catch2/pull/1481/files
+#define DOCTEST_FORBIT_EXPRESSION(rt, op) \
+ template <typename R> \
+ rt& operator op(const R&) { \
+ static_assert(deferred_false<R>::value, \
+ "Expression Too Complex Please Rewrite As Binary Comparison!"); \
+ return *this; \
+ }
+
+ struct DOCTEST_INTERFACE Result // NOLINT(*-member-init)
+ {
+ bool m_passed;
+ String m_decomp;
+
+ Result() = default; // TODO: Why do we need this? (To remove NOLINT)
+ Result(bool passed, const String& decomposition = String());
+
+ // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
+ DOCTEST_FORBIT_EXPRESSION(Result, &)
+ DOCTEST_FORBIT_EXPRESSION(Result, ^)
+ DOCTEST_FORBIT_EXPRESSION(Result, |)
+ DOCTEST_FORBIT_EXPRESSION(Result, &&)
+ DOCTEST_FORBIT_EXPRESSION(Result, ||)
+ DOCTEST_FORBIT_EXPRESSION(Result, ==)
+ DOCTEST_FORBIT_EXPRESSION(Result, !=)
+ DOCTEST_FORBIT_EXPRESSION(Result, <)
+ DOCTEST_FORBIT_EXPRESSION(Result, >)
+ DOCTEST_FORBIT_EXPRESSION(Result, <=)
+ DOCTEST_FORBIT_EXPRESSION(Result, >=)
+ DOCTEST_FORBIT_EXPRESSION(Result, =)
+ DOCTEST_FORBIT_EXPRESSION(Result, +=)
+ DOCTEST_FORBIT_EXPRESSION(Result, -=)
+ DOCTEST_FORBIT_EXPRESSION(Result, *=)
+ DOCTEST_FORBIT_EXPRESSION(Result, /=)
+ DOCTEST_FORBIT_EXPRESSION(Result, %=)
+ DOCTEST_FORBIT_EXPRESSION(Result, <<=)
+ DOCTEST_FORBIT_EXPRESSION(Result, >>=)
+ DOCTEST_FORBIT_EXPRESSION(Result, &=)
+ DOCTEST_FORBIT_EXPRESSION(Result, ^=)
+ DOCTEST_FORBIT_EXPRESSION(Result, |=)
+ };
+
+#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion")
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare")
+ //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion")
+ //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion")
+ //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal")
+
+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion")
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare")
+ //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion")
+ //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion")
+ //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+ // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389
+ DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch
+ DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch
+ DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch
+ //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation
+
+#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ // clang-format off
+#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_COMPARISON_RETURN_TYPE bool
+#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_COMPARISON_RETURN_TYPE typename types::enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type
+ inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); }
+ inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); }
+ inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); }
+ inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); }
+ inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); }
+ inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); }
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ // clang-format on
+
+#define DOCTEST_RELATIONAL_OP(name, op) \
+ template <typename L, typename R> \
+ DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \
+ const DOCTEST_REF_WRAP(R) rhs) { \
+ return lhs op rhs; \
+ }
+
+ DOCTEST_RELATIONAL_OP(eq, ==)
+ DOCTEST_RELATIONAL_OP(ne, !=)
+ DOCTEST_RELATIONAL_OP(lt, <)
+ DOCTEST_RELATIONAL_OP(gt, >)
+ DOCTEST_RELATIONAL_OP(le, <=)
+ DOCTEST_RELATIONAL_OP(ge, >=)
+
+#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_CMP_EQ(l, r) l == r
+#define DOCTEST_CMP_NE(l, r) l != r
+#define DOCTEST_CMP_GT(l, r) l > r
+#define DOCTEST_CMP_LT(l, r) l < r
+#define DOCTEST_CMP_GE(l, r) l >= r
+#define DOCTEST_CMP_LE(l, r) l <= r
+#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_CMP_EQ(l, r) eq(l, r)
+#define DOCTEST_CMP_NE(l, r) ne(l, r)
+#define DOCTEST_CMP_GT(l, r) gt(l, r)
+#define DOCTEST_CMP_LT(l, r) lt(l, r)
+#define DOCTEST_CMP_GE(l, r) ge(l, r)
+#define DOCTEST_CMP_LE(l, r) le(l, r)
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+
+ template <typename L>
+ // cppcheck-suppress copyCtorAndEqOperator
+ struct Expression_lhs
+ {
+ L lhs;
+ assertType::Enum m_at;
+
+ explicit Expression_lhs(L&& in, assertType::Enum at)
+ : lhs(static_cast<L&&>(in))
+ , m_at(at) {}
+
+ DOCTEST_NOINLINE operator Result() {
+// this is needed only for MSVC 2015
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool
+ bool res = static_cast<bool>(lhs);
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+ if(m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional
+ res = !res;
+ }
+
+ if(!res || getContextOptions()->success) {
+ return { res, (DOCTEST_STRINGIFY(lhs)) };
+ }
+ return { res };
+ }
+
+ /* This is required for user-defined conversions from Expression_lhs to L */
+ operator L() const { return lhs; }
+
+ // clang-format off
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>, " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<, " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
+ // clang-format on
+
+ // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=)
+ // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the
+ // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression...
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>)
+ };
+
+#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
+
+#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
+DOCTEST_CLANG_SUPPRESS_WARNING_POP
+#endif
+
+ struct DOCTEST_INTERFACE ExpressionDecomposer
+ {
+ assertType::Enum m_at;
+
+ ExpressionDecomposer(assertType::Enum at);
+
+ // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table)
+ // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now...
+ // https://github.com/catchorg/Catch2/issues/870
+ // https://github.com/catchorg/Catch2/issues/565
+ template <typename L>
+ Expression_lhs<L> operator<<(L&& operand) {
+ return Expression_lhs<L>(static_cast<L&&>(operand), m_at);
+ }
+
+ template <typename L,typename types::enable_if<!doctest::detail::types::is_rvalue_reference<L>::value,void >::type* = nullptr>
+ Expression_lhs<const L&> operator<<(const L &operand) {
+ return Expression_lhs<const L&>(operand, m_at);
+ }
+ };
+
+ struct DOCTEST_INTERFACE TestSuite
+ {
+ const char* m_test_suite = nullptr;
+ const char* m_description = nullptr;
+ bool m_skip = false;
+ bool m_no_breaks = false;
+ bool m_no_output = false;
+ bool m_may_fail = false;
+ bool m_should_fail = false;
+ int m_expected_failures = 0;
+ double m_timeout = 0;
+
+ TestSuite& operator*(const char* in);
+
+ template <typename T>
+ TestSuite& operator*(const T& in) {
+ in.fill(*this);
+ return *this;
+ }
+ };
+
+ using funcType = void (*)();
+
+ struct DOCTEST_INTERFACE TestCase : public TestCaseData
+ {
+ funcType m_test; // a function pointer to the test case
+
+ String m_type; // for templated test cases - gets appended to the real name
+ int m_template_id; // an ID used to distinguish between the different versions of a templated test case
+ String m_full_name; // contains the name (only for templated test cases!) + the template type
+
+ TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
+ const String& type = String(), int template_id = -1);
+
+ TestCase(const TestCase& other);
+ TestCase(TestCase&&) = delete;
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
+ TestCase& operator=(const TestCase& other);
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ TestCase& operator=(TestCase&&) = delete;
+
+ TestCase& operator*(const char* in);
+
+ template <typename T>
+ TestCase& operator*(const T& in) {
+ in.fill(*this);
+ return *this;
+ }
+
+ bool operator<(const TestCase& other) const;
+
+ ~TestCase() = default;
+ };
+
+ // forward declarations of functions used by the macros
+ DOCTEST_INTERFACE int regTest(const TestCase& tc);
+ DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts);
+ DOCTEST_INTERFACE bool isDebuggerActive();
+
+ template<typename T>
+ int instantiationHelper(const T&) { return 0; }
+
+ namespace binaryAssertComparison {
+ enum Enum
+ {
+ eq = 0,
+ ne,
+ gt,
+ lt,
+ ge,
+ le
+ };
+ } // namespace binaryAssertComparison
+
+ // clang-format off
+ template <int, class L, class R> struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } };
+
+#define DOCTEST_BINARY_RELATIONAL_OP(n, op) \
+ template <class L, class R> struct RelationalComparator<n, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } };
+ // clang-format on
+
+ DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq)
+ DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne)
+ DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt)
+ DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt)
+ DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge)
+ DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le)
+
+ struct DOCTEST_INTERFACE ResultBuilder : public AssertData
+ {
+ ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type = "", const String& exception_string = "");
+
+ ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const Contains& exception_string);
+
+ void setResult(const Result& res);
+
+ template <int comparison, typename L, typename R>
+ DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ m_failed = !RelationalComparator<comparison, L, R>()(lhs, rhs);
+ if (m_failed || getContextOptions()->success) {
+ m_decomp = stringifyBinaryExpr(lhs, ", ", rhs);
+ }
+ return !m_failed;
+ }
+
+ template <typename L>
+ DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) {
+ m_failed = !val;
+
+ if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional
+ m_failed = !m_failed;
+ }
+
+ if (m_failed || getContextOptions()->success) {
+ m_decomp = (DOCTEST_STRINGIFY(val));
+ }
+
+ return !m_failed;
+ }
+
+ void translateException();
+
+ bool log();
+ void react() const;
+ };
+
+ namespace assertAction {
+ enum Enum
+ {
+ nothing = 0,
+ dbgbreak = 1,
+ shouldthrow = 2
+ };
+ } // namespace assertAction
+
+ DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad);
+
+ DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line,
+ const char* expr, const Result& result);
+
+#define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \
+ do { \
+ if(!is_running_in_test) { \
+ if(failed) { \
+ ResultBuilder rb(at, file, line, expr); \
+ rb.m_failed = failed; \
+ rb.m_decomp = decomp; \
+ failed_out_of_a_testing_context(rb); \
+ if(isDebuggerActive() && !getContextOptions()->no_breaks) \
+ DOCTEST_BREAK_INTO_DEBUGGER(); \
+ if(checkIfShouldThrow(at)) \
+ throwException(); \
+ } \
+ return !failed; \
+ } \
+ } while(false)
+
+#define DOCTEST_ASSERT_IN_TESTS(decomp) \
+ ResultBuilder rb(at, file, line, expr); \
+ rb.m_failed = failed; \
+ if(rb.m_failed || getContextOptions()->success) \
+ rb.m_decomp = decomp; \
+ if(rb.log()) \
+ DOCTEST_BREAK_INTO_DEBUGGER(); \
+ if(rb.m_failed && checkIfShouldThrow(at)) \
+ throwException()
+
+ template <int comparison, typename L, typename R>
+ DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line,
+ const char* expr, const DOCTEST_REF_WRAP(L) lhs,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ bool failed = !RelationalComparator<comparison, L, R>()(lhs, rhs);
+
+ // ###################################################################################
+ // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
+ // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
+ // ###################################################################################
+ DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
+ DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
+ return !failed;
+ }
+
+ template <typename L>
+ DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line,
+ const char* expr, const DOCTEST_REF_WRAP(L) val) {
+ bool failed = !val;
+
+ if(at & assertType::is_false) //!OCLINT bitwise operator in conditional
+ failed = !failed;
+
+ // ###################################################################################
+ // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
+ // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
+ // ###################################################################################
+ DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val)));
+ DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val)));
+ return !failed;
+ }
+
+ struct DOCTEST_INTERFACE IExceptionTranslator
+ {
+ DOCTEST_DECLARE_INTERFACE(IExceptionTranslator)
+ virtual bool translate(String&) const = 0;
+ };
+
+ template <typename T>
+ class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class
+ {
+ public:
+ explicit ExceptionTranslator(String (*translateFunction)(T))
+ : m_translateFunction(translateFunction) {}
+
+ bool translate(String& res) const override {
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ try {
+ throw; // lgtm [cpp/rethrow-no-exception]
+ // cppcheck-suppress catchExceptionByValue
+ } catch(const T& ex) {
+ res = m_translateFunction(ex); //!OCLINT parameter reassignment
+ return true;
+ } catch(...) {} //!OCLINT - empty catch statement
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ static_cast<void>(res); // to silence -Wunused-parameter
+ return false;
+ }
+
+ private:
+ String (*m_translateFunction)(T);
+ };
+
+ DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et);
+
+ // ContextScope base class used to allow implementing methods of ContextScope
+ // that don't depend on the template parameter in doctest.cpp.
+ struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope {
+ ContextScopeBase(const ContextScopeBase&) = delete;
+
+ ContextScopeBase& operator=(const ContextScopeBase&) = delete;
+ ContextScopeBase& operator=(ContextScopeBase&&) = delete;
+
+ ~ContextScopeBase() override = default;
+
+ protected:
+ ContextScopeBase();
+ ContextScopeBase(ContextScopeBase&& other) noexcept;
+
+ void destroy();
+ bool need_to_destroy{true};
+ };
+
+ template <typename L> class ContextScope : public ContextScopeBase
+ {
+ L lambda_;
+
+ public:
+ explicit ContextScope(const L &lambda) : lambda_(lambda) {}
+ explicit ContextScope(L&& lambda) : lambda_(static_cast<L&&>(lambda)) { }
+
+ ContextScope(const ContextScope&) = delete;
+ ContextScope(ContextScope&&) noexcept = default;
+
+ ContextScope& operator=(const ContextScope&) = delete;
+ ContextScope& operator=(ContextScope&&) = delete;
+
+ void stringify(std::ostream* s) const override { lambda_(s); }
+
+ ~ContextScope() override {
+ if (need_to_destroy) {
+ destroy();
+ }
+ }
+ };
+
+ struct DOCTEST_INTERFACE MessageBuilder : public MessageData
+ {
+ std::ostream* m_stream;
+ bool logged = false;
+
+ MessageBuilder(const char* file, int line, assertType::Enum severity);
+
+ MessageBuilder(const MessageBuilder&) = delete;
+ MessageBuilder(MessageBuilder&&) = delete;
+
+ MessageBuilder& operator=(const MessageBuilder&) = delete;
+ MessageBuilder& operator=(MessageBuilder&&) = delete;
+
+ ~MessageBuilder();
+
+ // the preferred way of chaining parameters for stringification
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866)
+ template <typename T>
+ MessageBuilder& operator,(const T& in) {
+ *m_stream << (DOCTEST_STRINGIFY(in));
+ return *this;
+ }
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ // kept here just for backwards-compatibility - the comma operator should be preferred now
+ template <typename T>
+ MessageBuilder& operator<<(const T& in) { return this->operator,(in); }
+
+ // the `,` operator has the lowest operator precedence - if `<<` is used by the user then
+ // the `,` operator will be called last which is not what we want and thus the `*` operator
+ // is used first (has higher operator precedence compared to `<<`) so that we guarantee that
+ // an operator of the MessageBuilder class is called first before the rest of the parameters
+ template <typename T>
+ MessageBuilder& operator*(const T& in) { return this->operator,(in); }
+
+ bool log();
+ void react();
+ };
+
+ template <typename L>
+ ContextScope<L> MakeContextScope(const L &lambda) {
+ return ContextScope<L>(lambda);
+ }
+} // namespace detail
+
+#define DOCTEST_DEFINE_DECORATOR(name, type, def) \
+ struct name \
+ { \
+ type data; \
+ name(type in = def) \
+ : data(in) {} \
+ void fill(detail::TestCase& state) const { state.DOCTEST_CAT(m_, name) = data; } \
+ void fill(detail::TestSuite& state) const { state.DOCTEST_CAT(m_, name) = data; } \
+ }
+
+DOCTEST_DEFINE_DECORATOR(test_suite, const char*, "");
+DOCTEST_DEFINE_DECORATOR(description, const char*, "");
+DOCTEST_DEFINE_DECORATOR(skip, bool, true);
+DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true);
+DOCTEST_DEFINE_DECORATOR(no_output, bool, true);
+DOCTEST_DEFINE_DECORATOR(timeout, double, 0);
+DOCTEST_DEFINE_DECORATOR(may_fail, bool, true);
+DOCTEST_DEFINE_DECORATOR(should_fail, bool, true);
+DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0);
+
+template <typename T>
+int registerExceptionTranslator(String (*translateFunction)(T)) {
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors")
+ static detail::ExceptionTranslator<T> exceptionTranslator(translateFunction);
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ detail::registerExceptionTranslatorImpl(&exceptionTranslator);
+ return 0;
+}
+
+} // namespace doctest
+
+// in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE macro
+// introduces an anonymous namespace in which getCurrentTestSuite gets overridden
+namespace doctest_detail_test_suite_ns {
+DOCTEST_INTERFACE doctest::detail::TestSuite& getCurrentTestSuite();
+} // namespace doctest_detail_test_suite_ns
+
+namespace doctest {
+#else // DOCTEST_CONFIG_DISABLE
+template <typename T>
+int registerExceptionTranslator(String (*)(T)) {
+ return 0;
+}
+#endif // DOCTEST_CONFIG_DISABLE
+
+namespace detail {
+ using assert_handler = void (*)(const AssertData&);
+ struct ContextState;
+} // namespace detail
+
+class DOCTEST_INTERFACE Context
+{
+ detail::ContextState* p;
+
+ void parseArgs(int argc, const char* const* argv, bool withDefaults = false);
+
+public:
+ explicit Context(int argc = 0, const char* const* argv = nullptr);
+
+ Context(const Context&) = delete;
+ Context(Context&&) = delete;
+
+ Context& operator=(const Context&) = delete;
+ Context& operator=(Context&&) = delete;
+
+ ~Context(); // NOLINT(performance-trivially-destructible)
+
+ void applyCommandLine(int argc, const char* const* argv);
+
+ void addFilter(const char* filter, const char* value);
+ void clearFilters();
+ void setOption(const char* option, bool value);
+ void setOption(const char* option, int value);
+ void setOption(const char* option, const char* value);
+
+ bool shouldExit();
+
+ void setAsDefaultForAssertsOutOfTestCases();
+
+ void setAssertHandler(detail::assert_handler ah);
+
+ void setCout(std::ostream* out);
+
+ int run();
+};
+
+namespace TestCaseFailureReason {
+ enum Enum
+ {
+ None = 0,
+ AssertFailure = 1, // an assertion has failed in the test case
+ Exception = 2, // test case threw an exception
+ Crash = 4, // a crash...
+ TooManyFailedAsserts = 8, // the abort-after option
+ Timeout = 16, // see the timeout decorator
+ ShouldHaveFailedButDidnt = 32, // see the should_fail decorator
+ ShouldHaveFailedAndDid = 64, // see the should_fail decorator
+ DidntFailExactlyNumTimes = 128, // see the expected_failures decorator
+ FailedExactlyNumTimes = 256, // see the expected_failures decorator
+ CouldHaveFailedAndDid = 512 // see the may_fail decorator
+ };
+} // namespace TestCaseFailureReason
+
+struct DOCTEST_INTERFACE CurrentTestCaseStats
+{
+ int numAssertsCurrentTest;
+ int numAssertsFailedCurrentTest;
+ double seconds;
+ int failure_flags; // use TestCaseFailureReason::Enum
+ bool testCaseSuccess;
+};
+
+struct DOCTEST_INTERFACE TestCaseException
+{
+ String error_string;
+ bool is_crash;
+};
+
+struct DOCTEST_INTERFACE TestRunStats
+{
+ unsigned numTestCases;
+ unsigned numTestCasesPassingFilters;
+ unsigned numTestSuitesPassingFilters;
+ unsigned numTestCasesFailed;
+ int numAsserts;
+ int numAssertsFailed;
+};
+
+struct QueryData
+{
+ const TestRunStats* run_stats = nullptr;
+ const TestCaseData** data = nullptr;
+ unsigned num_data = 0;
+};
+
+struct DOCTEST_INTERFACE IReporter
+{
+ // The constructor has to accept "const ContextOptions&" as a single argument
+ // which has most of the options for the run + a pointer to the stdout stream
+ // Reporter(const ContextOptions& in)
+
+ // called when a query should be reported (listing test cases, printing the version, etc.)
+ virtual void report_query(const QueryData&) = 0;
+
+ // called when the whole test run starts
+ virtual void test_run_start() = 0;
+ // called when the whole test run ends (caching a pointer to the input doesn't make sense here)
+ virtual void test_run_end(const TestRunStats&) = 0;
+
+ // called when a test case is started (safe to cache a pointer to the input)
+ virtual void test_case_start(const TestCaseData&) = 0;
+ // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input)
+ virtual void test_case_reenter(const TestCaseData&) = 0;
+ // called when a test case has ended
+ virtual void test_case_end(const CurrentTestCaseStats&) = 0;
+
+ // called when an exception is thrown from the test case (or it crashes)
+ virtual void test_case_exception(const TestCaseException&) = 0;
+
+ // called whenever a subcase is entered (don't cache pointers to the input)
+ virtual void subcase_start(const SubcaseSignature&) = 0;
+ // called whenever a subcase is exited (don't cache pointers to the input)
+ virtual void subcase_end() = 0;
+
+ // called for each assert (don't cache pointers to the input)
+ virtual void log_assert(const AssertData&) = 0;
+ // called for each message (don't cache pointers to the input)
+ virtual void log_message(const MessageData&) = 0;
+
+ // called when a test case is skipped either because it doesn't pass the filters, has a skip decorator
+ // or isn't in the execution range (between first and last) (safe to cache a pointer to the input)
+ virtual void test_case_skipped(const TestCaseData&) = 0;
+
+ DOCTEST_DECLARE_INTERFACE(IReporter)
+
+ // can obtain all currently active contexts and stringify them if one wishes to do so
+ static int get_num_active_contexts();
+ static const IContextScope* const* get_active_contexts();
+
+ // can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown
+ static int get_num_stringified_contexts();
+ static const String* get_stringified_contexts();
+};
+
+namespace detail {
+ using reporterCreatorFunc = IReporter* (*)(const ContextOptions&);
+
+ DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter);
+
+ template <typename Reporter>
+ IReporter* reporterCreator(const ContextOptions& o) {
+ return new Reporter(o);
+ }
+} // namespace detail
+
+template <typename Reporter>
+int registerReporter(const char* name, int priority, bool isReporter) {
+ detail::registerReporterImpl(name, priority, detail::reporterCreator<Reporter>, isReporter);
+ return 0;
+}
+} // namespace doctest
+
+#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES
+#define DOCTEST_FUNC_EMPTY [] { return false; }()
+#else
+#define DOCTEST_FUNC_EMPTY (void)0
+#endif
+
+// if registering is not disabled
+#ifndef DOCTEST_CONFIG_DISABLE
+
+#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES
+#define DOCTEST_FUNC_SCOPE_BEGIN [&]
+#define DOCTEST_FUNC_SCOPE_END ()
+#define DOCTEST_FUNC_SCOPE_RET(v) return v
+#else
+#define DOCTEST_FUNC_SCOPE_BEGIN do
+#define DOCTEST_FUNC_SCOPE_END while(false)
+#define DOCTEST_FUNC_SCOPE_RET(v) (void)0
+#endif
+
+// common code in asserts - for convenience
+#define DOCTEST_ASSERT_LOG_REACT_RETURN(b) \
+ if(b.log()) DOCTEST_BREAK_INTO_DEBUGGER(); \
+ b.react(); \
+ DOCTEST_FUNC_SCOPE_RET(!b.m_failed)
+
+#ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+#define DOCTEST_WRAP_IN_TRY(x) x;
+#else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+#define DOCTEST_WRAP_IN_TRY(x) \
+ try { \
+ x; \
+ } catch(...) { DOCTEST_RB.translateException(); }
+#endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+
+#ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
+#define DOCTEST_CAST_TO_VOID(...) \
+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \
+ static_cast<void>(__VA_ARGS__); \
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
+#else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
+#define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__;
+#endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
+
+// registers the test by initializing a dummy var with a function
+#define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \
+ global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */ \
+ doctest::detail::regTest( \
+ doctest::detail::TestCase( \
+ f, __FILE__, __LINE__, \
+ doctest_detail_test_suite_ns::getCurrentTestSuite()) * \
+ decorators))
+
+#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \
+ namespace { /* NOLINT */ \
+ struct der : public base \
+ { \
+ void f(); \
+ }; \
+ static DOCTEST_INLINE_NOINLINE void func() { \
+ der v; \
+ v.f(); \
+ } \
+ DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \
+ } \
+ DOCTEST_INLINE_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers)
+
+#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators) \
+ static void f(); \
+ DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators) \
+ static void f()
+
+#define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \
+ static doctest::detail::funcType proxy() { return f; } \
+ DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \
+ static void f()
+
+// for registering tests
+#define DOCTEST_TEST_CASE(decorators) \
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators)
+
+// for registering tests in classes - requires C++17 for inline variables!
+#if DOCTEST_CPLUSPLUS >= 201703L
+#define DOCTEST_TEST_CASE_CLASS(decorators) \
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \
+ DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), \
+ decorators)
+#else // DOCTEST_TEST_CASE_CLASS
+#define DOCTEST_TEST_CASE_CLASS(...) \
+ TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER
+#endif // DOCTEST_TEST_CASE_CLASS
+
+// for registering tests with a fixture
+#define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \
+ DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \
+ DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators)
+
+// for converting types to strings without the <typeinfo> header and demangling
+#define DOCTEST_TYPE_TO_STRING_AS(str, ...) \
+ namespace doctest { \
+ template <> \
+ inline String toString<__VA_ARGS__>() { \
+ return str; \
+ } \
+ } \
+ static_assert(true, "")
+
+#define DOCTEST_TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING_AS(#__VA_ARGS__, __VA_ARGS__)
+
+#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \
+ template <typename T> \
+ static void func(); \
+ namespace { /* NOLINT */ \
+ template <typename Tuple> \
+ struct iter; \
+ template <typename Type, typename... Rest> \
+ struct iter<std::tuple<Type, Rest...>> \
+ { \
+ iter(const char* file, unsigned line, int index) { \
+ doctest::detail::regTest(doctest::detail::TestCase(func<Type>, file, line, \
+ doctest_detail_test_suite_ns::getCurrentTestSuite(), \
+ doctest::toString<Type>(), \
+ int(line) * 1000 + index) \
+ * dec); \
+ iter<std::tuple<Rest...>>(file, line, index + 1); \
+ } \
+ }; \
+ template <> \
+ struct iter<std::tuple<>> \
+ { \
+ iter(const char*, unsigned, int) {} \
+ }; \
+ } \
+ template <typename T> \
+ static void func()
+
+#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \
+ DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \
+ DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_))
+
+#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY), /* NOLINT(cert-err58-cpp, fuchsia-statically-constructed-objects) */ \
+ doctest::detail::instantiationHelper( \
+ DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0)))
+
+#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \
+ static_assert(true, "")
+
+#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \
+ static_assert(true, "")
+
+#define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \
+ DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \
+ template <typename T> \
+ static void anon()
+
+#define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \
+ DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__)
+
+// for subcases
+#define DOCTEST_SUBCASE(name) \
+ if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \
+ doctest::detail::Subcase(name, __FILE__, __LINE__))
+
+// for grouping tests in test suites by using code blocks
+#define DOCTEST_TEST_SUITE_IMPL(decorators, ns_name) \
+ namespace ns_name { namespace doctest_detail_test_suite_ns { \
+ static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() noexcept { \
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \
+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \
+ static doctest::detail::TestSuite data{}; \
+ static bool inited = false; \
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP \
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP \
+ DOCTEST_GCC_SUPPRESS_WARNING_POP \
+ if(!inited) { \
+ data* decorators; \
+ inited = true; \
+ } \
+ return data; \
+ } \
+ } \
+ } \
+ namespace ns_name
+
+#define DOCTEST_TEST_SUITE(decorators) \
+ DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_))
+
+// for starting a testsuite block
+#define DOCTEST_TEST_SUITE_BEGIN(decorators) \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \
+ doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \
+ static_assert(true, "")
+
+// for ending a testsuite block
+#define DOCTEST_TEST_SUITE_END \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \
+ doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \
+ using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int
+
+// for registering exception translators
+#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \
+ inline doctest::String translatorName(signature); \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \
+ doctest::registerExceptionTranslator(translatorName)) \
+ doctest::String translatorName(signature)
+
+#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \
+ DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \
+ signature)
+
+// for registering reporters
+#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \
+ doctest::registerReporter<reporter>(name, priority, true)) \
+ static_assert(true, "")
+
+// for registering listeners
+#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \
+ doctest::registerReporter<reporter>(name, priority, false)) \
+ static_assert(true, "")
+
+// clang-format off
+// for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557
+#define DOCTEST_INFO(...) \
+ DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_), \
+ DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_OTHER_), \
+ __VA_ARGS__)
+// clang-format on
+
+#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \
+ auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \
+ [&](std::ostream* s_name) { \
+ doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \
+ mb_name.m_stream = s_name; \
+ mb_name * __VA_ARGS__; \
+ })
+
+#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x)
+
+#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
+ doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \
+ mb * __VA_ARGS__; \
+ if(mb.log()) \
+ DOCTEST_BREAK_INTO_DEBUGGER(); \
+ mb.react(); \
+ } DOCTEST_FUNC_SCOPE_END
+
+// clang-format off
+#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
+#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
+#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
+// clang-format on
+
+#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__)
+#define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__)
+#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__)
+
+#define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility.
+
+#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+#define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \
+ /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \
+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, #__VA_ARGS__); \
+ DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \
+ doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \
+ << __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \
+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+
+#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
+ DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \
+ } DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
+
+#define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, #__VA_ARGS__); \
+ DOCTEST_WRAP_IN_TRY( \
+ DOCTEST_RB.binary_assert<doctest::detail::binaryAssertComparison::comp>( \
+ __VA_ARGS__)) \
+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
+ } DOCTEST_FUNC_SCOPE_END
+
+#define DOCTEST_UNARY_ASSERT(assert_type, ...) \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, #__VA_ARGS__); \
+ DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \
+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
+ } DOCTEST_FUNC_SCOPE_END
+
+#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+// necessary for <ASSERT>_MESSAGE
+#define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1
+
+#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \
+ doctest::detail::decomp_assert( \
+ doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, \
+ doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \
+ << __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP
+
+#define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...) \
+ doctest::detail::binary_assert<doctest::detail::binaryAssertComparison::comparison>( \
+ doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__)
+
+#define DOCTEST_UNARY_ASSERT(assert_type, ...) \
+ doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \
+ #__VA_ARGS__, __VA_ARGS__)
+
+#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__)
+#define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__)
+#define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__)
+#define DOCTEST_WARN_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__)
+#define DOCTEST_CHECK_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__)
+#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__)
+
+// clang-format off
+#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } DOCTEST_FUNC_SCOPE_END
+// clang-format on
+
+#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__)
+#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__)
+#define DOCTEST_REQUIRE_EQ(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__)
+#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__)
+#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__)
+#define DOCTEST_REQUIRE_NE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__)
+#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__)
+#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__)
+#define DOCTEST_REQUIRE_GT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__)
+#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__)
+#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__)
+#define DOCTEST_REQUIRE_LT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__)
+#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__)
+#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__)
+#define DOCTEST_REQUIRE_GE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__)
+#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__)
+#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__)
+#define DOCTEST_REQUIRE_LE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__)
+
+#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__)
+#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__)
+#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__)
+#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__)
+#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__)
+#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__)
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
+ if(!doctest::getContextOptions()->no_throw) { \
+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, #expr, #__VA_ARGS__, message); \
+ try { \
+ DOCTEST_CAST_TO_VOID(expr) \
+ } catch(const typename doctest::detail::types::remove_const< \
+ typename doctest::detail::types::remove_reference<__VA_ARGS__>::type>::type&) {\
+ DOCTEST_RB.translateException(); \
+ DOCTEST_RB.m_threw_as = true; \
+ } catch(...) { DOCTEST_RB.translateException(); } \
+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
+ } else { /* NOLINT(*-else-after-return) */ \
+ DOCTEST_FUNC_SCOPE_RET(false); \
+ } \
+ } DOCTEST_FUNC_SCOPE_END
+
+#define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
+ if(!doctest::getContextOptions()->no_throw) { \
+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, expr_str, "", __VA_ARGS__); \
+ try { \
+ DOCTEST_CAST_TO_VOID(expr) \
+ } catch(...) { DOCTEST_RB.translateException(); } \
+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
+ } else { /* NOLINT(*-else-after-return) */ \
+ DOCTEST_FUNC_SCOPE_RET(false); \
+ } \
+ } DOCTEST_FUNC_SCOPE_END
+
+#define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, #__VA_ARGS__); \
+ try { \
+ DOCTEST_CAST_TO_VOID(__VA_ARGS__) \
+ } catch(...) { DOCTEST_RB.translateException(); } \
+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
+ } DOCTEST_FUNC_SCOPE_END
+
+// clang-format off
+#define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "")
+#define DOCTEST_CHECK_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_CHECK_THROWS, "")
+#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_REQUIRE_THROWS, "")
+
+#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__)
+#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__)
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__)
+
+#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_WARN_THROWS_WITH, __VA_ARGS__)
+#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_CHECK_THROWS_WITH, __VA_ARGS__)
+#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__)
+
+#define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__)
+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__)
+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__)
+
+#define DOCTEST_WARN_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_WARN_NOTHROW, __VA_ARGS__)
+#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__)
+#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__)
+
+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END
+// clang-format on
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+// =================================================================================================
+// == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING! ==
+// == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY! ==
+// =================================================================================================
+#else // DOCTEST_CONFIG_DISABLE
+
+#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \
+ namespace /* NOLINT */ { \
+ template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
+ struct der : public base \
+ { void f(); }; \
+ } \
+ template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
+ inline void der<DOCTEST_UNUSED_TEMPLATE_TYPE>::f()
+
+#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \
+ template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
+ static inline void f()
+
+// for registering tests
+#define DOCTEST_TEST_CASE(name) \
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
+
+// for registering tests in classes
+#define DOCTEST_TEST_CASE_CLASS(name) \
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
+
+// for registering tests with a fixture
+#define DOCTEST_TEST_CASE_FIXTURE(x, name) \
+ DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \
+ DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
+
+// for converting types to strings without the <typeinfo> header and demangling
+#define DOCTEST_TYPE_TO_STRING_AS(str, ...) static_assert(true, "")
+#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "")
+
+// for typed tests
+#define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \
+ template <typename type> \
+ inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)()
+
+#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \
+ template <typename type> \
+ inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)()
+
+#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "")
+#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "")
+
+// for subcases
+#define DOCTEST_SUBCASE(name)
+
+// for a testsuite block
+#define DOCTEST_TEST_SUITE(name) namespace // NOLINT
+
+// for starting a testsuite block
+#define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "")
+
+// for ending a testsuite block
+#define DOCTEST_TEST_SUITE_END using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int
+
+#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \
+ template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
+ static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature)
+
+#define DOCTEST_REGISTER_REPORTER(name, priority, reporter)
+#define DOCTEST_REGISTER_LISTENER(name, priority, reporter)
+
+#define DOCTEST_INFO(...) (static_cast<void>(0))
+#define DOCTEST_CAPTURE(x) (static_cast<void>(0))
+#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast<void>(0))
+#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast<void>(0))
+#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast<void>(0))
+#define DOCTEST_MESSAGE(...) (static_cast<void>(0))
+#define DOCTEST_FAIL_CHECK(...) (static_cast<void>(0))
+#define DOCTEST_FAIL(...) (static_cast<void>(0))
+
+#if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED) \
+ && defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES)
+
+#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }()
+#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }()
+#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }()
+#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }()
+#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }()
+
+#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }()
+#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }()
+#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }()
+#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
+#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
+#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
+
+namespace doctest {
+namespace detail {
+#define DOCTEST_RELATIONAL_OP(name, op) \
+ template <typename L, typename R> \
+ bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs op rhs; }
+
+ DOCTEST_RELATIONAL_OP(eq, ==)
+ DOCTEST_RELATIONAL_OP(ne, !=)
+ DOCTEST_RELATIONAL_OP(lt, <)
+ DOCTEST_RELATIONAL_OP(gt, >)
+ DOCTEST_RELATIONAL_OP(le, <=)
+ DOCTEST_RELATIONAL_OP(ge, >=)
+} // namespace detail
+} // namespace doctest
+
+#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
+#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
+#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
+#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
+#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
+#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
+#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
+#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
+#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
+#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
+#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
+#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
+#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }()
+#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }()
+#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }()
+#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
+#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#define DOCTEST_WARN_THROWS_WITH(expr, with, ...) [] { static_assert(false, "Exception translation is not available when doctest is disabled."); return false; }()
+#define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
+
+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
+
+#define DOCTEST_WARN_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
+#define DOCTEST_CHECK_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
+#define DOCTEST_REQUIRE_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
+#define DOCTEST_WARN_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
+#define DOCTEST_CHECK_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
+#define DOCTEST_WARN_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
+#define DOCTEST_CHECK_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
+#define DOCTEST_REQUIRE_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
+
+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED
+
+#define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_FUNC_EMPTY
+
+#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
+
+#define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_EQ(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_NE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_GT(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_LT(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_GE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_LE(...) DOCTEST_FUNC_EMPTY
+
+#define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY
+
+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED
+
+#endif // DOCTEST_CONFIG_DISABLE
+
+#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+#define DOCTEST_EXCEPTION_EMPTY_FUNC DOCTEST_FUNC_EMPTY
+#else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+#define DOCTEST_EXCEPTION_EMPTY_FUNC [] { static_assert(false, "Exceptions are disabled! " \
+ "Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if you want to compile with exceptions disabled."); return false; }()
+
+#undef DOCTEST_REQUIRE
+#undef DOCTEST_REQUIRE_FALSE
+#undef DOCTEST_REQUIRE_MESSAGE
+#undef DOCTEST_REQUIRE_FALSE_MESSAGE
+#undef DOCTEST_REQUIRE_EQ
+#undef DOCTEST_REQUIRE_NE
+#undef DOCTEST_REQUIRE_GT
+#undef DOCTEST_REQUIRE_LT
+#undef DOCTEST_REQUIRE_GE
+#undef DOCTEST_REQUIRE_LE
+#undef DOCTEST_REQUIRE_UNARY
+#undef DOCTEST_REQUIRE_UNARY_FALSE
+
+#define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_FALSE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+
+#define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC
+
+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+// clang-format off
+// KEPT FOR BACKWARDS COMPATIBILITY - FORWARDING TO THE RIGHT MACROS
+#define DOCTEST_FAST_WARN_EQ DOCTEST_WARN_EQ
+#define DOCTEST_FAST_CHECK_EQ DOCTEST_CHECK_EQ
+#define DOCTEST_FAST_REQUIRE_EQ DOCTEST_REQUIRE_EQ
+#define DOCTEST_FAST_WARN_NE DOCTEST_WARN_NE
+#define DOCTEST_FAST_CHECK_NE DOCTEST_CHECK_NE
+#define DOCTEST_FAST_REQUIRE_NE DOCTEST_REQUIRE_NE
+#define DOCTEST_FAST_WARN_GT DOCTEST_WARN_GT
+#define DOCTEST_FAST_CHECK_GT DOCTEST_CHECK_GT
+#define DOCTEST_FAST_REQUIRE_GT DOCTEST_REQUIRE_GT
+#define DOCTEST_FAST_WARN_LT DOCTEST_WARN_LT
+#define DOCTEST_FAST_CHECK_LT DOCTEST_CHECK_LT
+#define DOCTEST_FAST_REQUIRE_LT DOCTEST_REQUIRE_LT
+#define DOCTEST_FAST_WARN_GE DOCTEST_WARN_GE
+#define DOCTEST_FAST_CHECK_GE DOCTEST_CHECK_GE
+#define DOCTEST_FAST_REQUIRE_GE DOCTEST_REQUIRE_GE
+#define DOCTEST_FAST_WARN_LE DOCTEST_WARN_LE
+#define DOCTEST_FAST_CHECK_LE DOCTEST_CHECK_LE
+#define DOCTEST_FAST_REQUIRE_LE DOCTEST_REQUIRE_LE
+
+#define DOCTEST_FAST_WARN_UNARY DOCTEST_WARN_UNARY
+#define DOCTEST_FAST_CHECK_UNARY DOCTEST_CHECK_UNARY
+#define DOCTEST_FAST_REQUIRE_UNARY DOCTEST_REQUIRE_UNARY
+#define DOCTEST_FAST_WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE
+#define DOCTEST_FAST_CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE
+#define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE
+
+#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id,__VA_ARGS__)
+// clang-format on
+
+// BDD style macros
+// clang-format off
+#define DOCTEST_SCENARIO(name) DOCTEST_TEST_CASE(" Scenario: " name)
+#define DOCTEST_SCENARIO_CLASS(name) DOCTEST_TEST_CASE_CLASS(" Scenario: " name)
+#define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__)
+#define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id)
+
+#define DOCTEST_GIVEN(name) DOCTEST_SUBCASE(" Given: " name)
+#define DOCTEST_WHEN(name) DOCTEST_SUBCASE(" When: " name)
+#define DOCTEST_AND_WHEN(name) DOCTEST_SUBCASE("And when: " name)
+#define DOCTEST_THEN(name) DOCTEST_SUBCASE(" Then: " name)
+#define DOCTEST_AND_THEN(name) DOCTEST_SUBCASE(" And: " name)
+// clang-format on
+
+// == SHORT VERSIONS OF THE MACROS
+#ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
+
+#define TEST_CASE(name) DOCTEST_TEST_CASE(name)
+#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name)
+#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name)
+#define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__)
+#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__)
+#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__)
+#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id)
+#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__)
+#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__)
+#define SUBCASE(name) DOCTEST_SUBCASE(name)
+#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators)
+#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name)
+#define TEST_SUITE_END DOCTEST_TEST_SUITE_END
+#define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature)
+#define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter)
+#define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter)
+#define INFO(...) DOCTEST_INFO(__VA_ARGS__)
+#define CAPTURE(x) DOCTEST_CAPTURE(x)
+#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__)
+#define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__)
+#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__)
+#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__)
+#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__)
+#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__)
+#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__)
+
+#define WARN(...) DOCTEST_WARN(__VA_ARGS__)
+#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__)
+#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__)
+#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__)
+#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__)
+#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__)
+#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__)
+#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__)
+#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__)
+#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__)
+#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__)
+#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__)
+#define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__)
+#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__)
+#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__)
+#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__)
+#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__)
+#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__)
+#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__)
+#define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__)
+#define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__)
+
+#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__)
+#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__)
+#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__)
+#define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
+#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
+#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
+#define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__)
+#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__)
+#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__)
+#define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__)
+#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
+#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
+#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
+#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__)
+#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__)
+#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__)
+#define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__)
+#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
+#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
+#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
+#define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__)
+
+#define SCENARIO(name) DOCTEST_SCENARIO(name)
+#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name)
+#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__)
+#define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id)
+#define GIVEN(name) DOCTEST_GIVEN(name)
+#define WHEN(name) DOCTEST_WHEN(name)
+#define AND_WHEN(name) DOCTEST_AND_WHEN(name)
+#define THEN(name) DOCTEST_THEN(name)
+#define AND_THEN(name) DOCTEST_AND_THEN(name)
+
+#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__)
+#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__)
+#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__)
+#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__)
+#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__)
+#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__)
+#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__)
+#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__)
+#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__)
+#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__)
+#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__)
+#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__)
+#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__)
+#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__)
+#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__)
+#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__)
+#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__)
+#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__)
+#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__)
+#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__)
+#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__)
+#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__)
+#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__)
+#define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__)
+
+// KEPT FOR BACKWARDS COMPATIBILITY
+#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__)
+#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__)
+#define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__)
+#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__)
+#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__)
+#define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__)
+#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__)
+#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__)
+#define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__)
+#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__)
+#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__)
+#define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__)
+#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__)
+#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__)
+#define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__)
+#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__)
+#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__)
+#define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__)
+
+#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__)
+#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__)
+#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__)
+#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__)
+#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__)
+#define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__)
+
+#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__)
+
+#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
+
+#ifndef DOCTEST_CONFIG_DISABLE
+
+// this is here to clear the 'current test suite' for the current translation unit - at the top
+DOCTEST_TEST_SUITE_END();
+
+#endif // DOCTEST_CONFIG_DISABLE
+
+DOCTEST_CLANG_SUPPRESS_WARNING_POP
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+DOCTEST_GCC_SUPPRESS_WARNING_POP
+
+DOCTEST_SUPPRESS_COMMON_WARNINGS_POP
+
+#endif // DOCTEST_LIBRARY_INCLUDED
+
+#ifndef DOCTEST_SINGLE_HEADER
+#define DOCTEST_SINGLE_HEADER
+#endif // DOCTEST_SINGLE_HEADER
+
+#if defined(DOCTEST_CONFIG_IMPLEMENT) || !defined(DOCTEST_SINGLE_HEADER)
+
+#ifndef DOCTEST_SINGLE_HEADER
+#include "doctest_fwd.h"
+#endif // DOCTEST_SINGLE_HEADER
+
+DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros")
+
+#ifndef DOCTEST_LIBRARY_IMPLEMENTATION
+#define DOCTEST_LIBRARY_IMPLEMENTATION
+
+DOCTEST_CLANG_SUPPRESS_WARNING_POP
+
+DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH
+
+DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wglobal-constructors")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wshorten-64-to-32")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-variable-declarations")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch-enum")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wcovered-switch-default")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-noreturn")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wdisabled-macro-expansion")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-braces")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path")
+
+DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-field-initializers")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-braces")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-enum")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-default")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wunsafe-loop-optimizations")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wold-style-cast")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-function")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wmultiple-inheritance")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wsuggest-attribute")
+
+DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+DOCTEST_MSVC_SUPPRESS_WARNING(4267) // 'var' : conversion from 'x' to 'y', possible loss of data
+DOCTEST_MSVC_SUPPRESS_WARNING(4530) // C++ exception handler used, but unwind semantics not enabled
+DOCTEST_MSVC_SUPPRESS_WARNING(4577) // 'noexcept' used with no exception handling mode specified
+DOCTEST_MSVC_SUPPRESS_WARNING(4774) // format string expected in argument is not a string literal
+DOCTEST_MSVC_SUPPRESS_WARNING(4365) // conversion from 'int' to 'unsigned', signed/unsigned mismatch
+DOCTEST_MSVC_SUPPRESS_WARNING(5039) // pointer to potentially throwing function passed to extern C
+DOCTEST_MSVC_SUPPRESS_WARNING(4800) // forcing value to bool 'true' or 'false' (performance warning)
+DOCTEST_MSVC_SUPPRESS_WARNING(5245) // unreferenced function with internal linkage has been removed
+
+DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
+
+// required includes - will go only in one translation unit!
+#include <ctime>
+#include <cmath>
+#include <climits>
+// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/doctest/doctest/pull/37
+#ifdef __BORLANDC__
+#include <math.h>
+#endif // __BORLANDC__
+#include <new>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <limits>
+#include <utility>
+#include <fstream>
+#include <sstream>
+#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+#include <iostream>
+#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+#include <algorithm>
+#include <iomanip>
+#include <vector>
+#ifndef DOCTEST_CONFIG_NO_MULTITHREADING
+#include <atomic>
+#include <mutex>
+#define DOCTEST_DECLARE_MUTEX(name) std::mutex name;
+#define DOCTEST_DECLARE_STATIC_MUTEX(name) static DOCTEST_DECLARE_MUTEX(name)
+#define DOCTEST_LOCK_MUTEX(name) std::lock_guard<std::mutex> DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name);
+#else // DOCTEST_CONFIG_NO_MULTITHREADING
+#define DOCTEST_DECLARE_MUTEX(name)
+#define DOCTEST_DECLARE_STATIC_MUTEX(name)
+#define DOCTEST_LOCK_MUTEX(name)
+#endif // DOCTEST_CONFIG_NO_MULTITHREADING
+#include <set>
+#include <map>
+#include <unordered_set>
+#include <exception>
+#include <stdexcept>
+#include <csignal>
+#include <cfloat>
+#include <cctype>
+#include <cstdint>
+#include <string>
+
+#ifdef DOCTEST_PLATFORM_MAC
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+#endif // DOCTEST_PLATFORM_MAC
+
+#ifdef DOCTEST_PLATFORM_WINDOWS
+
+// defines for a leaner windows.h
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#define DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN
+#endif // WIN32_LEAN_AND_MEAN
+#ifndef NOMINMAX
+#define NOMINMAX
+#define DOCTEST_UNDEF_NOMINMAX
+#endif // NOMINMAX
+
+// not sure what AfxWin.h is for - here I do what Catch does
+#ifdef __AFXDLL
+#include <AfxWin.h>
+#else
+#include <windows.h>
+#endif
+#include <io.h>
+
+#else // DOCTEST_PLATFORM_WINDOWS
+
+#include <sys/time.h>
+#include <unistd.h>
+
+#endif // DOCTEST_PLATFORM_WINDOWS
+
+// this is a fix for https://github.com/doctest/doctest/issues/348
+// https://mail.gnome.org/archives/xml/2012-January/msg00000.html
+#if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO)
+#define STDOUT_FILENO fileno(stdout)
+#endif // HAVE_UNISTD_H
+
+DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
+
+// counts the number of elements in a C array
+#define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
+
+#ifdef DOCTEST_CONFIG_DISABLE
+#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_disabled
+#else // DOCTEST_CONFIG_DISABLE
+#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_not_disabled
+#endif // DOCTEST_CONFIG_DISABLE
+
+#ifndef DOCTEST_CONFIG_OPTIONS_PREFIX
+#define DOCTEST_CONFIG_OPTIONS_PREFIX "dt-"
+#endif
+
+#ifndef DOCTEST_THREAD_LOCAL
+#if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_THREAD_LOCAL
+#else // DOCTEST_MSVC
+#define DOCTEST_THREAD_LOCAL thread_local
+#endif // DOCTEST_MSVC
+#endif // DOCTEST_THREAD_LOCAL
+
+#ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES
+#define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32
+#endif
+
+#ifndef DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE
+#define DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE 64
+#endif
+
+#ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+#define DOCTEST_OPTIONS_PREFIX_DISPLAY DOCTEST_CONFIG_OPTIONS_PREFIX
+#else
+#define DOCTEST_OPTIONS_PREFIX_DISPLAY ""
+#endif
+
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
+#endif
+
+#ifndef DOCTEST_CDECL
+#define DOCTEST_CDECL __cdecl
+#endif
+
+namespace doctest {
+
+bool is_running_in_test = false;
+
+namespace {
+ using namespace detail;
+
+ template <typename Ex>
+ DOCTEST_NORETURN void throw_exception(Ex const& e) {
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ throw e;
+#else // DOCTEST_CONFIG_NO_EXCEPTIONS
+#ifdef DOCTEST_CONFIG_HANDLE_EXCEPTION
+ DOCTEST_CONFIG_HANDLE_EXCEPTION(e);
+#else // DOCTEST_CONFIG_HANDLE_EXCEPTION
+#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+ std::cerr << "doctest will terminate because it needed to throw an exception.\n"
+ << "The message was: " << e.what() << '\n';
+#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+#endif // DOCTEST_CONFIG_HANDLE_EXCEPTION
+ std::terminate();
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ }
+
+#ifndef DOCTEST_INTERNAL_ERROR
+#define DOCTEST_INTERNAL_ERROR(msg) \
+ throw_exception(std::logic_error( \
+ __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg))
+#endif // DOCTEST_INTERNAL_ERROR
+
+ // case insensitive strcmp
+ int stricmp(const char* a, const char* b) {
+ for(;; a++, b++) {
+ const int d = tolower(*a) - tolower(*b);
+ if(d != 0 || !*a)
+ return d;
+ }
+ }
+
+ struct Endianness
+ {
+ enum Arch
+ {
+ Big,
+ Little
+ };
+
+ static Arch which() {
+ int x = 1;
+ // casting any data pointer to char* is allowed
+ auto ptr = reinterpret_cast<char*>(&x);
+ if(*ptr)
+ return Little;
+ return Big;
+ }
+ };
+} // namespace
+
+namespace detail {
+ DOCTEST_THREAD_LOCAL class
+ {
+ std::vector<std::streampos> stack;
+ std::stringstream ss;
+
+ public:
+ std::ostream* push() {
+ stack.push_back(ss.tellp());
+ return &ss;
+ }
+
+ String pop() {
+ if (stack.empty())
+ DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!");
+
+ std::streampos pos = stack.back();
+ stack.pop_back();
+ unsigned sz = static_cast<unsigned>(ss.tellp() - pos);
+ ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out);
+ return String(ss, sz);
+ }
+ } g_oss;
+
+ std::ostream* tlssPush() {
+ return g_oss.push();
+ }
+
+ String tlssPop() {
+ return g_oss.pop();
+ }
+
+#ifndef DOCTEST_CONFIG_DISABLE
+
+namespace timer_large_integer
+{
+
+#if defined(DOCTEST_PLATFORM_WINDOWS)
+ using type = ULONGLONG;
+#else // DOCTEST_PLATFORM_WINDOWS
+ using type = std::uint64_t;
+#endif // DOCTEST_PLATFORM_WINDOWS
+}
+
+using ticks_t = timer_large_integer::type;
+
+#ifdef DOCTEST_CONFIG_GETCURRENTTICKS
+ ticks_t getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); }
+#elif defined(DOCTEST_PLATFORM_WINDOWS)
+ ticks_t getCurrentTicks() {
+ static LARGE_INTEGER hz = { {0} }, hzo = { {0} };
+ if(!hz.QuadPart) {
+ QueryPerformanceFrequency(&hz);
+ QueryPerformanceCounter(&hzo);
+ }
+ LARGE_INTEGER t;
+ QueryPerformanceCounter(&t);
+ return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart;
+ }
+#else // DOCTEST_PLATFORM_WINDOWS
+ ticks_t getCurrentTicks() {
+ timeval t;
+ gettimeofday(&t, nullptr);
+ return static_cast<ticks_t>(t.tv_sec) * 1000000 + static_cast<ticks_t>(t.tv_usec);
+ }
+#endif // DOCTEST_PLATFORM_WINDOWS
+
+ struct Timer
+ {
+ void start() { m_ticks = getCurrentTicks(); }
+ unsigned int getElapsedMicroseconds() const {
+ return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
+ }
+ //unsigned int getElapsedMilliseconds() const {
+ // return static_cast<unsigned int>(getElapsedMicroseconds() / 1000);
+ //}
+ double getElapsedSeconds() const { return static_cast<double>(getCurrentTicks() - m_ticks) / 1000000.0; }
+
+ private:
+ ticks_t m_ticks = 0;
+ };
+
+#ifdef DOCTEST_CONFIG_NO_MULTITHREADING
+ template <typename T>
+ using Atomic = T;
+#else // DOCTEST_CONFIG_NO_MULTITHREADING
+ template <typename T>
+ using Atomic = std::atomic<T>;
+#endif // DOCTEST_CONFIG_NO_MULTITHREADING
+
+#if defined(DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS) || defined(DOCTEST_CONFIG_NO_MULTITHREADING)
+ template <typename T>
+ using MultiLaneAtomic = Atomic<T>;
+#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
+ // Provides a multilane implementation of an atomic variable that supports add, sub, load,
+ // store. Instead of using a single atomic variable, this splits up into multiple ones,
+ // each sitting on a separate cache line. The goal is to provide a speedup when most
+ // operations are modifying. It achieves this with two properties:
+ //
+ // * Multiple atomics are used, so chance of congestion from the same atomic is reduced.
+ // * Each atomic sits on a separate cache line, so false sharing is reduced.
+ //
+ // The disadvantage is that there is a small overhead due to the use of TLS, and load/store
+ // is slower because all atomics have to be accessed.
+ template <typename T>
+ class MultiLaneAtomic
+ {
+ struct CacheLineAlignedAtomic
+ {
+ Atomic<T> atomic{};
+ char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic<T>)];
+ };
+ CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES];
+
+ static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE,
+ "guarantee one atomic takes exactly one cache line");
+
+ public:
+ T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; }
+
+ T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); }
+
+ T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
+ return myAtomic().fetch_add(arg, order);
+ }
+
+ T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
+ return myAtomic().fetch_sub(arg, order);
+ }
+
+ operator T() const DOCTEST_NOEXCEPT { return load(); }
+
+ T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT {
+ auto result = T();
+ for(auto const& c : m_atomics) {
+ result += c.atomic.load(order);
+ }
+ return result;
+ }
+
+ T operator=(T desired) DOCTEST_NOEXCEPT { // lgtm [cpp/assignment-does-not-return-this]
+ store(desired);
+ return desired;
+ }
+
+ void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
+ // first value becomes desired", all others become 0.
+ for(auto& c : m_atomics) {
+ c.atomic.store(desired, order);
+ desired = {};
+ }
+ }
+
+ private:
+ // Each thread has a different atomic that it operates on. If more than NumLanes threads
+ // use this, some will use the same atomic. So performance will degrade a bit, but still
+ // everything will work.
+ //
+ // The logic here is a bit tricky. The call should be as fast as possible, so that there
+ // is minimal to no overhead in determining the correct atomic for the current thread.
+ //
+ // 1. A global static counter laneCounter counts continuously up.
+ // 2. Each successive thread will use modulo operation of that counter so it gets an atomic
+ // assigned in a round-robin fashion.
+ // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with
+ // little overhead.
+ Atomic<T>& myAtomic() DOCTEST_NOEXCEPT {
+ static Atomic<size_t> laneCounter;
+ DOCTEST_THREAD_LOCAL size_t tlsLaneIdx =
+ laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES;
+
+ return m_atomics[tlsLaneIdx].atomic;
+ }
+ };
+#endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
+
+ // this holds both parameters from the command line and runtime data for tests
+ struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats
+ {
+ MultiLaneAtomic<int> numAssertsCurrentTest_atomic;
+ MultiLaneAtomic<int> numAssertsFailedCurrentTest_atomic;
+
+ std::vector<std::vector<String>> filters = decltype(filters)(9); // 9 different filters
+
+ std::vector<IReporter*> reporters_currently_used;
+
+ assert_handler ah = nullptr;
+
+ Timer timer;
+
+ std::vector<String> stringifiedContexts; // logging from INFO() due to an exception
+
+ // stuff for subcases
+ bool reachedLeaf;
+ std::vector<SubcaseSignature> subcaseStack;
+ std::vector<SubcaseSignature> nextSubcaseStack;
+ std::unordered_set<unsigned long long> fullyTraversedSubcases;
+ size_t currentSubcaseDepth;
+ Atomic<bool> shouldLogCurrentException;
+
+ void resetRunData() {
+ numTestCases = 0;
+ numTestCasesPassingFilters = 0;
+ numTestSuitesPassingFilters = 0;
+ numTestCasesFailed = 0;
+ numAsserts = 0;
+ numAssertsFailed = 0;
+ numAssertsCurrentTest = 0;
+ numAssertsFailedCurrentTest = 0;
+ }
+
+ void finalizeTestCaseData() {
+ seconds = timer.getElapsedSeconds();
+
+ // update the non-atomic counters
+ numAsserts += numAssertsCurrentTest_atomic;
+ numAssertsFailed += numAssertsFailedCurrentTest_atomic;
+ numAssertsCurrentTest = numAssertsCurrentTest_atomic;
+ numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic;
+
+ if(numAssertsFailedCurrentTest)
+ failure_flags |= TestCaseFailureReason::AssertFailure;
+
+ if(Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 &&
+ Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout)
+ failure_flags |= TestCaseFailureReason::Timeout;
+
+ if(currentTest->m_should_fail) {
+ if(failure_flags) {
+ failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid;
+ } else {
+ failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt;
+ }
+ } else if(failure_flags && currentTest->m_may_fail) {
+ failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid;
+ } else if(currentTest->m_expected_failures > 0) {
+ if(numAssertsFailedCurrentTest == currentTest->m_expected_failures) {
+ failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes;
+ } else {
+ failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes;
+ }
+ }
+
+ bool ok_to_fail = (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) ||
+ (TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) ||
+ (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags);
+
+ // if any subcase has failed - the whole test case has failed
+ testCaseSuccess = !(failure_flags && !ok_to_fail);
+ if(!testCaseSuccess)
+ numTestCasesFailed++;
+ }
+ };
+
+ ContextState* g_cs = nullptr;
+
+ // used to avoid locks for the debug output
+ // TODO: figure out if this is indeed necessary/correct - seems like either there still
+ // could be a race or that there wouldn't be a race even if using the context directly
+ DOCTEST_THREAD_LOCAL bool g_no_colors;
+
+#endif // DOCTEST_CONFIG_DISABLE
+} // namespace detail
+
+char* String::allocate(size_type sz) {
+ if (sz <= last) {
+ buf[sz] = '\0';
+ setLast(last - sz);
+ return buf;
+ } else {
+ setOnHeap();
+ data.size = sz;
+ data.capacity = data.size + 1;
+ data.ptr = new char[data.capacity];
+ data.ptr[sz] = '\0';
+ return data.ptr;
+ }
+}
+
+void String::setOnHeap() noexcept { *reinterpret_cast<unsigned char*>(&buf[last]) = 128; }
+void String::setLast(size_type in) noexcept { buf[last] = char(in); }
+void String::setSize(size_type sz) noexcept {
+ if (isOnStack()) { buf[sz] = '\0'; setLast(last - sz); }
+ else { data.ptr[sz] = '\0'; data.size = sz; }
+}
+
+void String::copy(const String& other) {
+ if(other.isOnStack()) {
+ memcpy(buf, other.buf, len);
+ } else {
+ memcpy(allocate(other.data.size), other.data.ptr, other.data.size);
+ }
+}
+
+String::String() noexcept {
+ buf[0] = '\0';
+ setLast();
+}
+
+String::~String() {
+ if(!isOnStack())
+ delete[] data.ptr;
+} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
+
+String::String(const char* in)
+ : String(in, strlen(in)) {}
+
+String::String(const char* in, size_type in_size) {
+ memcpy(allocate(in_size), in, in_size);
+}
+
+String::String(std::istream& in, size_type in_size) {
+ in.read(allocate(in_size), in_size);
+}
+
+String::String(const String& other) { copy(other); }
+
+String& String::operator=(const String& other) {
+ if(this != &other) {
+ if(!isOnStack())
+ delete[] data.ptr;
+
+ copy(other);
+ }
+
+ return *this;
+}
+
+String& String::operator+=(const String& other) {
+ const size_type my_old_size = size();
+ const size_type other_size = other.size();
+ const size_type total_size = my_old_size + other_size;
+ if(isOnStack()) {
+ if(total_size < len) {
+ // append to the current stack space
+ memcpy(buf + my_old_size, other.c_str(), other_size + 1);
+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+ setLast(last - total_size);
+ } else {
+ // alloc new chunk
+ char* temp = new char[total_size + 1];
+ // copy current data to new location before writing in the union
+ memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed
+ // update data in union
+ setOnHeap();
+ data.size = total_size;
+ data.capacity = data.size + 1;
+ data.ptr = temp;
+ // transfer the rest of the data
+ memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1);
+ }
+ } else {
+ if(data.capacity > total_size) {
+ // append to the current heap block
+ data.size = total_size;
+ memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1);
+ } else {
+ // resize
+ data.capacity *= 2;
+ if(data.capacity <= total_size)
+ data.capacity = total_size + 1;
+ // alloc new chunk
+ char* temp = new char[data.capacity];
+ // copy current data to new location before releasing it
+ memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed
+ // release old chunk
+ delete[] data.ptr;
+ // update the rest of the union members
+ data.size = total_size;
+ data.ptr = temp;
+ // transfer the rest of the data
+ memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1);
+ }
+ }
+
+ return *this;
+}
+
+String::String(String&& other) noexcept {
+ memcpy(buf, other.buf, len);
+ other.buf[0] = '\0';
+ other.setLast();
+}
+
+String& String::operator=(String&& other) noexcept {
+ if(this != &other) {
+ if(!isOnStack())
+ delete[] data.ptr;
+ memcpy(buf, other.buf, len);
+ other.buf[0] = '\0';
+ other.setLast();
+ }
+ return *this;
+}
+
+char String::operator[](size_type i) const {
+ return const_cast<String*>(this)->operator[](i);
+}
+
+char& String::operator[](size_type i) {
+ if(isOnStack())
+ return reinterpret_cast<char*>(buf)[i];
+ return data.ptr[i];
+}
+
+DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized")
+String::size_type String::size() const {
+ if(isOnStack())
+ return last - (size_type(buf[last]) & 31); // using "last" would work only if "len" is 32
+ return data.size;
+}
+DOCTEST_GCC_SUPPRESS_WARNING_POP
+
+String::size_type String::capacity() const {
+ if(isOnStack())
+ return len;
+ return data.capacity;
+}
+
+String String::substr(size_type pos, size_type cnt) && {
+ cnt = std::min(cnt, size() - 1 - pos);
+ char* cptr = c_str();
+ memmove(cptr, cptr + pos, cnt);
+ setSize(cnt);
+ return std::move(*this);
+}
+
+String String::substr(size_type pos, size_type cnt) const & {
+ cnt = std::min(cnt, size() - 1 - pos);
+ return String{ c_str() + pos, cnt };
+}
+
+String::size_type String::find(char ch, size_type pos) const {
+ const char* begin = c_str();
+ const char* end = begin + size();
+ const char* it = begin + pos;
+ for (; it < end && *it != ch; it++);
+ if (it < end) { return static_cast<size_type>(it - begin); }
+ else { return npos; }
+}
+
+String::size_type String::rfind(char ch, size_type pos) const {
+ const char* begin = c_str();
+ const char* it = begin + std::min(pos, size() - 1);
+ for (; it >= begin && *it != ch; it--);
+ if (it >= begin) { return static_cast<size_type>(it - begin); }
+ else { return npos; }
+}
+
+int String::compare(const char* other, bool no_case) const {
+ if(no_case)
+ return doctest::stricmp(c_str(), other);
+ return std::strcmp(c_str(), other);
+}
+
+int String::compare(const String& other, bool no_case) const {
+ return compare(other.c_str(), no_case);
+}
+
+String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; }
+
+bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; }
+bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; }
+bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; }
+bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; }
+bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; }
+bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; }
+
+std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); }
+
+Contains::Contains(const String& str) : string(str) { }
+
+bool Contains::checkWith(const String& other) const {
+ return strstr(other.c_str(), string.c_str()) != nullptr;
+}
+
+String toString(const Contains& in) {
+ return "Contains( " + in.string + " )";
+}
+
+bool operator==(const String& lhs, const Contains& rhs) { return rhs.checkWith(lhs); }
+bool operator==(const Contains& lhs, const String& rhs) { return lhs.checkWith(rhs); }
+bool operator!=(const String& lhs, const Contains& rhs) { return !rhs.checkWith(lhs); }
+bool operator!=(const Contains& lhs, const String& rhs) { return !lhs.checkWith(rhs); }
+
+namespace {
+ void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;)
+} // namespace
+
+namespace Color {
+ std::ostream& operator<<(std::ostream& s, Color::Enum code) {
+ color_to_stream(s, code);
+ return s;
+ }
+} // namespace Color
+
+// clang-format off
+const char* assertString(assertType::Enum at) {
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitly handled
+ #define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type
+ #define DOCTEST_GENERATE_ASSERT_TYPE_CASES(assert_type) \
+ DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN_ ## assert_type); \
+ DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK_ ## assert_type); \
+ DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE_ ## assert_type)
+ switch(at) {
+ DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(FALSE);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_AS);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH_AS);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(NOTHROW);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(EQ);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(NE);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(GT);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(LT);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(GE);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(LE);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY_FALSE);
+
+ default: DOCTEST_INTERNAL_ERROR("Tried stringifying invalid assert type!");
+ }
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+}
+// clang-format on
+
+const char* failureString(assertType::Enum at) {
+ if(at & assertType::is_warn) //!OCLINT bitwise operator in conditional
+ return "WARNING";
+ if(at & assertType::is_check) //!OCLINT bitwise operator in conditional
+ return "ERROR";
+ if(at & assertType::is_require) //!OCLINT bitwise operator in conditional
+ return "FATAL ERROR";
+ return "";
+}
+
+DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference")
+DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference")
+// depending on the current options this will remove the path of filenames
+const char* skipPathFromFilename(const char* file) {
+#ifndef DOCTEST_CONFIG_DISABLE
+ if(getContextOptions()->no_path_in_filenames) {
+ auto back = std::strrchr(file, '\\');
+ auto forward = std::strrchr(file, '/');
+ if(back || forward) {
+ if(back > forward)
+ forward = back;
+ return forward + 1;
+ }
+ }
+#endif // DOCTEST_CONFIG_DISABLE
+ return file;
+}
+DOCTEST_CLANG_SUPPRESS_WARNING_POP
+DOCTEST_GCC_SUPPRESS_WARNING_POP
+
+bool SubcaseSignature::operator==(const SubcaseSignature& other) const {
+ return m_line == other.m_line
+ && std::strcmp(m_file, other.m_file) == 0
+ && m_name == other.m_name;
+}
+
+bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
+ if(m_line != other.m_line)
+ return m_line < other.m_line;
+ if(std::strcmp(m_file, other.m_file) != 0)
+ return std::strcmp(m_file, other.m_file) < 0;
+ return m_name.compare(other.m_name) < 0;
+}
+
+DOCTEST_DEFINE_INTERFACE(IContextScope)
+
+namespace detail {
+ void filldata<const void*>::fill(std::ostream* stream, const void* in) {
+ if (in) { *stream << in; }
+ else { *stream << "nullptr"; }
+ }
+
+ template <typename T>
+ String toStreamLit(T t) {
+ std::ostream* os = tlssPush();
+ os->operator<<(t);
+ return tlssPop();
+ }
+}
+
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; }
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
+String toString(const std::string& in) { return in.c_str(); }
+#endif // VS 2019
+
+String toString(String in) { return in; }
+
+String toString(std::nullptr_t) { return "nullptr"; }
+
+String toString(bool in) { return in ? "true" : "false"; }
+
+String toString(float in) { return toStreamLit(in); }
+String toString(double in) { return toStreamLit(in); }
+String toString(double long in) { return toStreamLit(in); }
+
+String toString(char in) { return toStreamLit(static_cast<signed>(in)); }
+String toString(char signed in) { return toStreamLit(static_cast<signed>(in)); }
+String toString(char unsigned in) { return toStreamLit(static_cast<unsigned>(in)); }
+String toString(short in) { return toStreamLit(in); }
+String toString(short unsigned in) { return toStreamLit(in); }
+String toString(signed in) { return toStreamLit(in); }
+String toString(unsigned in) { return toStreamLit(in); }
+String toString(long in) { return toStreamLit(in); }
+String toString(long unsigned in) { return toStreamLit(in); }
+String toString(long long in) { return toStreamLit(in); }
+String toString(long long unsigned in) { return toStreamLit(in); }
+
+Approx::Approx(double value)
+ : m_epsilon(static_cast<double>(std::numeric_limits<float>::epsilon()) * 100)
+ , m_scale(1.0)
+ , m_value(value) {}
+
+Approx Approx::operator()(double value) const {
+ Approx approx(value);
+ approx.epsilon(m_epsilon);
+ approx.scale(m_scale);
+ return approx;
+}
+
+Approx& Approx::epsilon(double newEpsilon) {
+ m_epsilon = newEpsilon;
+ return *this;
+}
+Approx& Approx::scale(double newScale) {
+ m_scale = newScale;
+ return *this;
+}
+
+bool operator==(double lhs, const Approx& rhs) {
+ // Thanks to Richard Harris for his help refining this formula
+ return std::fabs(lhs - rhs.m_value) <
+ rhs.m_epsilon * (rhs.m_scale + std::max<double>(std::fabs(lhs), std::fabs(rhs.m_value)));
+}
+bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); }
+bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); }
+bool operator!=(const Approx& lhs, double rhs) { return !operator==(rhs, lhs); }
+bool operator<=(double lhs, const Approx& rhs) { return lhs < rhs.m_value || lhs == rhs; }
+bool operator<=(const Approx& lhs, double rhs) { return lhs.m_value < rhs || lhs == rhs; }
+bool operator>=(double lhs, const Approx& rhs) { return lhs > rhs.m_value || lhs == rhs; }
+bool operator>=(const Approx& lhs, double rhs) { return lhs.m_value > rhs || lhs == rhs; }
+bool operator<(double lhs, const Approx& rhs) { return lhs < rhs.m_value && lhs != rhs; }
+bool operator<(const Approx& lhs, double rhs) { return lhs.m_value < rhs && lhs != rhs; }
+bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs != rhs; }
+bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; }
+
+String toString(const Approx& in) {
+ return "Approx( " + doctest::toString(in.m_value) + " )";
+}
+const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); }
+
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738)
+template <typename F>
+IsNaN<F>::operator bool() const {
+ return std::isnan(value) ^ flipped;
+}
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+template struct DOCTEST_INTERFACE_DEF IsNaN<float>;
+template struct DOCTEST_INTERFACE_DEF IsNaN<double>;
+template struct DOCTEST_INTERFACE_DEF IsNaN<long double>;
+template <typename F>
+String toString(IsNaN<F> in) { return String(in.flipped ? "! " : "") + "IsNaN( " + doctest::toString(in.value) + " )"; }
+String toString(IsNaN<float> in) { return toString<float>(in); }
+String toString(IsNaN<double> in) { return toString<double>(in); }
+String toString(IsNaN<double long> in) { return toString<double long>(in); }
+
+} // namespace doctest
+
+#ifdef DOCTEST_CONFIG_DISABLE
+namespace doctest {
+Context::Context(int, const char* const*) {}
+Context::~Context() = default;
+void Context::applyCommandLine(int, const char* const*) {}
+void Context::addFilter(const char*, const char*) {}
+void Context::clearFilters() {}
+void Context::setOption(const char*, bool) {}
+void Context::setOption(const char*, int) {}
+void Context::setOption(const char*, const char*) {}
+bool Context::shouldExit() { return false; }
+void Context::setAsDefaultForAssertsOutOfTestCases() {}
+void Context::setAssertHandler(detail::assert_handler) {}
+void Context::setCout(std::ostream*) {}
+int Context::run() { return 0; }
+
+int IReporter::get_num_active_contexts() { return 0; }
+const IContextScope* const* IReporter::get_active_contexts() { return nullptr; }
+int IReporter::get_num_stringified_contexts() { return 0; }
+const String* IReporter::get_stringified_contexts() { return nullptr; }
+
+int registerReporter(const char*, int, IReporter*) { return 0; }
+
+} // namespace doctest
+#else // DOCTEST_CONFIG_DISABLE
+
+#if !defined(DOCTEST_CONFIG_COLORS_NONE)
+#if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && !defined(DOCTEST_CONFIG_COLORS_ANSI)
+#ifdef DOCTEST_PLATFORM_WINDOWS
+#define DOCTEST_CONFIG_COLORS_WINDOWS
+#else // linux
+#define DOCTEST_CONFIG_COLORS_ANSI
+#endif // platform
+#endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI
+#endif // DOCTEST_CONFIG_COLORS_NONE
+
+namespace doctest_detail_test_suite_ns {
+// holds the current test suite
+doctest::detail::TestSuite& getCurrentTestSuite() {
+ static doctest::detail::TestSuite data{};
+ return data;
+}
+} // namespace doctest_detail_test_suite_ns
+
+namespace doctest {
+namespace {
+ // the int (priority) is part of the key for automatic sorting - sadly one can register a
+ // reporter with a duplicate name and a different priority but hopefully that won't happen often :|
+ using reporterMap = std::map<std::pair<int, String>, reporterCreatorFunc>;
+
+ reporterMap& getReporters() {
+ static reporterMap data;
+ return data;
+ }
+ reporterMap& getListeners() {
+ static reporterMap data;
+ return data;
+ }
+} // namespace
+namespace detail {
+#define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...) \
+ for(auto& curr_rep : g_cs->reporters_currently_used) \
+ curr_rep->function(__VA_ARGS__)
+
+ bool checkIfShouldThrow(assertType::Enum at) {
+ if(at & assertType::is_require) //!OCLINT bitwise operator in conditional
+ return true;
+
+ if((at & assertType::is_check) //!OCLINT bitwise operator in conditional
+ && getContextOptions()->abort_after > 0 &&
+ (g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >=
+ getContextOptions()->abort_after)
+ return true;
+
+ return false;
+ }
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ DOCTEST_NORETURN void throwException() {
+ g_cs->shouldLogCurrentException = false;
+ throw TestFailureException(); // NOLINT(hicpp-exception-baseclass)
+ }
+#else // DOCTEST_CONFIG_NO_EXCEPTIONS
+ void throwException() {}
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+} // namespace detail
+
+namespace {
+ using namespace detail;
+ // matching of a string against a wildcard mask (case sensitivity configurable) taken from
+ // https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing
+ int wildcmp(const char* str, const char* wild, bool caseSensitive) {
+ const char* cp = str;
+ const char* mp = wild;
+
+ while((*str) && (*wild != '*')) {
+ if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) &&
+ (*wild != '?')) {
+ return 0;
+ }
+ wild++;
+ str++;
+ }
+
+ while(*str) {
+ if(*wild == '*') {
+ if(!*++wild) {
+ return 1;
+ }
+ mp = wild;
+ cp = str + 1;
+ } else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) ||
+ (*wild == '?')) {
+ wild++;
+ str++;
+ } else {
+ wild = mp; //!OCLINT parameter reassignment
+ str = cp++; //!OCLINT parameter reassignment
+ }
+ }
+
+ while(*wild == '*') {
+ wild++;
+ }
+ return !*wild;
+ }
+
+ // checks if the name matches any of the filters (and can be configured what to do when empty)
+ bool matchesAny(const char* name, const std::vector<String>& filters, bool matchEmpty,
+ bool caseSensitive) {
+ if (filters.empty() && matchEmpty)
+ return true;
+ for (auto& curr : filters)
+ if (wildcmp(name, curr.c_str(), caseSensitive))
+ return true;
+ return false;
+ }
+
+ DOCTEST_NO_SANITIZE_INTEGER
+ unsigned long long hash(unsigned long long a, unsigned long long b) {
+ return (a << 5) + b;
+ }
+
+ // C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html
+ DOCTEST_NO_SANITIZE_INTEGER
+ unsigned long long hash(const char* str) {
+ unsigned long long hash = 5381;
+ char c;
+ while ((c = *str++))
+ hash = ((hash << 5) + hash) + c; // hash * 33 + c
+ return hash;
+ }
+
+ unsigned long long hash(const SubcaseSignature& sig) {
+ return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line);
+ }
+
+ unsigned long long hash(const std::vector<SubcaseSignature>& sigs, size_t count) {
+ unsigned long long running = 0;
+ auto end = sigs.begin() + count;
+ for (auto it = sigs.begin(); it != end; it++) {
+ running = hash(running, hash(*it));
+ }
+ return running;
+ }
+
+ unsigned long long hash(const std::vector<SubcaseSignature>& sigs) {
+ unsigned long long running = 0;
+ for (const SubcaseSignature& sig : sigs) {
+ running = hash(running, hash(sig));
+ }
+ return running;
+ }
+} // namespace
+namespace detail {
+ bool Subcase::checkFilters() {
+ if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) {
+ if (!matchesAny(m_signature.m_name.c_str(), g_cs->filters[6], true, g_cs->case_sensitive))
+ return true;
+ if (matchesAny(m_signature.m_name.c_str(), g_cs->filters[7], false, g_cs->case_sensitive))
+ return true;
+ }
+ return false;
+ }
+
+ Subcase::Subcase(const String& name, const char* file, int line)
+ : m_signature({name, file, line}) {
+ if (!g_cs->reachedLeaf) {
+ if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size()
+ || g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) {
+ // Going down.
+ if (checkFilters()) { return; }
+
+ g_cs->subcaseStack.push_back(m_signature);
+ g_cs->currentSubcaseDepth++;
+ m_entered = true;
+ DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
+ }
+ } else {
+ if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) {
+ // This subcase is reentered via control flow.
+ g_cs->currentSubcaseDepth++;
+ m_entered = true;
+ DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
+ } else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth
+ && g_cs->fullyTraversedSubcases.find(hash(hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), hash(m_signature)))
+ == g_cs->fullyTraversedSubcases.end()) {
+ if (checkFilters()) { return; }
+ // This subcase is part of the one to be executed next.
+ g_cs->nextSubcaseStack.clear();
+ g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(),
+ g_cs->subcaseStack.begin(), g_cs->subcaseStack.begin() + g_cs->currentSubcaseDepth);
+ g_cs->nextSubcaseStack.push_back(m_signature);
+ }
+ }
+ }
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+
+ Subcase::~Subcase() {
+ if (m_entered) {
+ g_cs->currentSubcaseDepth--;
+
+ if (!g_cs->reachedLeaf) {
+ // Leaf.
+ g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack));
+ g_cs->nextSubcaseStack.clear();
+ g_cs->reachedLeaf = true;
+ } else if (g_cs->nextSubcaseStack.empty()) {
+ // All children are finished.
+ g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack));
+ }
+
+#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
+ if(std::uncaught_exceptions() > 0
+#else
+ if(std::uncaught_exception()
+#endif
+ && g_cs->shouldLogCurrentException) {
+ DOCTEST_ITERATE_THROUGH_REPORTERS(
+ test_case_exception, {"exception thrown in subcase - will translate later "
+ "when the whole test case has been exited (cannot "
+ "translate while there is an active exception)",
+ false});
+ g_cs->shouldLogCurrentException = false;
+ }
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
+ }
+ }
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ Subcase::operator bool() const { return m_entered; }
+
+ Result::Result(bool passed, const String& decomposition)
+ : m_passed(passed)
+ , m_decomp(decomposition) {}
+
+ ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at)
+ : m_at(at) {}
+
+ TestSuite& TestSuite::operator*(const char* in) {
+ m_test_suite = in;
+ return *this;
+ }
+
+ TestCase::TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
+ const String& type, int template_id) {
+ m_file = file;
+ m_line = line;
+ m_name = nullptr; // will be later overridden in operator*
+ m_test_suite = test_suite.m_test_suite;
+ m_description = test_suite.m_description;
+ m_skip = test_suite.m_skip;
+ m_no_breaks = test_suite.m_no_breaks;
+ m_no_output = test_suite.m_no_output;
+ m_may_fail = test_suite.m_may_fail;
+ m_should_fail = test_suite.m_should_fail;
+ m_expected_failures = test_suite.m_expected_failures;
+ m_timeout = test_suite.m_timeout;
+
+ m_test = test;
+ m_type = type;
+ m_template_id = template_id;
+ }
+
+ TestCase::TestCase(const TestCase& other)
+ : TestCaseData() {
+ *this = other;
+ }
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
+ TestCase& TestCase::operator=(const TestCase& other) {
+ TestCaseData::operator=(other);
+ m_test = other.m_test;
+ m_type = other.m_type;
+ m_template_id = other.m_template_id;
+ m_full_name = other.m_full_name;
+
+ if(m_template_id != -1)
+ m_name = m_full_name.c_str();
+ return *this;
+ }
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ TestCase& TestCase::operator*(const char* in) {
+ m_name = in;
+ // make a new name with an appended type for templated test case
+ if(m_template_id != -1) {
+ m_full_name = String(m_name) + "<" + m_type + ">";
+ // redirect the name to point to the newly constructed full name
+ m_name = m_full_name.c_str();
+ }
+ return *this;
+ }
+
+ bool TestCase::operator<(const TestCase& other) const {
+ // this will be used only to differentiate between test cases - not relevant for sorting
+ if(m_line != other.m_line)
+ return m_line < other.m_line;
+ const int name_cmp = strcmp(m_name, other.m_name);
+ if(name_cmp != 0)
+ return name_cmp < 0;
+ const int file_cmp = m_file.compare(other.m_file);
+ if(file_cmp != 0)
+ return file_cmp < 0;
+ return m_template_id < other.m_template_id;
+ }
+
+ // all the registered tests
+ std::set<TestCase>& getRegisteredTests() {
+ static std::set<TestCase> data;
+ return data;
+ }
+} // namespace detail
+namespace {
+ using namespace detail;
+ // for sorting tests by file/line
+ bool fileOrderComparator(const TestCase* lhs, const TestCase* rhs) {
+ // this is needed because MSVC gives different case for drive letters
+ // for __FILE__ when evaluated in a header and a source file
+ const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC));
+ if(res != 0)
+ return res < 0;
+ if(lhs->m_line != rhs->m_line)
+ return lhs->m_line < rhs->m_line;
+ return lhs->m_template_id < rhs->m_template_id;
+ }
+
+ // for sorting tests by suite/file/line
+ bool suiteOrderComparator(const TestCase* lhs, const TestCase* rhs) {
+ const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite);
+ if(res != 0)
+ return res < 0;
+ return fileOrderComparator(lhs, rhs);
+ }
+
+ // for sorting tests by name/suite/file/line
+ bool nameOrderComparator(const TestCase* lhs, const TestCase* rhs) {
+ const int res = std::strcmp(lhs->m_name, rhs->m_name);
+ if(res != 0)
+ return res < 0;
+ return suiteOrderComparator(lhs, rhs);
+ }
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+ void color_to_stream(std::ostream& s, Color::Enum code) {
+ static_cast<void>(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS
+ static_cast<void>(code); // for DOCTEST_CONFIG_COLORS_NONE
+#ifdef DOCTEST_CONFIG_COLORS_ANSI
+ if(g_no_colors ||
+ (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false))
+ return;
+
+ auto col = "";
+ // clang-format off
+ switch(code) { //!OCLINT missing break in switch statement / unnecessary default statement in covered switch statement
+ case Color::Red: col = "[0;31m"; break;
+ case Color::Green: col = "[0;32m"; break;
+ case Color::Blue: col = "[0;34m"; break;
+ case Color::Cyan: col = "[0;36m"; break;
+ case Color::Yellow: col = "[0;33m"; break;
+ case Color::Grey: col = "[1;30m"; break;
+ case Color::LightGrey: col = "[0;37m"; break;
+ case Color::BrightRed: col = "[1;31m"; break;
+ case Color::BrightGreen: col = "[1;32m"; break;
+ case Color::BrightWhite: col = "[1;37m"; break;
+ case Color::Bright: // invalid
+ case Color::None:
+ case Color::White:
+ default: col = "[0m";
+ }
+ // clang-format on
+ s << "\033" << col;
+#endif // DOCTEST_CONFIG_COLORS_ANSI
+
+#ifdef DOCTEST_CONFIG_COLORS_WINDOWS
+ if(g_no_colors ||
+ (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false))
+ return;
+
+ static struct ConsoleHelper {
+ HANDLE stdoutHandle;
+ WORD origFgAttrs;
+ WORD origBgAttrs;
+
+ ConsoleHelper() {
+ stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
+ GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo);
+ origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED |
+ BACKGROUND_BLUE | BACKGROUND_INTENSITY);
+ origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED |
+ FOREGROUND_BLUE | FOREGROUND_INTENSITY);
+ }
+ } ch;
+
+#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs)
+
+ // clang-format off
+ switch (code) {
+ case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
+ case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break;
+ case Color::Green: DOCTEST_SET_ATTR(FOREGROUND_GREEN); break;
+ case Color::Blue: DOCTEST_SET_ATTR(FOREGROUND_BLUE); break;
+ case Color::Cyan: DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN); break;
+ case Color::Yellow: DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN); break;
+ case Color::Grey: DOCTEST_SET_ATTR(0); break;
+ case Color::LightGrey: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY); break;
+ case Color::BrightRed: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED); break;
+ case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN); break;
+ case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
+ case Color::None:
+ case Color::Bright: // invalid
+ default: DOCTEST_SET_ATTR(ch.origFgAttrs);
+ }
+ // clang-format on
+#endif // DOCTEST_CONFIG_COLORS_WINDOWS
+ }
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+
+ std::vector<const IExceptionTranslator*>& getExceptionTranslators() {
+ static std::vector<const IExceptionTranslator*> data;
+ return data;
+ }
+
+ String translateActiveException() {
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ String res;
+ auto& translators = getExceptionTranslators();
+ for(auto& curr : translators)
+ if(curr->translate(res))
+ return res;
+ // clang-format off
+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcatch-value")
+ try {
+ throw;
+ } catch(std::exception& ex) {
+ return ex.what();
+ } catch(std::string& msg) {
+ return msg.c_str();
+ } catch(const char* msg) {
+ return msg;
+ } catch(...) {
+ return "unknown exception";
+ }
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
+// clang-format on
+#else // DOCTEST_CONFIG_NO_EXCEPTIONS
+ return "";
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ }
+} // namespace
+
+namespace detail {
+ // used by the macros for registering tests
+ int regTest(const TestCase& tc) {
+ getRegisteredTests().insert(tc);
+ return 0;
+ }
+
+ // sets the current test suite
+ int setTestSuite(const TestSuite& ts) {
+ doctest_detail_test_suite_ns::getCurrentTestSuite() = ts;
+ return 0;
+ }
+
+#ifdef DOCTEST_IS_DEBUGGER_ACTIVE
+ bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); }
+#else // DOCTEST_IS_DEBUGGER_ACTIVE
+#ifdef DOCTEST_PLATFORM_LINUX
+ class ErrnoGuard {
+ public:
+ ErrnoGuard() : m_oldErrno(errno) {}
+ ~ErrnoGuard() { errno = m_oldErrno; }
+ private:
+ int m_oldErrno;
+ };
+ // See the comments in Catch2 for the reasoning behind this implementation:
+ // https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102
+ bool isDebuggerActive() {
+ ErrnoGuard guard;
+ std::ifstream in("/proc/self/status");
+ for(std::string line; std::getline(in, line);) {
+ static const int PREFIX_LEN = 11;
+ if(line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) {
+ return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
+ }
+ }
+ return false;
+ }
+#elif defined(DOCTEST_PLATFORM_MAC)
+ // The following function is taken directly from the following technical note:
+ // https://developer.apple.com/library/archive/qa/qa1361/_index.html
+ // Returns true if the current process is being debugged (either
+ // running under the debugger or has a debugger attached post facto).
+ bool isDebuggerActive() {
+ int mib[4];
+ kinfo_proc info;
+ size_t size;
+ // Initialize the flags so that, if sysctl fails for some bizarre
+ // reason, we get a predictable result.
+ info.kp_proc.p_flag = 0;
+ // Initialize mib, which tells sysctl the info we want, in this case
+ // we're looking for information about a specific process ID.
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = getpid();
+ // Call sysctl.
+ size = sizeof(info);
+ if(sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) {
+ std::cerr << "\nCall to sysctl failed - unable to determine if debugger is active **\n";
+ return false;
+ }
+ // We're being debugged if the P_TRACED flag is set.
+ return ((info.kp_proc.p_flag & P_TRACED) != 0);
+ }
+#elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__)
+ bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; }
+#else
+ bool isDebuggerActive() { return false; }
+#endif // Platform
+#endif // DOCTEST_IS_DEBUGGER_ACTIVE
+
+ void registerExceptionTranslatorImpl(const IExceptionTranslator* et) {
+ if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) ==
+ getExceptionTranslators().end())
+ getExceptionTranslators().push_back(et);
+ }
+
+ DOCTEST_THREAD_LOCAL std::vector<IContextScope*> g_infoContexts; // for logging with INFO()
+
+ ContextScopeBase::ContextScopeBase() {
+ g_infoContexts.push_back(this);
+ }
+
+ ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) noexcept {
+ if (other.need_to_destroy) {
+ other.destroy();
+ }
+ other.need_to_destroy = false;
+ g_infoContexts.push_back(this);
+ }
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+
+ // destroy cannot be inlined into the destructor because that would mean calling stringify after
+ // ContextScope has been destroyed (base class destructors run after derived class destructors).
+ // Instead, ContextScope calls this method directly from its destructor.
+ void ContextScopeBase::destroy() {
+#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
+ if(std::uncaught_exceptions() > 0) {
+#else
+ if(std::uncaught_exception()) {
+#endif
+ std::ostringstream s;
+ this->stringify(&s);
+ g_cs->stringifiedContexts.push_back(s.str().c_str());
+ }
+ g_infoContexts.pop_back();
+ }
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+} // namespace detail
+namespace {
+ using namespace detail;
+
+#if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
+ struct FatalConditionHandler
+ {
+ static void reset() {}
+ static void allocateAltStackMem() {}
+ static void freeAltStackMem() {}
+ };
+#else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
+
+ void reportFatal(const std::string&);
+
+#ifdef DOCTEST_PLATFORM_WINDOWS
+
+ struct SignalDefs
+ {
+ DWORD id;
+ const char* name;
+ };
+ // There is no 1-1 mapping between signals and windows exceptions.
+ // Windows can easily distinguish between SO and SigSegV,
+ // but SigInt, SigTerm, etc are handled differently.
+ SignalDefs signalDefs[] = {
+ {static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION),
+ "SIGILL - Illegal instruction signal"},
+ {static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"},
+ {static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION),
+ "SIGSEGV - Segmentation violation signal"},
+ {static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"},
+ };
+
+ struct FatalConditionHandler
+ {
+ static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) {
+ // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the
+ // console just once no matter how many threads have crashed.
+ DOCTEST_DECLARE_STATIC_MUTEX(mutex)
+ static bool execute = true;
+ {
+ DOCTEST_LOCK_MUTEX(mutex)
+ if(execute) {
+ bool reported = false;
+ for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
+ if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
+ reportFatal(signalDefs[i].name);
+ reported = true;
+ break;
+ }
+ }
+ if(reported == false)
+ reportFatal("Unhandled SEH exception caught");
+ if(isDebuggerActive() && !g_cs->no_breaks)
+ DOCTEST_BREAK_INTO_DEBUGGER();
+ }
+ execute = false;
+ }
+ std::exit(EXIT_FAILURE);
+ }
+
+ static void allocateAltStackMem() {}
+ static void freeAltStackMem() {}
+
+ FatalConditionHandler() {
+ isSet = true;
+ // 32k seems enough for doctest to handle stack overflow,
+ // but the value was found experimentally, so there is no strong guarantee
+ guaranteeSize = 32 * 1024;
+ // Register an unhandled exception filter
+ previousTop = SetUnhandledExceptionFilter(handleException);
+ // Pass in guarantee size to be filled
+ SetThreadStackGuarantee(&guaranteeSize);
+
+ // On Windows uncaught exceptions from another thread, exceptions from
+ // destructors, or calls to std::terminate are not a SEH exception
+
+ // The terminal handler gets called when:
+ // - std::terminate is called FROM THE TEST RUNNER THREAD
+ // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD
+ original_terminate_handler = std::get_terminate();
+ std::set_terminate([]() DOCTEST_NOEXCEPT {
+ reportFatal("Terminate handler called");
+ if(isDebuggerActive() && !g_cs->no_breaks)
+ DOCTEST_BREAK_INTO_DEBUGGER();
+ std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well
+ });
+
+ // SIGABRT is raised when:
+ // - std::terminate is called FROM A DIFFERENT THREAD
+ // - an exception is thrown from a destructor FROM A DIFFERENT THREAD
+ // - an uncaught exception is thrown FROM A DIFFERENT THREAD
+ prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT {
+ if(signal == SIGABRT) {
+ reportFatal("SIGABRT - Abort (abnormal termination) signal");
+ if(isDebuggerActive() && !g_cs->no_breaks)
+ DOCTEST_BREAK_INTO_DEBUGGER();
+ std::exit(EXIT_FAILURE);
+ }
+ });
+
+ // The following settings are taken from google test, and more
+ // specifically from UnitTest::Run() inside of gtest.cc
+
+ // the user does not want to see pop-up dialogs about crashes
+ prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
+ SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+ // This forces the abort message to go to stderr in all circumstances.
+ prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR);
+ // In the debug version, Visual Studio pops up a separate dialog
+ // offering a choice to debug the aborted program - we want to disable that.
+ prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
+ // In debug mode, the Windows CRT can crash with an assertion over invalid
+ // input (e.g. passing an invalid file descriptor). The default handling
+ // for these assertions is to pop up a dialog and wait for user input.
+ // Instead ask the CRT to dump such assertions to stderr non-interactively.
+ prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+ }
+
+ static void reset() {
+ if(isSet) {
+ // Unregister handler and restore the old guarantee
+ SetUnhandledExceptionFilter(previousTop);
+ SetThreadStackGuarantee(&guaranteeSize);
+ std::set_terminate(original_terminate_handler);
+ std::signal(SIGABRT, prev_sigabrt_handler);
+ SetErrorMode(prev_error_mode_1);
+ _set_error_mode(prev_error_mode_2);
+ _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
+ static_cast<void>(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode));
+ static_cast<void>(_CrtSetReportFile(_CRT_ASSERT, prev_report_file));
+ isSet = false;
+ }
+ }
+
+ ~FatalConditionHandler() { reset(); }
+
+ private:
+ static UINT prev_error_mode_1;
+ static int prev_error_mode_2;
+ static unsigned int prev_abort_behavior;
+ static int prev_report_mode;
+ static _HFILE prev_report_file;
+ static void (DOCTEST_CDECL *prev_sigabrt_handler)(int);
+ static std::terminate_handler original_terminate_handler;
+ static bool isSet;
+ static ULONG guaranteeSize;
+ static LPTOP_LEVEL_EXCEPTION_FILTER previousTop;
+ };
+
+ UINT FatalConditionHandler::prev_error_mode_1;
+ int FatalConditionHandler::prev_error_mode_2;
+ unsigned int FatalConditionHandler::prev_abort_behavior;
+ int FatalConditionHandler::prev_report_mode;
+ _HFILE FatalConditionHandler::prev_report_file;
+ void (DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int);
+ std::terminate_handler FatalConditionHandler::original_terminate_handler;
+ bool FatalConditionHandler::isSet = false;
+ ULONG FatalConditionHandler::guaranteeSize = 0;
+ LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr;
+
+#else // DOCTEST_PLATFORM_WINDOWS
+
+ struct SignalDefs
+ {
+ int id;
+ const char* name;
+ };
+ SignalDefs signalDefs[] = {{SIGINT, "SIGINT - Terminal interrupt signal"},
+ {SIGILL, "SIGILL - Illegal instruction signal"},
+ {SIGFPE, "SIGFPE - Floating point error signal"},
+ {SIGSEGV, "SIGSEGV - Segmentation violation signal"},
+ {SIGTERM, "SIGTERM - Termination request signal"},
+ {SIGABRT, "SIGABRT - Abort (abnormal termination) signal"}};
+
+ struct FatalConditionHandler
+ {
+ static bool isSet;
+ static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)];
+ static stack_t oldSigStack;
+ static size_t altStackSize;
+ static char* altStackMem;
+
+ static void handleSignal(int sig) {
+ const char* name = "<unknown signal>";
+ for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
+ SignalDefs& def = signalDefs[i];
+ if(sig == def.id) {
+ name = def.name;
+ break;
+ }
+ }
+ reset();
+ reportFatal(name);
+ raise(sig);
+ }
+
+ static void allocateAltStackMem() {
+ altStackMem = new char[altStackSize];
+ }
+
+ static void freeAltStackMem() {
+ delete[] altStackMem;
+ }
+
+ FatalConditionHandler() {
+ isSet = true;
+ stack_t sigStack;
+ sigStack.ss_sp = altStackMem;
+ sigStack.ss_size = altStackSize;
+ sigStack.ss_flags = 0;
+ sigaltstack(&sigStack, &oldSigStack);
+ struct sigaction sa = {};
+ sa.sa_handler = handleSignal;
+ sa.sa_flags = SA_ONSTACK;
+ for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
+ sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
+ }
+ }
+
+ ~FatalConditionHandler() { reset(); }
+ static void reset() {
+ if(isSet) {
+ // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
+ for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
+ sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
+ }
+ // Return the old stack
+ sigaltstack(&oldSigStack, nullptr);
+ isSet = false;
+ }
+ }
+ };
+
+ bool FatalConditionHandler::isSet = false;
+ struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {};
+ stack_t FatalConditionHandler::oldSigStack = {};
+ size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ;
+ char* FatalConditionHandler::altStackMem = nullptr;
+
+#endif // DOCTEST_PLATFORM_WINDOWS
+#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
+
+} // namespace
+
+namespace {
+ using namespace detail;
+
+#ifdef DOCTEST_PLATFORM_WINDOWS
+#define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text)
+#else
+ // TODO: integration with XCode and other IDEs
+#define DOCTEST_OUTPUT_DEBUG_STRING(text)
+#endif // Platform
+
+ void addAssert(assertType::Enum at) {
+ if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional
+ g_cs->numAssertsCurrentTest_atomic++;
+ }
+
+ void addFailedAssert(assertType::Enum at) {
+ if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional
+ g_cs->numAssertsFailedCurrentTest_atomic++;
+ }
+
+#if defined(DOCTEST_CONFIG_POSIX_SIGNALS) || defined(DOCTEST_CONFIG_WINDOWS_SEH)
+ void reportFatal(const std::string& message) {
+ g_cs->failure_flags |= TestCaseFailureReason::Crash;
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true});
+
+ while (g_cs->subcaseStack.size()) {
+ g_cs->subcaseStack.pop_back();
+ DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
+ }
+
+ g_cs->finalizeTestCaseData();
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs);
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs);
+ }
+#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
+} // namespace
+
+AssertData::AssertData(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const StringContains& exception_string)
+ : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr),
+ m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type),
+ m_exception_string(exception_string) {
+#if DOCTEST_MSVC
+ if (m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC
+ ++m_expr;
+#endif // MSVC
+}
+
+namespace detail {
+ ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const String& exception_string)
+ : AssertData(at, file, line, expr, exception_type, exception_string) { }
+
+ ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const Contains& exception_string)
+ : AssertData(at, file, line, expr, exception_type, exception_string) { }
+
+ void ResultBuilder::setResult(const Result& res) {
+ m_decomp = res.m_decomp;
+ m_failed = !res.m_passed;
+ }
+
+ void ResultBuilder::translateException() {
+ m_threw = true;
+ m_exception = translateActiveException();
+ }
+
+ bool ResultBuilder::log() {
+ if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
+ m_failed = !m_threw;
+ } else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT
+ m_failed = !m_threw_as || !m_exception_string.check(m_exception);
+ } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
+ m_failed = !m_threw_as;
+ } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
+ m_failed = !m_exception_string.check(m_exception);
+ } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
+ m_failed = m_threw;
+ }
+
+ if(m_exception.size())
+ m_exception = "\"" + m_exception + "\"";
+
+ if(is_running_in_test) {
+ addAssert(m_at);
+ DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this);
+
+ if(m_failed)
+ addFailedAssert(m_at);
+ } else if(m_failed) {
+ failed_out_of_a_testing_context(*this);
+ }
+
+ return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks &&
+ (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger
+ }
+
+ void ResultBuilder::react() const {
+ if(m_failed && checkIfShouldThrow(m_at))
+ throwException();
+ }
+
+ void failed_out_of_a_testing_context(const AssertData& ad) {
+ if(g_cs->ah)
+ g_cs->ah(ad);
+ else
+ std::abort();
+ }
+
+ bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr,
+ const Result& result) {
+ bool failed = !result.m_passed;
+
+ // ###################################################################################
+ // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
+ // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
+ // ###################################################################################
+ DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp);
+ DOCTEST_ASSERT_IN_TESTS(result.m_decomp);
+ return !failed;
+ }
+
+ MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) {
+ m_stream = tlssPush();
+ m_file = file;
+ m_line = line;
+ m_severity = severity;
+ }
+
+ MessageBuilder::~MessageBuilder() {
+ if (!logged)
+ tlssPop();
+ }
+
+ DOCTEST_DEFINE_INTERFACE(IExceptionTranslator)
+
+ bool MessageBuilder::log() {
+ if (!logged) {
+ m_string = tlssPop();
+ logged = true;
+ }
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this);
+
+ const bool isWarn = m_severity & assertType::is_warn;
+
+ // warn is just a message in this context so we don't treat it as an assert
+ if(!isWarn) {
+ addAssert(m_severity);
+ addFailedAssert(m_severity);
+ }
+
+ return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn &&
+ (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger
+ }
+
+ void MessageBuilder::react() {
+ if(m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional
+ throwException();
+ }
+} // namespace detail
+namespace {
+ using namespace detail;
+
+ // clang-format off
+
+// =================================================================================================
+// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp
+// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched.
+// =================================================================================================
+
+ class XmlEncode {
+ public:
+ enum ForWhat { ForTextNodes, ForAttributes };
+
+ XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes );
+
+ void encodeTo( std::ostream& os ) const;
+
+ friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
+
+ private:
+ std::string m_str;
+ ForWhat m_forWhat;
+ };
+
+ class XmlWriter {
+ public:
+
+ class ScopedElement {
+ public:
+ ScopedElement( XmlWriter* writer );
+
+ ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT;
+ ScopedElement& operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT;
+
+ ~ScopedElement();
+
+ ScopedElement& writeText( std::string const& text, bool indent = true );
+
+ template<typename T>
+ ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
+ m_writer->writeAttribute( name, attribute );
+ return *this;
+ }
+
+ private:
+ mutable XmlWriter* m_writer = nullptr;
+ };
+
+#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+ XmlWriter( std::ostream& os = std::cout );
+#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+ XmlWriter( std::ostream& os );
+#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+ ~XmlWriter();
+
+ XmlWriter( XmlWriter const& ) = delete;
+ XmlWriter& operator=( XmlWriter const& ) = delete;
+
+ XmlWriter& startElement( std::string const& name );
+
+ ScopedElement scopedElement( std::string const& name );
+
+ XmlWriter& endElement();
+
+ XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );
+
+ XmlWriter& writeAttribute( std::string const& name, const char* attribute );
+
+ XmlWriter& writeAttribute( std::string const& name, bool attribute );
+
+ template<typename T>
+ XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
+ std::stringstream rss;
+ rss << attribute;
+ return writeAttribute( name, rss.str() );
+ }
+
+ XmlWriter& writeText( std::string const& text, bool indent = true );
+
+ //XmlWriter& writeComment( std::string const& text );
+
+ //void writeStylesheetRef( std::string const& url );
+
+ //XmlWriter& writeBlankLine();
+
+ void ensureTagClosed();
+
+ void writeDeclaration();
+
+ private:
+
+ void newlineIfNecessary();
+
+ bool m_tagIsOpen = false;
+ bool m_needsNewline = false;
+ std::vector<std::string> m_tags;
+ std::string m_indent;
+ std::ostream& m_os;
+ };
+
+// =================================================================================================
+// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp
+// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched.
+// =================================================================================================
+
+using uchar = unsigned char;
+
+namespace {
+
+ size_t trailingBytes(unsigned char c) {
+ if ((c & 0xE0) == 0xC0) {
+ return 2;
+ }
+ if ((c & 0xF0) == 0xE0) {
+ return 3;
+ }
+ if ((c & 0xF8) == 0xF0) {
+ return 4;
+ }
+ DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
+ }
+
+ uint32_t headerValue(unsigned char c) {
+ if ((c & 0xE0) == 0xC0) {
+ return c & 0x1F;
+ }
+ if ((c & 0xF0) == 0xE0) {
+ return c & 0x0F;
+ }
+ if ((c & 0xF8) == 0xF0) {
+ return c & 0x07;
+ }
+ DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
+ }
+
+ void hexEscapeChar(std::ostream& os, unsigned char c) {
+ std::ios_base::fmtflags f(os.flags());
+ os << "\\x"
+ << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
+ << static_cast<int>(c);
+ os.flags(f);
+ }
+
+} // anonymous namespace
+
+ XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
+ : m_str( str ),
+ m_forWhat( forWhat )
+ {}
+
+ void XmlEncode::encodeTo( std::ostream& os ) const {
+ // Apostrophe escaping not necessary if we always use " to write attributes
+ // (see: https://www.w3.org/TR/xml/#syntax)
+
+ for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
+ uchar c = m_str[idx];
+ switch (c) {
+ case '<': os << "&lt;"; break;
+ case '&': os << "&amp;"; break;
+
+ case '>':
+ // See: https://www.w3.org/TR/xml/#syntax
+ if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
+ os << "&gt;";
+ else
+ os << c;
+ break;
+
+ case '\"':
+ if (m_forWhat == ForAttributes)
+ os << "&quot;";
+ else
+ os << c;
+ break;
+
+ default:
+ // Check for control characters and invalid utf-8
+
+ // Escape control characters in standard ascii
+ // see https://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
+ if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
+ hexEscapeChar(os, c);
+ break;
+ }
+
+ // Plain ASCII: Write it to stream
+ if (c < 0x7F) {
+ os << c;
+ break;
+ }
+
+ // UTF-8 territory
+ // Check if the encoding is valid and if it is not, hex escape bytes.
+ // Important: We do not check the exact decoded values for validity, only the encoding format
+ // First check that this bytes is a valid lead byte:
+ // This means that it is not encoded as 1111 1XXX
+ // Or as 10XX XXXX
+ if (c < 0xC0 ||
+ c >= 0xF8) {
+ hexEscapeChar(os, c);
+ break;
+ }
+
+ auto encBytes = trailingBytes(c);
+ // Are there enough bytes left to avoid accessing out-of-bounds memory?
+ if (idx + encBytes - 1 >= m_str.size()) {
+ hexEscapeChar(os, c);
+ break;
+ }
+ // The header is valid, check data
+ // The next encBytes bytes must together be a valid utf-8
+ // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
+ bool valid = true;
+ uint32_t value = headerValue(c);
+ for (std::size_t n = 1; n < encBytes; ++n) {
+ uchar nc = m_str[idx + n];
+ valid &= ((nc & 0xC0) == 0x80);
+ value = (value << 6) | (nc & 0x3F);
+ }
+
+ if (
+ // Wrong bit pattern of following bytes
+ (!valid) ||
+ // Overlong encodings
+ (value < 0x80) ||
+ ( value < 0x800 && encBytes > 2) || // removed "0x80 <= value &&" because redundant
+ (0x800 < value && value < 0x10000 && encBytes > 3) ||
+ // Encoded value out of range
+ (value >= 0x110000)
+ ) {
+ hexEscapeChar(os, c);
+ break;
+ }
+
+ // If we got here, this is in fact a valid(ish) utf-8 sequence
+ for (std::size_t n = 0; n < encBytes; ++n) {
+ os << m_str[idx + n];
+ }
+ idx += encBytes - 1;
+ break;
+ }
+ }
+ }
+
+ std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
+ xmlEncode.encodeTo( os );
+ return os;
+ }
+
+ XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
+ : m_writer( writer )
+ {}
+
+ XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT
+ : m_writer( other.m_writer ){
+ other.m_writer = nullptr;
+ }
+ XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT {
+ if ( m_writer ) {
+ m_writer->endElement();
+ }
+ m_writer = other.m_writer;
+ other.m_writer = nullptr;
+ return *this;
+ }
+
+
+ XmlWriter::ScopedElement::~ScopedElement() {
+ if( m_writer )
+ m_writer->endElement();
+ }
+
+ XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) {
+ m_writer->writeText( text, indent );
+ return *this;
+ }
+
+ XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
+ {
+ // writeDeclaration(); // called explicitly by the reporters that use the writer class - see issue #627
+ }
+
+ XmlWriter::~XmlWriter() {
+ while( !m_tags.empty() )
+ endElement();
+ }
+
+ XmlWriter& XmlWriter::startElement( std::string const& name ) {
+ ensureTagClosed();
+ newlineIfNecessary();
+ m_os << m_indent << '<' << name;
+ m_tags.push_back( name );
+ m_indent += " ";
+ m_tagIsOpen = true;
+ return *this;
+ }
+
+ XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) {
+ ScopedElement scoped( this );
+ startElement( name );
+ return scoped;
+ }
+
+ XmlWriter& XmlWriter::endElement() {
+ newlineIfNecessary();
+ m_indent = m_indent.substr( 0, m_indent.size()-2 );
+ if( m_tagIsOpen ) {
+ m_os << "/>";
+ m_tagIsOpen = false;
+ }
+ else {
+ m_os << m_indent << "</" << m_tags.back() << ">";
+ }
+ m_os << std::endl;
+ m_tags.pop_back();
+ return *this;
+ }
+
+ XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) {
+ if( !name.empty() && !attribute.empty() )
+ m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
+ return *this;
+ }
+
+ XmlWriter& XmlWriter::writeAttribute( std::string const& name, const char* attribute ) {
+ if( !name.empty() && attribute && attribute[0] != '\0' )
+ m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
+ return *this;
+ }
+
+ XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) {
+ m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
+ return *this;
+ }
+
+ XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) {
+ if( !text.empty() ){
+ bool tagWasOpen = m_tagIsOpen;
+ ensureTagClosed();
+ if( tagWasOpen && indent )
+ m_os << m_indent;
+ m_os << XmlEncode( text );
+ m_needsNewline = true;
+ }
+ return *this;
+ }
+
+ //XmlWriter& XmlWriter::writeComment( std::string const& text ) {
+ // ensureTagClosed();
+ // m_os << m_indent << "<!--" << text << "-->";
+ // m_needsNewline = true;
+ // return *this;
+ //}
+
+ //void XmlWriter::writeStylesheetRef( std::string const& url ) {
+ // m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
+ //}
+
+ //XmlWriter& XmlWriter::writeBlankLine() {
+ // ensureTagClosed();
+ // m_os << '\n';
+ // return *this;
+ //}
+
+ void XmlWriter::ensureTagClosed() {
+ if( m_tagIsOpen ) {
+ m_os << ">" << std::endl;
+ m_tagIsOpen = false;
+ }
+ }
+
+ void XmlWriter::writeDeclaration() {
+ m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ }
+
+ void XmlWriter::newlineIfNecessary() {
+ if( m_needsNewline ) {
+ m_os << std::endl;
+ m_needsNewline = false;
+ }
+ }
+
+// =================================================================================================
+// End of copy-pasted code from Catch
+// =================================================================================================
+
+ // clang-format on
+
+ struct XmlReporter : public IReporter
+ {
+ XmlWriter xml;
+ DOCTEST_DECLARE_MUTEX(mutex)
+
+ // caching pointers/references to objects of these types - safe to do
+ const ContextOptions& opt;
+ const TestCaseData* tc = nullptr;
+
+ XmlReporter(const ContextOptions& co)
+ : xml(*co.cout)
+ , opt(co) {}
+
+ void log_contexts() {
+ int num_contexts = get_num_active_contexts();
+ if(num_contexts) {
+ auto contexts = get_active_contexts();
+ std::stringstream ss;
+ for(int i = 0; i < num_contexts; ++i) {
+ contexts[i]->stringify(&ss);
+ xml.scopedElement("Info").writeText(ss.str());
+ ss.str("");
+ }
+ }
+ }
+
+ unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; }
+
+ void test_case_start_impl(const TestCaseData& in) {
+ bool open_ts_tag = false;
+ if(tc != nullptr) { // we have already opened a test suite
+ if(std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) {
+ xml.endElement();
+ open_ts_tag = true;
+ }
+ }
+ else {
+ open_ts_tag = true; // first test case ==> first test suite
+ }
+
+ if(open_ts_tag) {
+ xml.startElement("TestSuite");
+ xml.writeAttribute("name", in.m_test_suite);
+ }
+
+ tc = &in;
+ xml.startElement("TestCase")
+ .writeAttribute("name", in.m_name)
+ .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str()))
+ .writeAttribute("line", line(in.m_line))
+ .writeAttribute("description", in.m_description);
+
+ if(Approx(in.m_timeout) != 0)
+ xml.writeAttribute("timeout", in.m_timeout);
+ if(in.m_may_fail)
+ xml.writeAttribute("may_fail", true);
+ if(in.m_should_fail)
+ xml.writeAttribute("should_fail", true);
+ }
+
+ // =========================================================================================
+ // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
+ // =========================================================================================
+
+ void report_query(const QueryData& in) override {
+ test_run_start();
+ if(opt.list_reporters) {
+ for(auto& curr : getListeners())
+ xml.scopedElement("Listener")
+ .writeAttribute("priority", curr.first.first)
+ .writeAttribute("name", curr.first.second);
+ for(auto& curr : getReporters())
+ xml.scopedElement("Reporter")
+ .writeAttribute("priority", curr.first.first)
+ .writeAttribute("name", curr.first.second);
+ } else if(opt.count || opt.list_test_cases) {
+ for(unsigned i = 0; i < in.num_data; ++i) {
+ xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name)
+ .writeAttribute("testsuite", in.data[i]->m_test_suite)
+ .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str()))
+ .writeAttribute("line", line(in.data[i]->m_line))
+ .writeAttribute("skipped", in.data[i]->m_skip);
+ }
+ xml.scopedElement("OverallResultsTestCases")
+ .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters);
+ } else if(opt.list_test_suites) {
+ for(unsigned i = 0; i < in.num_data; ++i)
+ xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite);
+ xml.scopedElement("OverallResultsTestCases")
+ .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters);
+ xml.scopedElement("OverallResultsTestSuites")
+ .writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters);
+ }
+ xml.endElement();
+ }
+
+ void test_run_start() override {
+ xml.writeDeclaration();
+
+ // remove .exe extension - mainly to have the same output on UNIX and Windows
+ std::string binary_name = skipPathFromFilename(opt.binary_name.c_str());
+#ifdef DOCTEST_PLATFORM_WINDOWS
+ if(binary_name.rfind(".exe") != std::string::npos)
+ binary_name = binary_name.substr(0, binary_name.length() - 4);
+#endif // DOCTEST_PLATFORM_WINDOWS
+
+ xml.startElement("doctest").writeAttribute("binary", binary_name);
+ if(opt.no_version == false)
+ xml.writeAttribute("version", DOCTEST_VERSION_STR);
+
+ // only the consequential ones (TODO: filters)
+ xml.scopedElement("Options")
+ .writeAttribute("order_by", opt.order_by.c_str())
+ .writeAttribute("rand_seed", opt.rand_seed)
+ .writeAttribute("first", opt.first)
+ .writeAttribute("last", opt.last)
+ .writeAttribute("abort_after", opt.abort_after)
+ .writeAttribute("subcase_filter_levels", opt.subcase_filter_levels)
+ .writeAttribute("case_sensitive", opt.case_sensitive)
+ .writeAttribute("no_throw", opt.no_throw)
+ .writeAttribute("no_skip", opt.no_skip);
+ }
+
+ void test_run_end(const TestRunStats& p) override {
+ if(tc) // the TestSuite tag - only if there has been at least 1 test case
+ xml.endElement();
+
+ xml.scopedElement("OverallResultsAsserts")
+ .writeAttribute("successes", p.numAsserts - p.numAssertsFailed)
+ .writeAttribute("failures", p.numAssertsFailed);
+
+ xml.startElement("OverallResultsTestCases")
+ .writeAttribute("successes",
+ p.numTestCasesPassingFilters - p.numTestCasesFailed)
+ .writeAttribute("failures", p.numTestCasesFailed);
+ if(opt.no_skipped_summary == false)
+ xml.writeAttribute("skipped", p.numTestCases - p.numTestCasesPassingFilters);
+ xml.endElement();
+
+ xml.endElement();
+ }
+
+ void test_case_start(const TestCaseData& in) override {
+ test_case_start_impl(in);
+ xml.ensureTagClosed();
+ }
+
+ void test_case_reenter(const TestCaseData&) override {}
+
+ void test_case_end(const CurrentTestCaseStats& st) override {
+ xml.startElement("OverallResultsAsserts")
+ .writeAttribute("successes",
+ st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest)
+ .writeAttribute("failures", st.numAssertsFailedCurrentTest)
+ .writeAttribute("test_case_success", st.testCaseSuccess);
+ if(opt.duration)
+ xml.writeAttribute("duration", st.seconds);
+ if(tc->m_expected_failures)
+ xml.writeAttribute("expected_failures", tc->m_expected_failures);
+ xml.endElement();
+
+ xml.endElement();
+ }
+
+ void test_case_exception(const TestCaseException& e) override {
+ DOCTEST_LOCK_MUTEX(mutex)
+
+ xml.scopedElement("Exception")
+ .writeAttribute("crash", e.is_crash)
+ .writeText(e.error_string.c_str());
+ }
+
+ void subcase_start(const SubcaseSignature& in) override {
+ xml.startElement("SubCase")
+ .writeAttribute("name", in.m_name)
+ .writeAttribute("filename", skipPathFromFilename(in.m_file))
+ .writeAttribute("line", line(in.m_line));
+ xml.ensureTagClosed();
+ }
+
+ void subcase_end() override { xml.endElement(); }
+
+ void log_assert(const AssertData& rb) override {
+ if(!rb.m_failed && !opt.success)
+ return;
+
+ DOCTEST_LOCK_MUTEX(mutex)
+
+ xml.startElement("Expression")
+ .writeAttribute("success", !rb.m_failed)
+ .writeAttribute("type", assertString(rb.m_at))
+ .writeAttribute("filename", skipPathFromFilename(rb.m_file))
+ .writeAttribute("line", line(rb.m_line));
+
+ xml.scopedElement("Original").writeText(rb.m_expr);
+
+ if(rb.m_threw)
+ xml.scopedElement("Exception").writeText(rb.m_exception.c_str());
+
+ if(rb.m_at & assertType::is_throws_as)
+ xml.scopedElement("ExpectedException").writeText(rb.m_exception_type);
+ if(rb.m_at & assertType::is_throws_with)
+ xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str());
+ if((rb.m_at & assertType::is_normal) && !rb.m_threw)
+ xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str());
+
+ log_contexts();
+
+ xml.endElement();
+ }
+
+ void log_message(const MessageData& mb) override {
+ DOCTEST_LOCK_MUTEX(mutex)
+
+ xml.startElement("Message")
+ .writeAttribute("type", failureString(mb.m_severity))
+ .writeAttribute("filename", skipPathFromFilename(mb.m_file))
+ .writeAttribute("line", line(mb.m_line));
+
+ xml.scopedElement("Text").writeText(mb.m_string.c_str());
+
+ log_contexts();
+
+ xml.endElement();
+ }
+
+ void test_case_skipped(const TestCaseData& in) override {
+ if(opt.no_skipped_summary == false) {
+ test_case_start_impl(in);
+ xml.writeAttribute("skipped", "true");
+ xml.endElement();
+ }
+ }
+ };
+
+ DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter);
+
+ void fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) {
+ if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) ==
+ 0) //!OCLINT bitwise operator in conditional
+ s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) "
+ << Color::None;
+
+ if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
+ s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n";
+ } else if((rb.m_at & assertType::is_throws_as) &&
+ (rb.m_at & assertType::is_throws_with)) { //!OCLINT
+ s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
+ << rb.m_exception_string.c_str()
+ << "\", " << rb.m_exception_type << " ) " << Color::None;
+ if(rb.m_threw) {
+ if(!rb.m_failed) {
+ s << "threw as expected!\n";
+ } else {
+ s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n";
+ }
+ } else {
+ s << "did NOT throw at all!\n";
+ }
+ } else if(rb.m_at &
+ assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
+ s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", "
+ << rb.m_exception_type << " ) " << Color::None
+ << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" :
+ "threw a DIFFERENT exception: ") :
+ "did NOT throw at all!")
+ << Color::Cyan << rb.m_exception << "\n";
+ } else if(rb.m_at &
+ assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
+ s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
+ << rb.m_exception_string.c_str()
+ << "\" ) " << Color::None
+ << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" :
+ "threw a DIFFERENT exception: ") :
+ "did NOT throw at all!")
+ << Color::Cyan << rb.m_exception << "\n";
+ } else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
+ s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan
+ << rb.m_exception << "\n";
+ } else {
+ s << (rb.m_threw ? "THREW exception: " :
+ (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n"));
+ if(rb.m_threw)
+ s << rb.m_exception << "\n";
+ else
+ s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n";
+ }
+ }
+
+ // TODO:
+ // - log_message()
+ // - respond to queries
+ // - honor remaining options
+ // - more attributes in tags
+ struct JUnitReporter : public IReporter
+ {
+ XmlWriter xml;
+ DOCTEST_DECLARE_MUTEX(mutex)
+ Timer timer;
+ std::vector<String> deepestSubcaseStackNames;
+
+ struct JUnitTestCaseData
+ {
+ static std::string getCurrentTimestamp() {
+ // Beware, this is not reentrant because of backward compatibility issues
+ // Also, UTC only, again because of backward compatibility (%z is C++11)
+ time_t rawtime;
+ std::time(&rawtime);
+ auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
+
+ std::tm timeInfo;
+#ifdef DOCTEST_PLATFORM_WINDOWS
+ gmtime_s(&timeInfo, &rawtime);
+#else // DOCTEST_PLATFORM_WINDOWS
+ gmtime_r(&rawtime, &timeInfo);
+#endif // DOCTEST_PLATFORM_WINDOWS
+
+ char timeStamp[timeStampSize];
+ const char* const fmt = "%Y-%m-%dT%H:%M:%SZ";
+
+ std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
+ return std::string(timeStamp);
+ }
+
+ struct JUnitTestMessage
+ {
+ JUnitTestMessage(const std::string& _message, const std::string& _type, const std::string& _details)
+ : message(_message), type(_type), details(_details) {}
+
+ JUnitTestMessage(const std::string& _message, const std::string& _details)
+ : message(_message), type(), details(_details) {}
+
+ std::string message, type, details;
+ };
+
+ struct JUnitTestCase
+ {
+ JUnitTestCase(const std::string& _classname, const std::string& _name)
+ : classname(_classname), name(_name), time(0), failures() {}
+
+ std::string classname, name;
+ double time;
+ std::vector<JUnitTestMessage> failures, errors;
+ };
+
+ void add(const std::string& classname, const std::string& name) {
+ testcases.emplace_back(classname, name);
+ }
+
+ void appendSubcaseNamesToLastTestcase(std::vector<String> nameStack) {
+ for(auto& curr: nameStack)
+ if(curr.size())
+ testcases.back().name += std::string("/") + curr.c_str();
+ }
+
+ void addTime(double time) {
+ if(time < 1e-4)
+ time = 0;
+ testcases.back().time = time;
+ totalSeconds += time;
+ }
+
+ void addFailure(const std::string& message, const std::string& type, const std::string& details) {
+ testcases.back().failures.emplace_back(message, type, details);
+ ++totalFailures;
+ }
+
+ void addError(const std::string& message, const std::string& details) {
+ testcases.back().errors.emplace_back(message, details);
+ ++totalErrors;
+ }
+
+ std::vector<JUnitTestCase> testcases;
+ double totalSeconds = 0;
+ int totalErrors = 0, totalFailures = 0;
+ };
+
+ JUnitTestCaseData testCaseData;
+
+ // caching pointers/references to objects of these types - safe to do
+ const ContextOptions& opt;
+ const TestCaseData* tc = nullptr;
+
+ JUnitReporter(const ContextOptions& co)
+ : xml(*co.cout)
+ , opt(co) {}
+
+ unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; }
+
+ // =========================================================================================
+ // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
+ // =========================================================================================
+
+ void report_query(const QueryData&) override {
+ xml.writeDeclaration();
+ }
+
+ void test_run_start() override {
+ xml.writeDeclaration();
+ }
+
+ void test_run_end(const TestRunStats& p) override {
+ // remove .exe extension - mainly to have the same output on UNIX and Windows
+ std::string binary_name = skipPathFromFilename(opt.binary_name.c_str());
+#ifdef DOCTEST_PLATFORM_WINDOWS
+ if(binary_name.rfind(".exe") != std::string::npos)
+ binary_name = binary_name.substr(0, binary_name.length() - 4);
+#endif // DOCTEST_PLATFORM_WINDOWS
+ xml.startElement("testsuites");
+ xml.startElement("testsuite").writeAttribute("name", binary_name)
+ .writeAttribute("errors", testCaseData.totalErrors)
+ .writeAttribute("failures", testCaseData.totalFailures)
+ .writeAttribute("tests", p.numAsserts);
+ if(opt.no_time_in_output == false) {
+ xml.writeAttribute("time", testCaseData.totalSeconds);
+ xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp());
+ }
+ if(opt.no_version == false)
+ xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR);
+
+ for(const auto& testCase : testCaseData.testcases) {
+ xml.startElement("testcase")
+ .writeAttribute("classname", testCase.classname)
+ .writeAttribute("name", testCase.name);
+ if(opt.no_time_in_output == false)
+ xml.writeAttribute("time", testCase.time);
+ // This is not ideal, but it should be enough to mimic gtest's junit output.
+ xml.writeAttribute("status", "run");
+
+ for(const auto& failure : testCase.failures) {
+ xml.scopedElement("failure")
+ .writeAttribute("message", failure.message)
+ .writeAttribute("type", failure.type)
+ .writeText(failure.details, false);
+ }
+
+ for(const auto& error : testCase.errors) {
+ xml.scopedElement("error")
+ .writeAttribute("message", error.message)
+ .writeText(error.details);
+ }
+
+ xml.endElement();
+ }
+ xml.endElement();
+ xml.endElement();
+ }
+
+ void test_case_start(const TestCaseData& in) override {
+ testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name);
+ timer.start();
+ }
+
+ void test_case_reenter(const TestCaseData& in) override {
+ testCaseData.addTime(timer.getElapsedSeconds());
+ testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames);
+ deepestSubcaseStackNames.clear();
+
+ timer.start();
+ testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name);
+ }
+
+ void test_case_end(const CurrentTestCaseStats&) override {
+ testCaseData.addTime(timer.getElapsedSeconds());
+ testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames);
+ deepestSubcaseStackNames.clear();
+ }
+
+ void test_case_exception(const TestCaseException& e) override {
+ DOCTEST_LOCK_MUTEX(mutex)
+ testCaseData.addError("exception", e.error_string.c_str());
+ }
+
+ void subcase_start(const SubcaseSignature& in) override {
+ deepestSubcaseStackNames.push_back(in.m_name);
+ }
+
+ void subcase_end() override {}
+
+ void log_assert(const AssertData& rb) override {
+ if(!rb.m_failed) // report only failures & ignore the `success` option
+ return;
+
+ DOCTEST_LOCK_MUTEX(mutex)
+
+ std::ostringstream os;
+ os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(")
+ << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl;
+
+ fulltext_log_assert_to_stream(os, rb);
+ log_contexts(os);
+ testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str());
+ }
+
+ void log_message(const MessageData& mb) override {
+ if(mb.m_severity & assertType::is_warn) // report only failures
+ return;
+
+ DOCTEST_LOCK_MUTEX(mutex)
+
+ std::ostringstream os;
+ os << skipPathFromFilename(mb.m_file) << (opt.gnu_file_line ? ":" : "(")
+ << line(mb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl;
+
+ os << mb.m_string.c_str() << "\n";
+ log_contexts(os);
+
+ testCaseData.addFailure(mb.m_string.c_str(),
+ mb.m_severity & assertType::is_check ? "FAIL_CHECK" : "FAIL", os.str());
+ }
+
+ void test_case_skipped(const TestCaseData&) override {}
+
+ void log_contexts(std::ostringstream& s) {
+ int num_contexts = get_num_active_contexts();
+ if(num_contexts) {
+ auto contexts = get_active_contexts();
+
+ s << " logged: ";
+ for(int i = 0; i < num_contexts; ++i) {
+ s << (i == 0 ? "" : " ");
+ contexts[i]->stringify(&s);
+ s << std::endl;
+ }
+ }
+ }
+ };
+
+ DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter);
+
+ struct Whitespace
+ {
+ int nrSpaces;
+ explicit Whitespace(int nr)
+ : nrSpaces(nr) {}
+ };
+
+ std::ostream& operator<<(std::ostream& out, const Whitespace& ws) {
+ if(ws.nrSpaces != 0)
+ out << std::setw(ws.nrSpaces) << ' ';
+ return out;
+ }
+
+ struct ConsoleReporter : public IReporter
+ {
+ std::ostream& s;
+ bool hasLoggedCurrentTestStart;
+ std::vector<SubcaseSignature> subcasesStack;
+ size_t currentSubcaseLevel;
+ DOCTEST_DECLARE_MUTEX(mutex)
+
+ // caching pointers/references to objects of these types - safe to do
+ const ContextOptions& opt;
+ const TestCaseData* tc;
+
+ ConsoleReporter(const ContextOptions& co)
+ : s(*co.cout)
+ , opt(co) {}
+
+ ConsoleReporter(const ContextOptions& co, std::ostream& ostr)
+ : s(ostr)
+ , opt(co) {}
+
+ // =========================================================================================
+ // WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF THE INTERFACE
+ // =========================================================================================
+
+ void separator_to_stream() {
+ s << Color::Yellow
+ << "==============================================================================="
+ "\n";
+ }
+
+ const char* getSuccessOrFailString(bool success, assertType::Enum at,
+ const char* success_str) {
+ if(success)
+ return success_str;
+ return failureString(at);
+ }
+
+ Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) {
+ return success ? Color::BrightGreen :
+ (at & assertType::is_warn) ? Color::Yellow : Color::Red;
+ }
+
+ void successOrFailColoredStringToStream(bool success, assertType::Enum at,
+ const char* success_str = "SUCCESS") {
+ s << getSuccessOrFailColor(success, at)
+ << getSuccessOrFailString(success, at, success_str) << ": ";
+ }
+
+ void log_contexts() {
+ int num_contexts = get_num_active_contexts();
+ if(num_contexts) {
+ auto contexts = get_active_contexts();
+
+ s << Color::None << " logged: ";
+ for(int i = 0; i < num_contexts; ++i) {
+ s << (i == 0 ? "" : " ");
+ contexts[i]->stringify(&s);
+ s << "\n";
+ }
+ }
+
+ s << "\n";
+ }
+
+ // this was requested to be made virtual so users could override it
+ virtual void file_line_to_stream(const char* file, int line,
+ const char* tail = "") {
+ s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(")
+ << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option
+ << (opt.gnu_file_line ? ":" : "):") << tail;
+ }
+
+ void logTestStart() {
+ if(hasLoggedCurrentTestStart)
+ return;
+
+ separator_to_stream();
+ file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n");
+ if(tc->m_description)
+ s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n";
+ if(tc->m_test_suite && tc->m_test_suite[0] != '\0')
+ s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n";
+ if(strncmp(tc->m_name, " Scenario:", 11) != 0)
+ s << Color::Yellow << "TEST CASE: ";
+ s << Color::None << tc->m_name << "\n";
+
+ for(size_t i = 0; i < currentSubcaseLevel; ++i) {
+ if(subcasesStack[i].m_name[0] != '\0')
+ s << " " << subcasesStack[i].m_name << "\n";
+ }
+
+ if(currentSubcaseLevel != subcasesStack.size()) {
+ s << Color::Yellow << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" << Color::None;
+ for(size_t i = 0; i < subcasesStack.size(); ++i) {
+ if(subcasesStack[i].m_name[0] != '\0')
+ s << " " << subcasesStack[i].m_name << "\n";
+ }
+ }
+
+ s << "\n";
+
+ hasLoggedCurrentTestStart = true;
+ }
+
+ void printVersion() {
+ if(opt.no_version == false)
+ s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \""
+ << DOCTEST_VERSION_STR << "\"\n";
+ }
+
+ void printIntro() {
+ if(opt.no_intro == false) {
+ printVersion();
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n";
+ }
+ }
+
+ void printHelp() {
+ int sizePrefixDisplay = static_cast<int>(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY));
+ printVersion();
+ // clang-format off
+ s << Color::Cyan << "[doctest]\n" << Color::None;
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n";
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "filter values: \"str1,str2,str3\" (comma separated strings)\n";
+ s << Color::Cyan << "[doctest]\n" << Color::None;
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "filters use wildcards for matching strings\n";
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "something passes a filter if any of the strings in a filter matches\n";
+#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+ s << Color::Cyan << "[doctest]\n" << Color::None;
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"" DOCTEST_CONFIG_OPTIONS_PREFIX "\" PREFIX!!!\n";
+#endif
+ s << Color::Cyan << "[doctest]\n" << Color::None;
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "Query flags - the program quits after them. Available:\n\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "?, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "help, -" DOCTEST_OPTIONS_PREFIX_DISPLAY "h "
+ << Whitespace(sizePrefixDisplay*0) << "prints this message\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "v, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "version "
+ << Whitespace(sizePrefixDisplay*1) << "prints the version\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "c, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "count "
+ << Whitespace(sizePrefixDisplay*1) << "prints the number of matching tests\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ltc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-cases "
+ << Whitespace(sizePrefixDisplay*1) << "lists all matching tests by name\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-suites "
+ << Whitespace(sizePrefixDisplay*1) << "lists all matching test suites\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-reporters "
+ << Whitespace(sizePrefixDisplay*1) << "lists all registered reporters\n\n";
+ // ================================================================================== << 79
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "The available <int>/<string> options/filters are:\n\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters tests by their name\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case-exclude=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their name\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters tests by their file\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sfe, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file-exclude=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their file\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters tests by their test suite\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tse, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite-exclude=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their test suite\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters subcases by their name\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-exclude=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters OUT subcases by their name\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "r, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "reporters=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "reporters to use (console is default)\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "o, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "out=<string> "
+ << Whitespace(sizePrefixDisplay*1) << "output filename\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by=<string> "
+ << Whitespace(sizePrefixDisplay*1) << "how the tests should be ordered\n";
+ s << Whitespace(sizePrefixDisplay*3) << " <string> - [file/suite/name/rand/none]\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed=<int> "
+ << Whitespace(sizePrefixDisplay*1) << "seed for random ordering\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first=<int> "
+ << Whitespace(sizePrefixDisplay*1) << "the first test passing the filters to\n";
+ s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "l, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "last=<int> "
+ << Whitespace(sizePrefixDisplay*1) << "the last test passing the filters to\n";
+ s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "aa, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "abort-after=<int> "
+ << Whitespace(sizePrefixDisplay*1) << "stop after <int> failed assertions\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "scfl,--" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-filter-levels=<int> "
+ << Whitespace(sizePrefixDisplay*1) << "apply filters for the first <int> levels\n";
+ s << Color::Cyan << "\n[doctest] " << Color::None;
+ s << "Bool options - can be used like flags and true is assumed. Available:\n\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "s, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "success=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "include successful assertions in output\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "cs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "case-sensitive=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "filters being treated as case sensitive\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "e, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "exit=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "exits after the tests finish\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "d, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "duration=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "prints the time duration of each test\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "m, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "minimal=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "minimal console output (only failures)\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "q, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "quiet=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "no console output\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nt, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-throw=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "skips exceptions-related assert checks\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ne, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-exitcode=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "returns (or exits) always with success\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-run=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "skips all runtime doctest operations\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ni, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-intro=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "omit the framework intro in the output\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nv, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-version=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "omit the framework version in the output\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-colors=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "disables colors in output\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "fc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "force-colors=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "use colors even when not in a tty\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nb, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-breaks=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "disables breakpoints in debuggers\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ns, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-skip=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "don't skip test cases marked as skip\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "gfl, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "gnu-file-line=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << ":n: vs (n): for line numbers in output\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "npf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-path-filenames=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "only filenames and no paths in output\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nln, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-line-numbers=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "0 instead of real line numbers in output\n";
+ // ================================================================================== << 79
+ // clang-format on
+
+ s << Color::Cyan << "\n[doctest] " << Color::None;
+ s << "for more information visit the project documentation\n\n";
+ }
+
+ void printRegisteredReporters() {
+ printVersion();
+ auto printReporters = [this] (const reporterMap& reporters, const char* type) {
+ if(reporters.size()) {
+ s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type << "\n";
+ for(auto& curr : reporters)
+ s << "priority: " << std::setw(5) << curr.first.first
+ << " name: " << curr.first.second << "\n";
+ }
+ };
+ printReporters(getListeners(), "listeners");
+ printReporters(getReporters(), "reporters");
+ }
+
+ // =========================================================================================
+ // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
+ // =========================================================================================
+
+ void report_query(const QueryData& in) override {
+ if(opt.version) {
+ printVersion();
+ } else if(opt.help) {
+ printHelp();
+ } else if(opt.list_reporters) {
+ printRegisteredReporters();
+ } else if(opt.count || opt.list_test_cases) {
+ if(opt.list_test_cases) {
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "listing all test case names\n";
+ separator_to_stream();
+ }
+
+ for(unsigned i = 0; i < in.num_data; ++i)
+ s << Color::None << in.data[i]->m_name << "\n";
+
+ separator_to_stream();
+
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "unskipped test cases passing the current filters: "
+ << g_cs->numTestCasesPassingFilters << "\n";
+
+ } else if(opt.list_test_suites) {
+ s << Color::Cyan << "[doctest] " << Color::None << "listing all test suites\n";
+ separator_to_stream();
+
+ for(unsigned i = 0; i < in.num_data; ++i)
+ s << Color::None << in.data[i]->m_test_suite << "\n";
+
+ separator_to_stream();
+
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "unskipped test cases passing the current filters: "
+ << g_cs->numTestCasesPassingFilters << "\n";
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "test suites with unskipped test cases passing the current filters: "
+ << g_cs->numTestSuitesPassingFilters << "\n";
+ }
+ }
+
+ void test_run_start() override {
+ if(!opt.minimal)
+ printIntro();
+ }
+
+ void test_run_end(const TestRunStats& p) override {
+ if(opt.minimal && p.numTestCasesFailed == 0)
+ return;
+
+ separator_to_stream();
+ s << std::dec;
+
+ auto totwidth = int(std::ceil(log10(static_cast<double>(std::max(p.numTestCasesPassingFilters, static_cast<unsigned>(p.numAsserts))) + 1)));
+ auto passwidth = int(std::ceil(log10(static_cast<double>(std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast<unsigned>(p.numAsserts - p.numAssertsFailed))) + 1)));
+ auto failwidth = int(std::ceil(log10(static_cast<double>(std::max(p.numTestCasesFailed, static_cast<unsigned>(p.numAssertsFailed))) + 1)));
+ const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0;
+ s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth)
+ << p.numTestCasesPassingFilters << " | "
+ << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None :
+ Color::Green)
+ << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed"
+ << Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None)
+ << std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |";
+ if(opt.no_skipped_summary == false) {
+ const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters;
+ s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped
+ << " skipped" << Color::None;
+ }
+ s << "\n";
+ s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth)
+ << p.numAsserts << " | "
+ << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green)
+ << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None
+ << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth)
+ << p.numAssertsFailed << " failed" << Color::None << " |\n";
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green)
+ << ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None << std::endl;
+ }
+
+ void test_case_start(const TestCaseData& in) override {
+ hasLoggedCurrentTestStart = false;
+ tc = &in;
+ subcasesStack.clear();
+ currentSubcaseLevel = 0;
+ }
+
+ void test_case_reenter(const TestCaseData&) override {
+ subcasesStack.clear();
+ }
+
+ void test_case_end(const CurrentTestCaseStats& st) override {
+ if(tc->m_no_output)
+ return;
+
+ // log the preamble of the test case only if there is something
+ // else to print - something other than that an assert has failed
+ if(opt.duration ||
+ (st.failure_flags && st.failure_flags != static_cast<int>(TestCaseFailureReason::AssertFailure)))
+ logTestStart();
+
+ if(opt.duration)
+ s << Color::None << std::setprecision(6) << std::fixed << st.seconds
+ << " s: " << tc->m_name << "\n";
+
+ if(st.failure_flags & TestCaseFailureReason::Timeout)
+ s << Color::Red << "Test case exceeded time limit of " << std::setprecision(6)
+ << std::fixed << tc->m_timeout << "!\n";
+
+ if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) {
+ s << Color::Red << "Should have failed but didn't! Marking it as failed!\n";
+ } else if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) {
+ s << Color::Yellow << "Failed as expected so marking it as not failed\n";
+ } else if(st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) {
+ s << Color::Yellow << "Allowed to fail so marking it as not failed\n";
+ } else if(st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) {
+ s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures
+ << " times so marking it as failed!\n";
+ } else if(st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) {
+ s << Color::Yellow << "Failed exactly " << tc->m_expected_failures
+ << " times as expected so marking it as not failed!\n";
+ }
+ if(st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) {
+ s << Color::Red << "Aborting - too many failed asserts!\n";
+ }
+ s << Color::None; // lgtm [cpp/useless-expression]
+ }
+
+ void test_case_exception(const TestCaseException& e) override {
+ DOCTEST_LOCK_MUTEX(mutex)
+ if(tc->m_no_output)
+ return;
+
+ logTestStart();
+
+ file_line_to_stream(tc->m_file.c_str(), tc->m_line, " ");
+ successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require :
+ assertType::is_check);
+ s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ")
+ << Color::Cyan << e.error_string << "\n";
+
+ int num_stringified_contexts = get_num_stringified_contexts();
+ if(num_stringified_contexts) {
+ auto stringified_contexts = get_stringified_contexts();
+ s << Color::None << " logged: ";
+ for(int i = num_stringified_contexts; i > 0; --i) {
+ s << (i == num_stringified_contexts ? "" : " ")
+ << stringified_contexts[i - 1] << "\n";
+ }
+ }
+ s << "\n" << Color::None;
+ }
+
+ void subcase_start(const SubcaseSignature& subc) override {
+ subcasesStack.push_back(subc);
+ ++currentSubcaseLevel;
+ hasLoggedCurrentTestStart = false;
+ }
+
+ void subcase_end() override {
+ --currentSubcaseLevel;
+ hasLoggedCurrentTestStart = false;
+ }
+
+ void log_assert(const AssertData& rb) override {
+ if((!rb.m_failed && !opt.success) || tc->m_no_output)
+ return;
+
+ DOCTEST_LOCK_MUTEX(mutex)
+
+ logTestStart();
+
+ file_line_to_stream(rb.m_file, rb.m_line, " ");
+ successOrFailColoredStringToStream(!rb.m_failed, rb.m_at);
+
+ fulltext_log_assert_to_stream(s, rb);
+
+ log_contexts();
+ }
+
+ void log_message(const MessageData& mb) override {
+ if(tc->m_no_output)
+ return;
+
+ DOCTEST_LOCK_MUTEX(mutex)
+
+ logTestStart();
+
+ file_line_to_stream(mb.m_file, mb.m_line, " ");
+ s << getSuccessOrFailColor(false, mb.m_severity)
+ << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity,
+ "MESSAGE") << ": ";
+ s << Color::None << mb.m_string << "\n";
+ log_contexts();
+ }
+
+ void test_case_skipped(const TestCaseData&) override {}
+ };
+
+ DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter);
+
+#ifdef DOCTEST_PLATFORM_WINDOWS
+ struct DebugOutputWindowReporter : public ConsoleReporter
+ {
+ DOCTEST_THREAD_LOCAL static std::ostringstream oss;
+
+ DebugOutputWindowReporter(const ContextOptions& co)
+ : ConsoleReporter(co, oss) {}
+
+#define DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(func, type, arg) \
+ void func(type arg) override { \
+ bool with_col = g_no_colors; \
+ g_no_colors = false; \
+ ConsoleReporter::func(arg); \
+ if(oss.tellp() != std::streampos{}) { \
+ DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \
+ oss.str(""); \
+ } \
+ g_no_colors = with_col; \
+ }
+
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData&, in)
+ };
+
+ DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss;
+#endif // DOCTEST_PLATFORM_WINDOWS
+
+ // the implementation of parseOption()
+ bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) {
+ // going from the end to the beginning and stopping on the first occurrence from the end
+ for(int i = argc; i > 0; --i) {
+ auto index = i - 1;
+ auto temp = std::strstr(argv[index], pattern);
+ if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue
+ // eliminate matches in which the chars before the option are not '-'
+ bool noBadCharsFound = true;
+ auto curr = argv[index];
+ while(curr != temp) {
+ if(*curr++ != '-') {
+ noBadCharsFound = false;
+ break;
+ }
+ }
+ if(noBadCharsFound && argv[index][0] == '-') {
+ if(value) {
+ // parsing the value of an option
+ temp += strlen(pattern);
+ const unsigned len = strlen(temp);
+ if(len) {
+ *value = temp;
+ return true;
+ }
+ } else {
+ // just a flag - no value
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ // parses an option and returns the string after the '=' character
+ bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr,
+ const String& defaultVal = String()) {
+ if(value)
+ *value = defaultVal;
+#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+ // offset (normally 3 for "dt-") to skip prefix
+ if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value))
+ return true;
+#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+ return parseOptionImpl(argc, argv, pattern, value);
+ }
+
+ // locates a flag on the command line
+ bool parseFlag(int argc, const char* const* argv, const char* pattern) {
+ return parseOption(argc, argv, pattern);
+ }
+
+ // parses a comma separated list of words after a pattern in one of the arguments in argv
+ bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern,
+ std::vector<String>& res) {
+ String filtersString;
+ if(parseOption(argc, argv, pattern, &filtersString)) {
+ // tokenize with "," as a separator, unless escaped with backslash
+ std::ostringstream s;
+ auto flush = [&s, &res]() {
+ auto string = s.str();
+ if(string.size() > 0) {
+ res.push_back(string.c_str());
+ }
+ s.str("");
+ };
+
+ bool seenBackslash = false;
+ const char* current = filtersString.c_str();
+ const char* end = current + strlen(current);
+ while(current != end) {
+ char character = *current++;
+ if(seenBackslash) {
+ seenBackslash = false;
+ if(character == ',' || character == '\\') {
+ s.put(character);
+ continue;
+ }
+ s.put('\\');
+ }
+ if(character == '\\') {
+ seenBackslash = true;
+ } else if(character == ',') {
+ flush();
+ } else {
+ s.put(character);
+ }
+ }
+
+ if(seenBackslash) {
+ s.put('\\');
+ }
+ flush();
+ return true;
+ }
+ return false;
+ }
+
+ enum optionType
+ {
+ option_bool,
+ option_int
+ };
+
+ // parses an int/bool option from the command line
+ bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type,
+ int& res) {
+ String parsedValue;
+ if(!parseOption(argc, argv, pattern, &parsedValue))
+ return false;
+
+ if(type) {
+ // integer
+ // TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse...
+ int theInt = std::atoi(parsedValue.c_str());
+ if (theInt != 0) {
+ res = theInt; //!OCLINT parameter reassignment
+ return true;
+ }
+ } else {
+ // boolean
+ const char positive[][5] = { "1", "true", "on", "yes" }; // 5 - strlen("true") + 1
+ const char negative[][6] = { "0", "false", "off", "no" }; // 6 - strlen("false") + 1
+
+ // if the value matches any of the positive/negative possibilities
+ for (unsigned i = 0; i < 4; i++) {
+ if (parsedValue.compare(positive[i], true) == 0) {
+ res = 1; //!OCLINT parameter reassignment
+ return true;
+ }
+ if (parsedValue.compare(negative[i], true) == 0) {
+ res = 0; //!OCLINT parameter reassignment
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+} // namespace
+
+Context::Context(int argc, const char* const* argv)
+ : p(new detail::ContextState) {
+ parseArgs(argc, argv, true);
+ if(argc)
+ p->binary_name = argv[0];
+}
+
+Context::~Context() {
+ if(g_cs == p)
+ g_cs = nullptr;
+ delete p;
+}
+
+void Context::applyCommandLine(int argc, const char* const* argv) {
+ parseArgs(argc, argv);
+ if(argc)
+ p->binary_name = argv[0];
+}
+
+// parses args
+void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {
+ using namespace detail;
+
+ // clang-format off
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file=", p->filters[0]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sf=", p->filters[0]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file-exclude=",p->filters[1]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sfe=", p->filters[1]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite=", p->filters[2]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ts=", p->filters[2]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite-exclude=", p->filters[3]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tse=", p->filters[3]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case=", p->filters[4]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tc=", p->filters[4]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case-exclude=", p->filters[5]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tce=", p->filters[5]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase=", p->filters[6]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sc=", p->filters[6]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase-exclude=", p->filters[7]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sce=", p->filters[7]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "reporters=", p->filters[8]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "r=", p->filters[8]);
+ // clang-format on
+
+ int intRes = 0;
+ String strRes;
+
+#define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \
+ if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \
+ parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \
+ p->var = static_cast<bool>(intRes); \
+ else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \
+ p->var = true; \
+ else if(withDefaults) \
+ p->var = default
+
+#define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \
+ if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_int, intRes) || \
+ parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_int, intRes)) \
+ p->var = intRes; \
+ else if(withDefaults) \
+ p->var = default
+
+#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \
+ if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \
+ parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \
+ withDefaults) \
+ p->var = strRes
+
+ // clang-format off
+ DOCTEST_PARSE_STR_OPTION("out", "o", out, "");
+ DOCTEST_PARSE_STR_OPTION("order-by", "ob", order_by, "file");
+ DOCTEST_PARSE_INT_OPTION("rand-seed", "rs", rand_seed, 0);
+
+ DOCTEST_PARSE_INT_OPTION("first", "f", first, 0);
+ DOCTEST_PARSE_INT_OPTION("last", "l", last, UINT_MAX);
+
+ DOCTEST_PARSE_INT_OPTION("abort-after", "aa", abort_after, 0);
+ DOCTEST_PARSE_INT_OPTION("subcase-filter-levels", "scfl", subcase_filter_levels, INT_MAX);
+
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("success", "s", success, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("case-sensitive", "cs", case_sensitive, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("exit", "e", exit, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("duration", "d", duration, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("minimal", "m", minimal, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("quiet", "q", quiet, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-throw", "nt", no_throw, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-exitcode", "ne", no_exitcode, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-run", "nr", no_run, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-intro", "ni", no_intro, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-version", "nv", no_version, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-colors", "nc", no_colors, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("force-colors", "fc", force_colors, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-breaks", "nb", no_breaks, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skip", "ns", no_skip, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("gnu-file-line", "gfl", gnu_file_line, !bool(DOCTEST_MSVC));
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-debug-output", "ndo", no_debug_output, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false);
+ // clang-format on
+
+ if(withDefaults) {
+ p->help = false;
+ p->version = false;
+ p->count = false;
+ p->list_test_cases = false;
+ p->list_test_suites = false;
+ p->list_reporters = false;
+ }
+ if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) {
+ p->help = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) {
+ p->version = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) {
+ p->count = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) {
+ p->list_test_cases = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) {
+ p->list_test_suites = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) {
+ p->list_reporters = true;
+ p->exit = true;
+ }
+}
+
+// allows the user to add procedurally to the filters from the command line
+void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); }
+
+// allows the user to clear all filters from the command line
+void Context::clearFilters() {
+ for(auto& curr : p->filters)
+ curr.clear();
+}
+
+// allows the user to override procedurally the bool options from the command line
+void Context::setOption(const char* option, bool value) {
+ setOption(option, value ? "true" : "false");
+}
+
+// allows the user to override procedurally the int options from the command line
+void Context::setOption(const char* option, int value) {
+ setOption(option, toString(value).c_str());
+}
+
+// allows the user to override procedurally the string options from the command line
+void Context::setOption(const char* option, const char* value) {
+ auto argv = String("-") + option + "=" + value;
+ auto lvalue = argv.c_str();
+ parseArgs(1, &lvalue);
+}
+
+// users should query this in their main() and exit the program if true
+bool Context::shouldExit() { return p->exit; }
+
+void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; }
+
+void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; }
+
+void Context::setCout(std::ostream* out) { p->cout = out; }
+
+static class DiscardOStream : public std::ostream
+{
+private:
+ class : public std::streambuf
+ {
+ private:
+ // allowing some buffering decreases the amount of calls to overflow
+ char buf[1024];
+
+ protected:
+ std::streamsize xsputn(const char_type*, std::streamsize count) override { return count; }
+
+ int_type overflow(int_type ch) override {
+ setp(std::begin(buf), std::end(buf));
+ return traits_type::not_eof(ch);
+ }
+ } discardBuf;
+
+public:
+ DiscardOStream()
+ : std::ostream(&discardBuf) {}
+} discardOut;
+
+// the main function that does all the filtering and test running
+int Context::run() {
+ using namespace detail;
+
+ // save the old context state in case such was setup - for using asserts out of a testing context
+ auto old_cs = g_cs;
+ // this is the current contest
+ g_cs = p;
+ is_running_in_test = true;
+
+ g_no_colors = p->no_colors;
+ p->resetRunData();
+
+ std::fstream fstr;
+ if(p->cout == nullptr) {
+ if(p->quiet) {
+ p->cout = &discardOut;
+ } else if(p->out.size()) {
+ // to a file if specified
+ fstr.open(p->out.c_str(), std::fstream::out);
+ p->cout = &fstr;
+ } else {
+#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+ // stdout by default
+ p->cout = &std::cout;
+#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+ return EXIT_FAILURE;
+#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
+ }
+ }
+
+ FatalConditionHandler::allocateAltStackMem();
+
+ auto cleanup_and_return = [&]() {
+ FatalConditionHandler::freeAltStackMem();
+
+ if(fstr.is_open())
+ fstr.close();
+
+ // restore context
+ g_cs = old_cs;
+ is_running_in_test = false;
+
+ // we have to free the reporters which were allocated when the run started
+ for(auto& curr : p->reporters_currently_used)
+ delete curr;
+ p->reporters_currently_used.clear();
+
+ if(p->numTestCasesFailed && !p->no_exitcode)
+ return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+ };
+
+ // setup default reporter if none is given through the command line
+ if(p->filters[8].empty())
+ p->filters[8].push_back("console");
+
+ // check to see if any of the registered reporters has been selected
+ for(auto& curr : getReporters()) {
+ if(matchesAny(curr.first.second.c_str(), p->filters[8], false, p->case_sensitive))
+ p->reporters_currently_used.push_back(curr.second(*g_cs));
+ }
+
+ // TODO: check if there is nothing in reporters_currently_used
+
+ // prepend all listeners
+ for(auto& curr : getListeners())
+ p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs));
+
+#ifdef DOCTEST_PLATFORM_WINDOWS
+ if(isDebuggerActive() && p->no_debug_output == false)
+ p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs));
+#endif // DOCTEST_PLATFORM_WINDOWS
+
+ // handle version, help and no_run
+ if(p->no_run || p->version || p->help || p->list_reporters) {
+ DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData());
+
+ return cleanup_and_return();
+ }
+
+ std::vector<const TestCase*> testArray;
+ for(auto& curr : getRegisteredTests())
+ testArray.push_back(&curr);
+ p->numTestCases = testArray.size();
+
+ // sort the collected records
+ if(!testArray.empty()) {
+ if(p->order_by.compare("file", true) == 0) {
+ std::sort(testArray.begin(), testArray.end(), fileOrderComparator);
+ } else if(p->order_by.compare("suite", true) == 0) {
+ std::sort(testArray.begin(), testArray.end(), suiteOrderComparator);
+ } else if(p->order_by.compare("name", true) == 0) {
+ std::sort(testArray.begin(), testArray.end(), nameOrderComparator);
+ } else if(p->order_by.compare("rand", true) == 0) {
+ std::srand(p->rand_seed);
+
+ // random_shuffle implementation
+ const auto first = &testArray[0];
+ for(size_t i = testArray.size() - 1; i > 0; --i) {
+ int idxToSwap = std::rand() % (i + 1);
+
+ const auto temp = first[i];
+
+ first[i] = first[idxToSwap];
+ first[idxToSwap] = temp;
+ }
+ } else if(p->order_by.compare("none", true) == 0) {
+ // means no sorting - beneficial for death tests which call into the executable
+ // with a specific test case in mind - we don't want to slow down the startup times
+ }
+ }
+
+ std::set<String> testSuitesPassingFilt;
+
+ bool query_mode = p->count || p->list_test_cases || p->list_test_suites;
+ std::vector<const TestCaseData*> queryResults;
+
+ if(!query_mode)
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY);
+
+ // invoke the registered functions if they match the filter criteria (or just count them)
+ for(auto& curr : testArray) {
+ const auto& tc = *curr;
+
+ bool skip_me = false;
+ if(tc.m_skip && !p->no_skip)
+ skip_me = true;
+
+ if(!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive))
+ skip_me = true;
+ if(matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive))
+ skip_me = true;
+ if(!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive))
+ skip_me = true;
+ if(matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive))
+ skip_me = true;
+ if(!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive))
+ skip_me = true;
+ if(matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive))
+ skip_me = true;
+
+ if(!skip_me)
+ p->numTestCasesPassingFilters++;
+
+ // skip the test if it is not in the execution range
+ if((p->last < p->numTestCasesPassingFilters && p->first <= p->last) ||
+ (p->first > p->numTestCasesPassingFilters))
+ skip_me = true;
+
+ if(skip_me) {
+ if(!query_mode)
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc);
+ continue;
+ }
+
+ // do not execute the test if we are to only count the number of filter passing tests
+ if(p->count)
+ continue;
+
+ // print the name of the test and don't execute it
+ if(p->list_test_cases) {
+ queryResults.push_back(&tc);
+ continue;
+ }
+
+ // print the name of the test suite if not done already and don't execute it
+ if(p->list_test_suites) {
+ if((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') {
+ queryResults.push_back(&tc);
+ testSuitesPassingFilt.insert(tc.m_test_suite);
+ p->numTestSuitesPassingFilters++;
+ }
+ continue;
+ }
+
+ // execute the test if it passes all the filtering
+ {
+ p->currentTest = &tc;
+
+ p->failure_flags = TestCaseFailureReason::None;
+ p->seconds = 0;
+
+ // reset atomic counters
+ p->numAssertsFailedCurrentTest_atomic = 0;
+ p->numAssertsCurrentTest_atomic = 0;
+
+ p->fullyTraversedSubcases.clear();
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc);
+
+ p->timer.start();
+
+ bool run_test = true;
+
+ do {
+ // reset some of the fields for subcases (except for the set of fully passed ones)
+ p->reachedLeaf = false;
+ // May not be empty if previous subcase exited via exception.
+ p->subcaseStack.clear();
+ p->currentSubcaseDepth = 0;
+
+ p->shouldLogCurrentException = true;
+
+ // reset stuff for logging with INFO()
+ p->stringifiedContexts.clear();
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ try {
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method)
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable
+ FatalConditionHandler fatalConditionHandler; // Handle signals
+ // execute the test
+ tc.m_test();
+ fatalConditionHandler.reset();
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ } catch(const TestFailureException&) {
+ p->failure_flags |= TestCaseFailureReason::AssertFailure;
+ } catch(...) {
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception,
+ {translateActiveException(), false});
+ p->failure_flags |= TestCaseFailureReason::Exception;
+ }
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+ // exit this loop if enough assertions have failed - even if there are more subcases
+ if(p->abort_after > 0 &&
+ p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) {
+ run_test = false;
+ p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts;
+ }
+
+ if(!p->nextSubcaseStack.empty() && run_test)
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc);
+ if(p->nextSubcaseStack.empty())
+ run_test = false;
+ } while(run_test);
+
+ p->finalizeTestCaseData();
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs);
+
+ p->currentTest = nullptr;
+
+ // stop executing tests if enough assertions have failed
+ if(p->abort_after > 0 && p->numAssertsFailed >= p->abort_after)
+ break;
+ }
+ }
+
+ if(!query_mode) {
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs);
+ } else {
+ QueryData qdata;
+ qdata.run_stats = g_cs;
+ qdata.data = queryResults.data();
+ qdata.num_data = unsigned(queryResults.size());
+ DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata);
+ }
+
+ return cleanup_and_return();
+}
+
+DOCTEST_DEFINE_INTERFACE(IReporter)
+
+int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); }
+const IContextScope* const* IReporter::get_active_contexts() {
+ return get_num_active_contexts() ? &detail::g_infoContexts[0] : nullptr;
+}
+
+int IReporter::get_num_stringified_contexts() { return detail::g_cs->stringifiedContexts.size(); }
+const String* IReporter::get_stringified_contexts() {
+ return get_num_stringified_contexts() ? &detail::g_cs->stringifiedContexts[0] : nullptr;
+}
+
+namespace detail {
+ void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c, bool isReporter) {
+ if(isReporter)
+ getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c));
+ else
+ getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c));
+ }
+} // namespace detail
+
+} // namespace doctest
+
+#endif // DOCTEST_CONFIG_DISABLE
+
+#ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) // 'function' : must be 'attribute' - see issue #182
+int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); }
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+
+DOCTEST_CLANG_SUPPRESS_WARNING_POP
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+DOCTEST_GCC_SUPPRESS_WARNING_POP
+
+DOCTEST_SUPPRESS_COMMON_WARNINGS_POP
+
+#endif // DOCTEST_LIBRARY_IMPLEMENTATION
+#endif // DOCTEST_CONFIG_IMPLEMENT
+
+#ifdef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN
+#undef WIN32_LEAN_AND_MEAN
+#undef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN
+#endif // DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN
+
+#ifdef DOCTEST_UNDEF_NOMINMAX
+#undef NOMINMAX
+#undef DOCTEST_UNDEF_NOMINMAX
+#endif // DOCTEST_UNDEF_NOMINMAX
diff --git a/source/d/ccache/doctest.h.url b/source/d/ccache/doctest.h.url
new file mode 100644
index 000000000..e5aedb4da
--- /dev/null
+++ b/source/d/ccache/doctest.h.url
@@ -0,0 +1 @@
+https://github.com/doctest/doctest/releases/download/v2.4.11/doctest.h
diff --git a/source/d/perl/perl.SlackBuild b/source/d/perl/perl.SlackBuild
index abe4b9355..a0f16afeb 100755
--- a/source/d/perl/perl.SlackBuild
+++ b/source/d/perl/perl.SlackBuild
@@ -26,8 +26,8 @@
cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=perl
-VERSION=5.38.2
-BUILD=${BUILD:-2}
+VERSION=5.40.0
+BUILD=${BUILD:-1}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
@@ -60,7 +60,7 @@ PKG=$TMP/package-perl
# https://metacpan.org/release/Devel-CheckLib
DEVELCHECKLIB=1.16
# https://metacpan.org/release/DBD-mysql
-DBDMYSQL=4.051
+DBDMYSQL=4.052
# https://metacpan.org/release/DBI
DBI=1.643
# https://metacpan.org/pod/Locale::gettext
@@ -68,7 +68,7 @@ GETTEXT=1.07
# https://metacpan.org/release/TermReadKey
TERMREADKEY=2.38
# https://metacpan.org/release/URI
-URI=5.27
+URI=5.28
# https://metacpan.org/release/XML-Parser
XMLPARSER=2.47
# https://metacpan.org/release/XML-Simple
@@ -86,7 +86,7 @@ LIBNET=3.15
# https://metacpan.org/release/Parse-Yapp
PARSEYAPP=1.21
# https://metacpan.org/release/Path-Tiny (freecell-solver)
-PATHTINY=0.144
+PATHTINY=0.146
# https://metacpan.org/release/Template-Toolkit (freecell-solver)
TEMPLATETOOLKIT=3.101
# https://metacpan.org/release/Moo (freecell-solver)
diff --git a/source/d/subversion/subversion.SlackBuild b/source/d/subversion/subversion.SlackBuild
index 4863bfa6b..acf3204e9 100755
--- a/source/d/subversion/subversion.SlackBuild
+++ b/source/d/subversion/subversion.SlackBuild
@@ -24,7 +24,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=subversion
VERSION=${VERSION:-$(echo subversion-*.tar.?z* | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
-BUILD=${BUILD:-1}
+BUILD=${BUILD:-2}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
diff --git a/source/kde/fcitx5-configtool/slack-desc b/source/kde/fcitx5-configtool/slack-desc
index 1b4b69421..8681b8178 100644
--- a/source/kde/fcitx5-configtool/slack-desc
+++ b/source/kde/fcitx5-configtool/slack-desc
@@ -6,9 +6,9 @@
# customary to leave one space after the ':' except on otherwise blank lines.
|-----handy-ruler------------------------------------------------------|
-fcitx5-configtool: fcitx5-configtool (Plasma config module for Fcitx5)
+fcitx5-configtool: fcitx5-configtool (Plasma config module for fcitx5)
fcitx5-configtool:
-fcitx5-configtool: Plasma/Qt config module for Fcitx5.
+fcitx5-configtool: Plasma/Qt config module for fcitx5.
fcitx5-configtool:
fcitx5-configtool: Homepage: https://fcitx-im.org/wiki/Fcitx_5
fcitx5-configtool:
diff --git a/source/kde/kde/patch/plasma-workspace.patch b/source/kde/kde/patch/plasma-workspace.patch
index 77645b0cb..4a94c28a1 100644
--- a/source/kde/kde/patch/plasma-workspace.patch
+++ b/source/kde/kde/patch/plasma-workspace.patch
@@ -1 +1,2 @@
cat $CWD/patch/plasma-workspace/0001-Revert-No-icons-on-the-desktop-by-default.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
+cat $CWD/patch/plasma-workspace/1181acfe30557d6646511df8d98d82589878a570.patch | patch -p1 --verbose || { touch ${SLACK_KDE_BUILD_DIR}/${PKGNAME}.failed ; continue ; }
diff --git a/source/kde/kde/patch/plasma-workspace/1181acfe30557d6646511df8d98d82589878a570.patch b/source/kde/kde/patch/plasma-workspace/1181acfe30557d6646511df8d98d82589878a570.patch
new file mode 100644
index 000000000..ed1b67bbd
--- /dev/null
+++ b/source/kde/kde/patch/plasma-workspace/1181acfe30557d6646511df8d98d82589878a570.patch
@@ -0,0 +1,66 @@
+From 1181acfe30557d6646511df8d98d82589878a570 Mon Sep 17 00:00:00 2001
+From: Fushan Wen <qydwhotmail@gmail.com>
+Date: Tue, 4 Jun 2024 12:18:11 +0000
+Subject: [PATCH] Fix writing ICEAuthority file
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 9398f6cf8933055b31506ba155aef2fc2b3561d7 "Remove iceauth
+dependency" introduced two bugs:
+
+1) "fp" is never closed, so the generated auth data stays buffered in
+ memory for some indeterminate time and the file stays empty on disk.
+ This completely breaks authentication and thus also session restore.
+
+2) Checking the return value of IceWriteAuthFileEntry() is inverted (the
+ function returns non-zero on success), so warnings are printed iff
+ everything goes well.
+
+BUG: 487912
+
+
+(cherry picked from commit 0dcf34458d99b07a3d9054ae0c86c656e0dfa7aa)
+
+Co-authored-by: Tomáš Trnka <tomastrnka@gmx.com>
+---
+ ksmserver/server.cpp | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/ksmserver/server.cpp b/ksmserver/server.cpp
+index f88de40dba4..bba6b13ffae 100644
+--- a/ksmserver/server.cpp
++++ b/ksmserver/server.cpp
+@@ -333,7 +333,7 @@ Status SetAuthentication(int count, IceListenObj *listenObjs, IceAuthDataEntry *
+ file_entry->auth_name = strdup("MIT-MAGIC-COOKIE-1");
+ file_entry->auth_data = strdup((*authDataEntries)[i].auth_data);
+ file_entry->auth_data_length = MAGIC_COOKIE_LEN;
+- if (IceWriteAuthFileEntry(fp, file_entry) != 0) {
++ if (IceWriteAuthFileEntry(fp, file_entry) == 0) {
+ qWarning("Failed to write ice auth file entry");
+ }
+ IceFreeAuthFileEntry(file_entry);
+@@ -357,7 +357,7 @@ Status SetAuthentication(int count, IceListenObj *listenObjs, IceAuthDataEntry *
+ file_entry->auth_name = strdup("MIT-MAGIC-COOKIE-1");
+ file_entry->auth_data = strdup((*authDataEntries)[i + 1].auth_data);
+ file_entry->auth_data_length = MAGIC_COOKIE_LEN;
+- if (IceWriteAuthFileEntry(fp, file_entry) != 0) {
++ if (IceWriteAuthFileEntry(fp, file_entry) == 0) {
+ qWarning("Failed to write xsmp ice auth file entry");
+ }
+ IceFreeAuthFileEntry(file_entry);
+@@ -366,6 +366,11 @@ Status SetAuthentication(int count, IceListenObj *listenObjs, IceAuthDataEntry *
+ IceSetPaAuthData(2, &(*authDataEntries)[i]);
+ }
+
++ if (fclose(fp) != 0) {
++ qWarning() << "Could not close ICEAuthority file";
++ return 0;
++ }
++
+ return (1);
+ }
+
+--
+GitLab
+
diff --git a/source/l/glib2/4073.patch b/source/l/glib2/4073.patch
deleted file mode 100644
index 24156369b..000000000
--- a/source/l/glib2/4073.patch
+++ /dev/null
@@ -1,290 +0,0 @@
-From df2c5d925ac4b8f1708bafa5ac1d35acada05d55 Mon Sep 17 00:00:00 2001
-From: Philip Withnall <pwithnall@gnome.org>
-Date: Wed, 15 May 2024 12:26:36 +0100
-Subject: [PATCH 1/2] gmenuexporter: Fix a NULL pointer dereference on an error
- handling path
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This latent bug wasn’t triggered until commit 3f30ec86c (or its
-cherry-pick onto `glib-2-80`, 747e3af99, which was first released in
-2.80.1).
-
-That change means that `g_menu_exporter_free()` is now called on the
-registration failure path by `g_dbus_connection_register_object()`
-before it returns. The caller then tries to call `g_slice_free()` on the
-exporter again. The call to `g_menu_exporter_free()` tries to
-dereference/free members of the exporter which it expects to be
-initialised — but because this is happening in an error handling path,
-they are not initialised.
-
-If it were to get any further, the `g_slice_free()` would then be a
-double-free on the exporter allocation.
-
-Fix that by making `g_menu_exporter_free()` robust to some of the
-exporter members being `NULL`, and moving some of the initialisation
-code higher in `g_dbus_connection_export_menu_model()`, and removing the
-duplicate free code on the error handling path.
-
-This includes a unit test.
-
-Signed-off-by: Philip Withnall <pwithnall@gnome.org>
-
-Fixes: #3366
----
- gio/gmenuexporter.c | 23 ++++++++---------------
- gio/tests/gmenumodel.c | 37 +++++++++++++++++++++++++++++++++++++
- 2 files changed, 45 insertions(+), 15 deletions(-)
-
-diff --git a/gio/gmenuexporter.c b/gio/gmenuexporter.c
-index 909780cb2c..1d4db13523 100644
---- a/gio/gmenuexporter.c
-+++ b/gio/gmenuexporter.c
-@@ -707,11 +707,9 @@ g_menu_exporter_create_group (GMenuExporter *exporter)
- }
-
- static void
--g_menu_exporter_free (gpointer user_data)
-+g_menu_exporter_free (GMenuExporter *exporter)
- {
-- GMenuExporter *exporter = user_data;
--
-- g_menu_exporter_menu_free (exporter->root);
-+ g_clear_pointer (&exporter->root, g_menu_exporter_menu_free);
- g_clear_pointer (&exporter->peer_remote, g_menu_exporter_remote_free);
- g_hash_table_unref (exporter->remotes);
- g_hash_table_unref (exporter->groups);
-@@ -794,21 +792,16 @@ g_dbus_connection_export_menu_model (GDBusConnection *connection,
- guint id;
-
- exporter = g_slice_new0 (GMenuExporter);
--
-- id = g_dbus_connection_register_object (connection, object_path, org_gtk_Menus_get_interface (),
-- &vtable, exporter, g_menu_exporter_free, error);
--
-- if (id == 0)
-- {
-- g_slice_free (GMenuExporter, exporter);
-- return 0;
-- }
--
- exporter->connection = g_object_ref (connection);
- exporter->object_path = g_strdup (object_path);
- exporter->groups = g_hash_table_new (NULL, NULL);
- exporter->remotes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_menu_exporter_remote_free);
-- exporter->root = g_menu_exporter_group_add_menu (g_menu_exporter_create_group (exporter), menu);
-+
-+ id = g_dbus_connection_register_object (connection, object_path, org_gtk_Menus_get_interface (),
-+ &vtable, exporter, (GDestroyNotify) g_menu_exporter_free, error);
-+
-+ if (id != 0)
-+ exporter->root = g_menu_exporter_group_add_menu (g_menu_exporter_create_group (exporter), menu);
-
- return id;
- }
-diff --git a/gio/tests/gmenumodel.c b/gio/tests/gmenumodel.c
-index d75f36a297..22d1b4d61e 100644
---- a/gio/tests/gmenumodel.c
-+++ b/gio/tests/gmenumodel.c
-@@ -1159,6 +1159,42 @@ test_dbus_peer_subscriptions (void)
- #endif
- }
-
-+static void
-+test_dbus_export_error_handling (void)
-+{
-+ GRand *rand = NULL;
-+ RandomMenu *menu = NULL;
-+ GDBusConnection *bus;
-+ GError *local_error = NULL;
-+ guint id1, id2;
-+
-+ g_test_summary ("Test that error handling of menu model export failure works");
-+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3366");
-+
-+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
-+
-+ rand = g_rand_new_with_seed (g_test_rand_int ());
-+ menu = random_menu_new (rand, 2);
-+
-+ id1 = g_dbus_connection_export_menu_model (bus, "/", G_MENU_MODEL (menu), &local_error);
-+ g_assert_no_error (local_error);
-+ g_assert_cmpuint (id1, !=, 0);
-+
-+ /* Trigger a failure by trying to export on a path which is already in use */
-+ id2 = g_dbus_connection_export_menu_model (bus, "/", G_MENU_MODEL (menu), &local_error);
-+ g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS);
-+ g_assert_cmpuint (id2, ==, 0);
-+ g_clear_error (&local_error);
-+
-+ g_dbus_connection_unexport_menu_model (bus, id1);
-+
-+ while (g_main_context_iteration (NULL, FALSE));
-+
-+ g_clear_object (&menu);
-+ g_rand_free (rand);
-+ g_clear_object (&bus);
-+}
-+
- static gpointer
- do_modify (gpointer data)
- {
-@@ -1658,6 +1694,7 @@ main (int argc, char **argv)
- g_test_add_func ("/gmenu/dbus/threaded", test_dbus_threaded);
- g_test_add_func ("/gmenu/dbus/peer/roundtrip", test_dbus_peer_roundtrip);
- g_test_add_func ("/gmenu/dbus/peer/subscriptions", test_dbus_peer_subscriptions);
-+ g_test_add_func ("/gmenu/dbus/export/error-handling", test_dbus_export_error_handling);
- g_test_add_func ("/gmenu/attributes", test_attributes);
- g_test_add_func ("/gmenu/attributes/iterate", test_attribute_iter);
- g_test_add_func ("/gmenu/links", test_links);
---
-GitLab
-
-
-From 7a7137838e79e5a98e6f4eab6898e2a0dc6392cd Mon Sep 17 00:00:00 2001
-From: Philip Withnall <pwithnall@gnome.org>
-Date: Wed, 15 May 2024 14:00:09 +0100
-Subject: [PATCH 2/2] gactiongroupexporter: Fix memory problems on an error
- handling path
-
-Almost identically to the previous commit, fix a similar latent bug in
-`g_dbus_connection_export_action_group()`, which was not ready to handle
-the fledgling `GActionGroupExporter` being freed early on an error
-handling path.
-
-See the previous commit message for details of the approach.
-
-This includes a unit test.
-
-Signed-off-by: Philip Withnall <pwithnall@gnome.org>
-
-Fixes: #3366
----
- gio/gactiongroupexporter.c | 35 ++++++++++++++------------------
- gio/tests/actions.c | 41 ++++++++++++++++++++++++++++++++++++++
- 2 files changed, 56 insertions(+), 20 deletions(-)
-
-diff --git a/gio/gactiongroupexporter.c b/gio/gactiongroupexporter.c
-index 3ec1db224e..1e253ec88b 100644
---- a/gio/gactiongroupexporter.c
-+++ b/gio/gactiongroupexporter.c
-@@ -531,10 +531,8 @@ org_gtk_Actions_method_call (GDBusConnection *connection,
- }
-
- static void
--g_action_group_exporter_free (gpointer user_data)
-+g_action_group_exporter_free (GActionGroupExporter *exporter)
- {
-- GActionGroupExporter *exporter = user_data;
--
- g_signal_handlers_disconnect_by_func (exporter->action_group,
- g_action_group_exporter_action_added, exporter);
- g_signal_handlers_disconnect_by_func (exporter->action_group,
-@@ -616,15 +614,6 @@ g_dbus_connection_export_action_group (GDBusConnection *connection,
- }
-
- exporter = g_slice_new (GActionGroupExporter);
-- id = g_dbus_connection_register_object (connection, object_path, org_gtk_Actions, &vtable,
-- exporter, g_action_group_exporter_free, error);
--
-- if (id == 0)
-- {
-- g_slice_free (GActionGroupExporter, exporter);
-- return 0;
-- }
--
- exporter->context = g_main_context_ref_thread_default ();
- exporter->pending_changes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- exporter->pending_source = NULL;
-@@ -632,14 +621,20 @@ g_dbus_connection_export_action_group (GDBusConnection *connection,
- exporter->connection = g_object_ref (connection);
- exporter->object_path = g_strdup (object_path);
-
-- g_signal_connect (action_group, "action-added",
-- G_CALLBACK (g_action_group_exporter_action_added), exporter);
-- g_signal_connect (action_group, "action-removed",
-- G_CALLBACK (g_action_group_exporter_action_removed), exporter);
-- g_signal_connect (action_group, "action-state-changed",
-- G_CALLBACK (g_action_group_exporter_action_state_changed), exporter);
-- g_signal_connect (action_group, "action-enabled-changed",
-- G_CALLBACK (g_action_group_exporter_action_enabled_changed), exporter);
-+ id = g_dbus_connection_register_object (connection, object_path, org_gtk_Actions, &vtable,
-+ exporter, (GDestroyNotify) g_action_group_exporter_free, error);
-+
-+ if (id != 0)
-+ {
-+ g_signal_connect (action_group, "action-added",
-+ G_CALLBACK (g_action_group_exporter_action_added), exporter);
-+ g_signal_connect (action_group, "action-removed",
-+ G_CALLBACK (g_action_group_exporter_action_removed), exporter);
-+ g_signal_connect (action_group, "action-state-changed",
-+ G_CALLBACK (g_action_group_exporter_action_state_changed), exporter);
-+ g_signal_connect (action_group, "action-enabled-changed",
-+ G_CALLBACK (g_action_group_exporter_action_enabled_changed), exporter);
-+ }
-
- return id;
- }
-diff --git a/gio/tests/actions.c b/gio/tests/actions.c
-index a24c52c5e4..2b7a100fcf 100644
---- a/gio/tests/actions.c
-+++ b/gio/tests/actions.c
-@@ -1125,6 +1125,46 @@ test_dbus_export (void)
- session_bus_down ();
- }
-
-+static void
-+test_dbus_export_error_handling (void)
-+{
-+ GDBusConnection *bus = NULL;
-+ GSimpleActionGroup *group = NULL;
-+ GError *local_error = NULL;
-+ guint id1, id2;
-+
-+ g_test_summary ("Test that error handling of action group export failure works");
-+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3366");
-+
-+ session_bus_up ();
-+ bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
-+
-+ group = g_simple_action_group_new ();
-+ g_simple_action_group_add_entries (group,
-+ exported_entries,
-+ G_N_ELEMENTS (exported_entries),
-+ NULL);
-+
-+ id1 = g_dbus_connection_export_action_group (bus, "/", G_ACTION_GROUP (group), &local_error);
-+ g_assert_no_error (local_error);
-+ g_assert_cmpuint (id1, !=, 0);
-+
-+ /* Trigger a failure by trying to export on a path which is already in use */
-+ id2 = g_dbus_connection_export_action_group (bus, "/", G_ACTION_GROUP (group), &local_error);
-+ g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS);
-+ g_assert_cmpuint (id2, ==, 0);
-+ g_clear_error (&local_error);
-+
-+ g_dbus_connection_unexport_action_group (bus, id1);
-+
-+ while (g_main_context_iteration (NULL, FALSE));
-+
-+ g_object_unref (group);
-+ g_object_unref (bus);
-+
-+ session_bus_down ();
-+}
-+
- static gpointer
- do_export (gpointer data)
- {
-@@ -1448,6 +1488,7 @@ main (int argc, char **argv)
- g_test_add_func ("/actions/entries", test_entries);
- g_test_add_func ("/actions/parse-detailed", test_parse_detailed);
- g_test_add_func ("/actions/dbus/export", test_dbus_export);
-+ g_test_add_func ("/actions/dbus/export/error-handling", test_dbus_export_error_handling);
- g_test_add_func ("/actions/dbus/threaded", test_dbus_threaded);
- g_test_add_func ("/actions/dbus/bug679509", test_bug679509);
- g_test_add_func ("/actions/property", test_property_actions);
---
-GitLab
-
diff --git a/source/l/glib2/glib2.SlackBuild b/source/l/glib2/glib2.SlackBuild
index 6ad62007b..83bb0ba32 100755
--- a/source/l/glib2/glib2.SlackBuild
+++ b/source/l/glib2/glib2.SlackBuild
@@ -24,7 +24,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=glib2
VERSION=${VERSION:-$(echo glib-*.tar.?z* | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
-BUILD=${BUILD:-2}
+BUILD=${BUILD:-1}
NUMJOBS=${NUMJOBS:-" -j$(expr $(nproc) + 1) "}
@@ -77,9 +77,6 @@ find . \
\( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \
-exec chmod 644 {} \+
-# Patch regressions:
-cat $CWD/4073.patch | patch -p1 --verbose || exit 1
-
# Configure, build, and install:
export CFLAGS="$SLKCFLAGS"
export CXXFLAGS="$SLKCFLAGS"
diff --git a/source/l/imagemagick/imagemagick.SlackBuild b/source/l/imagemagick/imagemagick.SlackBuild
index 3c3e9e46d..5390ca1e4 100755
--- a/source/l/imagemagick/imagemagick.SlackBuild
+++ b/source/l/imagemagick/imagemagick.SlackBuild
@@ -23,7 +23,7 @@
cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=imagemagick
-BUILD=${BUILD:-1}
+BUILD=${BUILD:-2}
# NOTE: This is to cope with ImageMagick version numbers such as 5.4.7-4,
# which occur fairly often (but not always). If these numbers are all the same,
diff --git a/source/l/pango/pango.SlackBuild b/source/l/pango/pango.SlackBuild
index b18eef80b..c083bee05 100755
--- a/source/l/pango/pango.SlackBuild
+++ b/source/l/pango/pango.SlackBuild
@@ -1,6 +1,6 @@
#!/bin/bash
-# Copyright 2008, 2009, 2010, 2011, 2015, 2017, 2018, 2019 Patrick J. Volkerding, Sebeka, MN, USA
+# Copyright 2008, 2009, 2010, 2011, 2015, 2017, 2018, 2019, 2024 Patrick J. Volkerding, Sebeka, MN, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
@@ -94,7 +94,7 @@ meson setup \
--sysconfdir=/etc \
--localstatedir=/var \
--buildtype=release \
- -Dgtk_doc=false \
+ -Ddocumentation=false \
.. || exit 1
"${NINJA:=ninja}" $NUMJOBS || exit 1
DESTDIR=$PKG $NINJA install || exit 1
diff --git a/source/l/python-packaging/python-packaging.SlackBuild b/source/l/python-packaging/python-packaging.SlackBuild
index e66d2fe91..82a5cdd12 100755
--- a/source/l/python-packaging/python-packaging.SlackBuild
+++ b/source/l/python-packaging/python-packaging.SlackBuild
@@ -25,7 +25,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=python-packaging
VERSION=${VERSION:-$(echo packaging-*.tar.?z | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
-BUILD=${BUILD:-2}
+BUILD=${BUILD:-1}
SRCNAM=packaging
diff --git a/source/n/epic5/epic5.SlackBuild b/source/n/epic5/epic5.SlackBuild
index a7888aa28..8d26fa653 100755
--- a/source/n/epic5/epic5.SlackBuild
+++ b/source/n/epic5/epic5.SlackBuild
@@ -26,7 +26,7 @@ PKGNAM=epic5
VERSION=${VERSION:-$(echo $PKGNAM-*.tar.xz | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
EPICVER=5
HELPFILE=current
-BUILD=${BUILD:-8}
+BUILD=${BUILD:-9}
## Default to no Ruby support, since it seems that ruby-2.7.0 is not compatible.
## Patches to fix this are welcome, otherwise we'll keep an eye on upstream.
diff --git a/source/n/irssi/irssi.SlackBuild b/source/n/irssi/irssi.SlackBuild
index 4437ed256..518529f2f 100755
--- a/source/n/irssi/irssi.SlackBuild
+++ b/source/n/irssi/irssi.SlackBuild
@@ -28,7 +28,7 @@ PKG=$TMP/package-irssi
VERSION=${VERSION:-$(echo irssi-*.tar.xz | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
DIRCD=${VERSION}
-BUILD=${BUILD:-2}
+BUILD=${BUILD:-3}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
diff --git a/source/n/net-snmp/net-snmp.SlackBuild b/source/n/net-snmp/net-snmp.SlackBuild
index 7b2a899cd..0d91fadc3 100755
--- a/source/n/net-snmp/net-snmp.SlackBuild
+++ b/source/n/net-snmp/net-snmp.SlackBuild
@@ -24,7 +24,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=net-snmp
VERSION=${VERSION:-$(echo $PKGNAM-*.tar.?z | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
-BUILD=${BUILD:-4}
+BUILD=${BUILD:-5}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
diff --git a/source/n/ntp/ntp.SlackBuild b/source/n/ntp/ntp.SlackBuild
index 10408ee42..5a09ccc2e 100755
--- a/source/n/ntp/ntp.SlackBuild
+++ b/source/n/ntp/ntp.SlackBuild
@@ -24,7 +24,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=ntp
VERSION=${VERSION:-$(echo $PKGNAM-*.tar.?z* | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
-BUILD=${BUILD:-2}
+BUILD=${BUILD:-3}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
diff --git a/source/n/ntp/ntp.logrotate b/source/n/ntp/ntp.logrotate
index 37fd0be15..99e02e6c7 100644
--- a/source/n/ntp/ntp.logrotate
+++ b/source/n/ntp/ntp.logrotate
@@ -3,6 +3,6 @@
missingok
rotate 4
postrotate
- ! [ -x /etc/rc.d/rc.ntpd ] || /etc/rc.d/rc.ntpd restart
+ [ ! -x /etc/rc.d/rc.ntpd ] || /etc/rc.d/rc.ntpd restart
endscript
}
diff --git a/source/n/openldap/openldap.SlackBuild b/source/n/openldap/openldap.SlackBuild
index 783526f36..745b8d301 100755
--- a/source/n/openldap/openldap.SlackBuild
+++ b/source/n/openldap/openldap.SlackBuild
@@ -25,7 +25,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=openldap
VERSION=${VERSION:-$(echo $PKGNAM-*.tar.?z | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
-BUILD=${BUILD:-1}
+BUILD=${BUILD:-2}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
diff --git a/source/x/fcitx5-gtk/slack-desc b/source/x/fcitx5-gtk/slack-desc
index 8d3ae5613..e65f6337b 100644
--- a/source/x/fcitx5-gtk/slack-desc
+++ b/source/x/fcitx5-gtk/slack-desc
@@ -6,7 +6,7 @@
# customary to leave one space after the ':' except on otherwise blank lines.
|-----handy-ruler------------------------------------------------------|
-fcitx5-gtk: fcitx5-gtk (Gtk IM Module for Fcitx5)
+fcitx5-gtk: fcitx5-gtk (Gtk IM Module for fcitx5)
fcitx5-gtk:
fcitx5-gtk: Gtk IM module for fcitx5 and glib based dbus client library.
fcitx5-gtk:
diff --git a/source/x/fcitx5-hangul/slack-desc b/source/x/fcitx5-hangul/slack-desc
index d03dc299e..96365fb6c 100644
--- a/source/x/fcitx5-hangul/slack-desc
+++ b/source/x/fcitx5-hangul/slack-desc
@@ -8,7 +8,7 @@
|-----handy-ruler------------------------------------------------------|
fcitx5-hangul: fcitx5-hangul (Hangul wrapper for fcitx5)
fcitx5-hangul:
-fcitx5-hangul: Hangul Wrapper for Fcitx.
+fcitx5-hangul: Hangul Wrapper for fcitx5.
fcitx5-hangul:
fcitx5-hangul: Homepage: https://fcitx-im.org/wiki/Fcitx_5
fcitx5-hangul:
diff --git a/source/x/fcitx5-kkc/slack-desc b/source/x/fcitx5-kkc/slack-desc
index abe90ce0b..7ebaf35b4 100644
--- a/source/x/fcitx5-kkc/slack-desc
+++ b/source/x/fcitx5-kkc/slack-desc
@@ -6,9 +6,9 @@
# customary to leave one space after the ':' except on otherwise blank lines.
|-----handy-ruler------------------------------------------------------|
-fcitx5-kkc: fcitx5-kkc (Japanese Kana Kanji Engine for Fcitx5)
+fcitx5-kkc: fcitx5-kkc (Japanese Kana Kanji Engine for fcitx5)
fcitx5-kkc:
-fcitx5-kkc: Fcitx-kkc is a Kana Kanji engine for Fcitx. It provides Japanese
+fcitx5-kkc: Fcitx-kkc is a Kana Kanji engine for fcitx5. It provides Japanese
fcitx5-kkc: input method using libkkc.
fcitx5-kkc:
fcitx5-kkc: Homepage: https://fcitx-im.org/wiki/Fcitx_5
diff --git a/source/x/fcitx5-qt/slack-desc b/source/x/fcitx5-qt/slack-desc
index 53a5ceadb..5cfe701fe 100644
--- a/source/x/fcitx5-qt/slack-desc
+++ b/source/x/fcitx5-qt/slack-desc
@@ -6,9 +6,9 @@
# customary to leave one space after the ':' except on otherwise blank lines.
|-----handy-ruler------------------------------------------------------|
-fcitx5-qt: fcitx5-qt (Qt IM Module for Fcitx5)
+fcitx5-qt: fcitx5-qt (Qt IM Module for fcitx5)
fcitx5-qt:
-fcitx5-qt: Qt IM Module for Fcitx5.
+fcitx5-qt: Qt IM Module for fcitx5.
fcitx5-qt:
fcitx5-qt: Homepage: https://fcitx-im.org/wiki/Fcitx_5
fcitx5-qt:
diff --git a/source/x/fcitx5-sayura/slack-desc b/source/x/fcitx5-sayura/slack-desc
index 40aeb4407..aace33ea9 100644
--- a/source/x/fcitx5-sayura/slack-desc
+++ b/source/x/fcitx5-sayura/slack-desc
@@ -8,7 +8,7 @@
|-----handy-ruler------------------------------------------------------|
fcitx5-sayura: fcitx5-sayura (Sinhala input method for fcitx5)
fcitx5-sayura:
-fcitx5-sayura: Fcitx-Sayura is a Sinhala input method for Fcitx.
+fcitx5-sayura: Fcitx-Sayura is a Sinhala input method for fcitx5.
fcitx5-sayura:
fcitx5-sayura: Homepage: https://fcitx-im.org/wiki/Fcitx_5
fcitx5-sayura:
diff --git a/source/x/fcitx5-table-extra/slack-desc b/source/x/fcitx5-table-extra/slack-desc
index a887dcd18..19449fbe3 100644
--- a/source/x/fcitx5-table-extra/slack-desc
+++ b/source/x/fcitx5-table-extra/slack-desc
@@ -8,8 +8,8 @@
|-----handy-ruler------------------------------------------------------|
fcitx5-table-extra: fcitx5-table-extra (Extra tables for fcitx5)
fcitx5-table-extra:
-fcitx5-table-extra: fcitx5-table-extra provides extra tables for Fcitx, including Boshiamy,
-fcitx5-table-extra: Zhengma, Cangjie, and Quick.
+fcitx5-table-extra: fcitx5-table-extra provides extra tables for fcitx5, including
+fcitx5-table-extra: Boshiamy, Zhengma, Cangjie, and Quick.
fcitx5-table-extra:
fcitx5-table-extra: Homepage: https://fcitx-im.org/wiki/Fcitx_5
fcitx5-table-extra:
diff --git a/source/x/fcitx5-table-other/slack-desc b/source/x/fcitx5-table-other/slack-desc
index 2b6224637..57f555464 100644
--- a/source/x/fcitx5-table-other/slack-desc
+++ b/source/x/fcitx5-table-other/slack-desc
@@ -8,7 +8,7 @@
|-----handy-ruler------------------------------------------------------|
fcitx5-table-other: fcitx5-table-other (Other tables for fcitx5)
fcitx5-table-other:
-fcitx5-table-other: fcitx5-table-other provides some other tables for Fcitx, forked from
+fcitx5-table-other: fcitx5-table-other provides some other tables for fcitx5, forked from
fcitx5-table-other: ibus-table-others and scim-tables.
fcitx5-table-other:
fcitx5-table-other: Homepage: https://fcitx-im.org/wiki/Fcitx_5
diff --git a/source/x/fcitx5-unikey/slack-desc b/source/x/fcitx5-unikey/slack-desc
index 6c92149ab..088babfb5 100644
--- a/source/x/fcitx5-unikey/slack-desc
+++ b/source/x/fcitx5-unikey/slack-desc
@@ -8,7 +8,7 @@
|-----handy-ruler------------------------------------------------------|
fcitx5-unikey: fcitx5-unikey (Vietnamese input support for fcitx5)
fcitx5-unikey:
-fcitx5-unikey: Unikey (Vietnamese Input Method) engine support for Fcitx.
+fcitx5-unikey: Unikey (Vietnamese Input Method) engine support for fcitx5.
fcitx5-unikey:
fcitx5-unikey: Homepage: https://fcitx-im.org/wiki/Fcitx_5
fcitx5-unikey:
diff --git a/source/xap/hexchat/hexchat.SlackBuild b/source/xap/hexchat/hexchat.SlackBuild
index d1baf6d30..75d706127 100755
--- a/source/xap/hexchat/hexchat.SlackBuild
+++ b/source/xap/hexchat/hexchat.SlackBuild
@@ -24,7 +24,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=hexchat
VERSION=${VERSION:-$(echo $PKGNAM-*.tar.?z | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
-BUILD=${BUILD:-2}
+BUILD=${BUILD:-3}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
diff --git a/source/xap/pidgin/pidgin.SlackBuild b/source/xap/pidgin/pidgin.SlackBuild
index 627d1b1bf..6fab57a2d 100755
--- a/source/xap/pidgin/pidgin.SlackBuild
+++ b/source/xap/pidgin/pidgin.SlackBuild
@@ -25,7 +25,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=pidgin
VERSION=${VERSION:-$(echo $PKGNAM-2.*.tar.?z | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
PIDGINENC=${PIDGINENC:-3.1}
-BUILD=${BUILD:-1}
+BUILD=${BUILD:-2}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
diff --git a/source/xap/rxvt-unicode/rxvt-unicode.SlackBuild b/source/xap/rxvt-unicode/rxvt-unicode.SlackBuild
index 0135cdab3..b161d2d34 100755
--- a/source/xap/rxvt-unicode/rxvt-unicode.SlackBuild
+++ b/source/xap/rxvt-unicode/rxvt-unicode.SlackBuild
@@ -24,7 +24,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=rxvt-unicode
VERSION=${VERSION:-$(echo $PKGNAM-*.tar.?z | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
-BUILD=${BUILD:-2}
+BUILD=${BUILD:-3}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
diff --git a/source/xap/xscreensaver/xscreensaver.SlackBuild b/source/xap/xscreensaver/xscreensaver.SlackBuild
index ffc957672..1e287dcd8 100755
--- a/source/xap/xscreensaver/xscreensaver.SlackBuild
+++ b/source/xap/xscreensaver/xscreensaver.SlackBuild
@@ -24,7 +24,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=xscreensaver
VERSION=${VERSION:-$(echo xscreensaver-*.tar.?z | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
-BUILD=${BUILD:-2}
+BUILD=${BUILD:-1}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
@@ -71,20 +71,6 @@ rm -rf xscreensaver-$VERSION
tar xvf $CWD/xscreensaver-$VERSION.tar.?z || exit 1
cd xscreensaver-$VERSION
-if [ -L /lib${LIBDIRSUFFIX}/libpam.so.? ]; then
- USE_PAM="--with-pam"
- unset USE_SHADOW
-else
- ## NOTE: The patch below (and support for setgid shadow) is broken and
- ## unmaintained. But the broken bits will be left as hints for anyone
- ## down the line who might care.
- # Allow xscreensaver to work setgid shadow. I'd rather avoid requiring
- # setuid root on this if at all possible...
- #zcat $CWD/xscreensaver.setuid.diff.gz | patch -p1 --verbose --backup --suffix=.orig || exit 1
- unset USE_PAM
- USE_SHADOW="--with-shadow"
-fi
-
# Add support for the electricsheep distributed screensaver:
zcat $CWD/xscreensaver.electricsheep.diff.gz | patch -p1 --verbose --backup --suffix=.orig || exit 1
@@ -110,8 +96,7 @@ CXXFLAGS="$SLKCFLAGS" \
--mandir=/usr/man \
--with-app-defaults=/etc/X11/app-defaults \
--with-text-file=/usr/doc/netdate/COPYRIGHT \
- $USE_SHADOW \
- $USE_PAM \
+ --with-pam \
--without-kerberos \
--with-jpeg \
--with-gl \
@@ -121,22 +106,10 @@ CXXFLAGS="$SLKCFLAGS" \
make $NUMJOBS || make || exit 1
make install_prefix=$PKG install-strip || exit 1
-if [ -z $USE_PAM ]; then
- # Needed for password unlock:
- chown root:shadow $PKG/usr/bin/xscreensaver
- chmod 2751 $PKG/usr/bin/xscreensaver
-else
- ## Commenting out the chmod below, since as of v6.00 this binary is no longer
- ## made setuid at installation. But if that changes, we'll go along with it
- ## since jwz says it may be required to prevent OOM killer abuse from
- ## unlocking the screen.
- # No special perms needed with PAM:
- #chmod 755 $PKG/usr/bin/xscreensaver
- mkdir -p $PKG/etc/pam.d
- cat $CWD/xscreensaver.pam > $PKG/etc/pam.d/xscreensaver.new
- mkdir -p $PKG/install
- zcat $CWD/doinst.sh.gz > $PKG/install/doinst.sh
-fi
+# No special perms needed with PAM:
+#chmod 755 $PKG/usr/bin/xscreensaver
+mkdir -p $PKG/etc/pam.d
+cat $CWD/xscreensaver.pam > $PKG/etc/pam.d/xscreensaver.new
# This is needed for the menus:
mkdir -p $PKG/usr/share/pixmaps
@@ -168,6 +141,7 @@ fi
cat $CWD/xscreensaver-getimage-file-5.14 > $PKG/usr/bin/xscreensaver-getimage-file
mkdir -p $PKG/install
+zcat $CWD/doinst.sh.gz > $PKG/install/doinst.sh
cat $CWD/slack-desc > $PKG/install/slack-desc
cd $PKG
diff --git a/source/xap/xscreensaver/xscreensaver.setuid.diff b/source/xap/xscreensaver/xscreensaver.setuid.diff
deleted file mode 100644
index c6810af55..000000000
--- a/source/xap/xscreensaver/xscreensaver.setuid.diff
+++ /dev/null
@@ -1,179 +0,0 @@
---- ./driver/setuid.c.orig 2006-02-08 20:28:38.000000000 -0600
-+++ ./driver/setuid.c 2006-04-04 16:48:08.000000000 -0500
-@@ -1,5 +1,5 @@
- /* setuid.c --- management of runtime privileges.
-- * xscreensaver, Copyright (c) 1993-1998, 2005 Jamie Zawinski <jwz@jwz.org>
-+ * xscreensaver, Copyright (c) 1993-1998 Jamie Zawinski <jwz@jwz.org>
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
-@@ -41,7 +41,7 @@
- struct group *g = 0;
- p = getpwuid (uid);
- g = getgrgid (gid);
-- sprintf (buf, "%.100s/%.100s (%ld/%ld)",
-+ sprintf (buf, "%s/%s (%ld/%ld)",
- (p && p->pw_name ? p->pw_name : "???"),
- (g && g->gr_name ? g->gr_name : "???"),
- (long) uid, (long) gid);
-@@ -74,50 +74,11 @@
- }
-
-
--/* Returns true if we need to call setgroups().
--
-- Without calling setgroups(), the process will retain any supplementary
-- gids associated with the uid, e.g.:
--
-- % groups root
-- root : root bin daemon sys adm disk wheel
--
-- However, setgroups() can only be called by root, and returns EPERM
-- for other users even if the call would be a no-op (e.g., setting the
-- group list to the current list.) So, to avoid that spurious error,
-- before calling setgroups() we first check whether the current list
-- of groups contains only one element, our target group. If so, we
-- don't need to call setgroups().
-- */
--static int
--setgroups_needed_p (uid_t target_group)
--{
-- gid_t groups[1024];
-- int n, size;
-- size = sizeof(groups) / sizeof(gid_t);
-- n = getgroups (size - 1, groups);
-- if (n < 0)
-- {
-- char buf [1024];
-- sprintf (buf, "%s: getgroups(%ld, ...)", blurb(), (long int)(size - 1));
-- perror (buf);
-- return 1;
-- }
-- else if (n == 0) /* an empty list means only egid is in effect. */
-- return 0;
-- else if (n == 1 && groups[0] == target_group) /* one element, the target */
-- return 0;
-- else /* more than one, or the wrong one. */
-- return 1;
--}
--
--
- static int
- set_ids_by_number (uid_t uid, gid_t gid, char **message_ret)
- {
- int uid_errno = 0;
- int gid_errno = 0;
-- int sgs_errno = 0;
- struct passwd *p = getpwuid (uid);
- struct group *g = getgrgid (gid);
-
-@@ -136,11 +97,6 @@
- if (uid == (uid_t) -1) uid = (uid_t) -2;
-
- errno = 0;
-- if (setgroups_needed_p (gid) &&
-- setgroups (1, &gid) < 0)
-- sgs_errno = errno ? errno : -1;
--
-- errno = 0;
- if (setgid (gid) != 0)
- gid_errno = errno ? errno : -1;
-
-@@ -148,10 +104,10 @@
- if (setuid (uid) != 0)
- uid_errno = errno ? errno : -1;
-
-- if (uid_errno == 0 && gid_errno == 0 && sgs_errno == 0)
-+ if (uid_errno == 0 && gid_errno == 0)
- {
- static char buf [1024];
-- sprintf (buf, "changed uid/gid to %.100s/%.100s (%ld/%ld).",
-+ sprintf (buf, "changed uid/gid to %s/%s (%ld/%ld).",
- (p && p->pw_name ? p->pw_name : "???"),
- (g && g->gr_name ? g->gr_name : "???"),
- (long) uid, (long) gid);
-@@ -162,71 +118,28 @@
- else
- {
- char buf [1024];
-- gid_t groups[1024];
-- int n, size;
--
-- if (sgs_errno)
-- {
-- sprintf (buf, "%s: couldn't setgroups to %.100s (%ld)",
-- blurb(),
-- (g && g->gr_name ? g->gr_name : "???"),
-- (long) gid);
-- if (sgs_errno == -1)
-- fprintf(stderr, "%s: unknown error\n", buf);
-- else
-- {
-- errno = sgs_errno;
-- perror(buf);
-- }
--
-- fprintf (stderr, "%s: effective group list: ", blurb());
-- size = sizeof(groups) / sizeof(gid_t);
-- n = getgroups (size - 1, groups);
-- if (n < 0)
-- fprintf (stderr, "unknown!\n");
-- else
-- {
-- int i;
-- fprintf (stderr, "[");
-- for (i = 0; i < n; i++)
-- {
-- g = getgrgid (groups[i]);
-- if (i > 0) fprintf (stderr, ", ");
-- if (g && g->gr_name) fprintf (stderr, "%s", g->gr_name);
-- else fprintf (stderr, "%ld", (long) groups[i]);
-- }
-- fprintf (stderr, "]\n");
-- }
-- }
--
- if (gid_errno)
- {
-- sprintf (buf, "%s: couldn't set gid to %.100s (%ld)",
-+ sprintf (buf, "%s: couldn't set gid to %s (%ld)",
- blurb(),
- (g && g->gr_name ? g->gr_name : "???"),
- (long) gid);
- if (gid_errno == -1)
- fprintf(stderr, "%s: unknown error\n", buf);
- else
-- {
-- errno = gid_errno;
-- perror(buf);
-- }
-+ perror(buf);
- }
-
- if (uid_errno)
- {
-- sprintf (buf, "%s: couldn't set uid to %.100s (%ld)",
-+ sprintf (buf, "%s: couldn't set uid to %s (%ld)",
- blurb(),
- (p && p->pw_name ? p->pw_name : "???"),
- (long) uid);
- if (uid_errno == -1)
- fprintf(stderr, "%s: unknown error\n", buf);
- else
-- {
-- errno = uid_errno;
-- perror(buf);
-- }
-+ perror(buf);
- }
-
- return -1;
-@@ -350,7 +263,7 @@
- !strcmp (p->pw_name, "games"))
- {
- static char buf [1024];
-- sprintf (buf, "running as %.100s",
-+ sprintf (buf, "running as %s",
- (p && p->pw_name && *p->pw_name
- ? p->pw_name : "<unknown>"));
- si->nolock_reason = buf;