#!/bin/sh -
#
# Alex Kozlov <ak@FreeBSD.org> , 2008 - 2024
# Public domain or 2-clause BSD License
#

PATH=/bin:/usr/bin
LANG=C

parse_options()
{
	local OPT OPTARG OPTIND

	while getopts aw OPT; do
		# escape meta
		OPTARG=${OPTARG%%[;\\\$]*}

		case ${OPT} in
		a)	opt_all=yes ;;
		w)	opt_skip_white=yes ;;
		*)	usage ;;
		esac
	done

	OPTC=$((${OPTIND} - 1))
}

usage()
{
	echo "usage: ${0##*/} [-aw] [portsdir]"
	echo '	-a all checks'
	echo '	-w disable whitelists'
	echo
	exit 1
}


#
# MAIN
#

parse_options ${1+"$@"}
shift ${OPTC}

_PORTSDIR=${1-'/usr/ports'}
# normalize
_PORTSDIR=$(realpath "${_PORTSDIR}")
[ -d ${_PORTSDIR} ] || usage

[ -n "$2" ] && usage

echo empty files and directories:
find "${_PORTSDIR}" -empty
echo

echo nonstandard directories:
whitelist="
/files
/scripts"

whitelist_userdir=E_m_P_t_Y_s_E_t

# validate whitelist
for name in ${whitelist_userdir}; do
	[ ${whitelist_userdir} == E_m_P_t_Y_s_E_t -o -d "${_PORTSDIR}/${name}" ] || \
		echo whitelist: ${name} doesn\'t exist
done

# convert to grep regexp
whitelist="$(echo ${whitelist} | sed -e 's/ /|/g')"

if [ -n "${opt_skip_white}" ]; then
	whitelist_userdir=E_m_P_t_Y_s_E_t
else
	# convert to grep regexp
	whitelist_userdir="$(echo ${whitelist_userdir} | sed -e 's/ /|/g')"
fi

# no maxdepth
find "${_PORTSDIR}" -mindepth 3 -type d | \
	grep -vE "${whitelist}|${whitelist_userdir}"
echo

echo nonstandard files:
whitelist="
${_PORTSDIR}/Templates
${_PORTSDIR}/Tools
${_PORTSDIR}/.hooks
${_PORTSDIR}/Mk/Features
${_PORTSDIR}/Mk/Uses
${_PORTSDIR}/Mk/Scripts
${_PORTSDIR}/Mk/Wrappers
${_PORTSDIR}/distfiles
${_PORTSDIR}/packages
Makefile$
distinfo$
pkg-help$
pkg-plist$
pkg-message$
pkg-descr$
pkg-install$
pkg-post-install$
pkg-deinstall$
pkg-pre-deinstall$
Makefile.common$
Makefile.crates$
pkg-plist.i386$
pkg-plist.amd64$
pkg-plist.aarch64$"

whitelist_userfile="
accessibility/libqaccessibilityclient/pkg-plist.qt5
accessibility/libqaccessibilityclient/pkg-plist.qt6
audio/fluidplug-lv2/Makefile.list
audio/timidity++/Makefile.interface
benchmarks/linux-unigine-superposition/pkg-license
benchmarks/linux-unigine-valley/pkg-license
cad/kicad-devel/Makefile.git_rev
cad/kicad-library-footprints-devel/Makefile.git_rev
cad/kicad-library-packages3d-devel/Makefile.git_rev
cad/kicad-library-symbols-devel/Makefile.git_rev
cad/kicad-library-templates-devel/Makefile.git_rev
cad/ngspice_rework/pkg-plist-shlib
chinese/ttfm/Makefile.ttf
comms/hackrf-devel/Makefile.git_rev
comms/opencbm/Makefile.inc
comms/owfs/Makefile.options
databases/firebird30-server/pkg-install-server
databases/firebird30-server/pkg-plist.client
databases/firebird40-server/pkg-install-server
databases/firebird40-server/pkg-plist.client
databases/linux-oracle-instantclient-basic/distinfo.amd64
databases/linux-oracle-instantclient-basic/distinfo.i386
databases/linux-oracle-instantclient-sdk/distinfo.amd64
databases/linux-oracle-instantclient-sdk/distinfo.i386
databases/phpmyadmin/pkg-plist-chunk
databases/phpmyadmin5/pkg-plist-chunk
databases/postgresql-promscale/crates.mk
databases/postgresql12-server/pkg-install-server
databases/postgresql12-server/pkg-plist-client
databases/postgresql12-server/pkg-plist-contrib
databases/postgresql12-server/pkg-plist-plperl
databases/postgresql12-server/pkg-plist-plpython
databases/postgresql12-server/pkg-plist-pltcl
databases/postgresql12-server/pkg-plist-server
databases/postgresql13-server/pkg-install-server
databases/postgresql13-server/pkg-plist-client
databases/postgresql13-server/pkg-plist-contrib
databases/postgresql13-server/pkg-plist-plperl
databases/postgresql13-server/pkg-plist-plpython
databases/postgresql13-server/pkg-plist-pltcl
databases/postgresql13-server/pkg-plist-server
databases/postgresql14-server/pkg-install-server
databases/postgresql14-server/pkg-plist-client
databases/postgresql14-server/pkg-plist-contrib
databases/postgresql14-server/pkg-plist-plperl
databases/postgresql14-server/pkg-plist-plpython
databases/postgresql14-server/pkg-plist-pltcl
databases/postgresql14-server/pkg-plist-server
databases/postgresql15-server/pkg-install-server
databases/postgresql15-server/pkg-plist-client
databases/postgresql15-server/pkg-plist-contrib
databases/postgresql15-server/pkg-plist-plperl
databases/postgresql15-server/pkg-plist-plpython
databases/postgresql15-server/pkg-plist-pltcl
databases/postgresql15-server/pkg-plist-server
databases/postgresql16-server/pkg-install-server
databases/postgresql16-server/pkg-plist-client
databases/postgresql16-server/pkg-plist-contrib
databases/postgresql16-server/pkg-plist-plperl
databases/postgresql16-server/pkg-plist-plpython
databases/postgresql16-server/pkg-plist-pltcl
databases/postgresql16-server/pkg-plist-server
databases/qt6-base_sqldriver/pkg-plist.mysql
databases/qt6-base_sqldriver/pkg-plist.odbc
databases/qt6-base_sqldriver/pkg-plist.psql
databases/qt6-base_sqldriver/pkg-plist.sqlite
databases/sqlite3/pkg-descr-tea
deskutils/gnome-shell-extra-extensions/pkg-message.slaves
deskutils/libportal/pkg-plist.gtk3
deskutils/libportal/pkg-plist.gtk4
deskutils/libportal/pkg-plist.qt5
devel/appstream/pkg-descr.compose
devel/appstream/pkg-descr.qt6
devel/avr-libc/pkg-plist.doc
devel/binutils/pkg-plist-aarch64
devel/binutils/pkg-plist-aarch64-none-elf
devel/binutils/pkg-plist-arm-gnueabi
devel/binutils/pkg-plist-arm-none-eabi
devel/binutils/pkg-plist-avr
devel/binutils/pkg-plist-mingw32
devel/binutils/pkg-plist-mips
devel/binutils/pkg-plist-mips64
devel/binutils/pkg-plist-powerpc
devel/binutils/pkg-plist-powerpc64
devel/binutils/pkg-plist-powerpc64le
devel/binutils/pkg-plist-riscv32-unknown-elf
devel/binutils/pkg-plist-riscv64
devel/binutils/pkg-plist-riscv64-none-elf
devel/binutils/pkg-plist-s390x
devel/binutils/pkg-plist-sparc64
devel/boost-all/common.mk
devel/boost-all/compiled.mk
devel/boost-all/pkg-message.python
devel/boost-all/pkg-message.threads
devel/bugzilla44/Makefile.options
devel/bugzilla50/Makefile.options
devel/ccache/Makefile.compilers
devel/compiler-rt/Makefile.svn_rev
devel/electron25/Makefile.version
devel/electron26/Makefile.version
devel/electron27/Makefile.version
devel/eric6/Makefile.inc
devel/eric6/bsd.eric6.mk
devel/freebsd-gcc12/pkg-plist.arm
devel/freebsd-gcc12/pkg-plist.arm_gnueabi
devel/freebsd-gcc12/pkg-plist.powerpc
devel/freebsd-gcc12/pkg-plist.powerpc64
devel/freebsd-gcc12/pkg-plist.riscv64
devel/freebsd-gcc13/pkg-plist.arm
devel/freebsd-gcc13/pkg-plist.arm_gnueabi
devel/freebsd-gcc13/pkg-plist.powerpc
devel/freebsd-gcc13/pkg-plist.powerpc64
devel/freebsd-gcc13/pkg-plist.riscv64
devel/freebsd-sysroot/pkg-plist.armv7
devel/freebsd-sysroot/pkg-plist.powerpc
devel/freebsd-sysroot/pkg-plist.powerpc64
devel/freebsd-sysroot/pkg-plist.powerpc64le
devel/freebsd-sysroot/pkg-plist.powerpcspe
devel/freebsd-sysroot/pkg-plist.riscv64
devel/gfold/bsd.gfold.mk
devel/git/pkg-descr-tiny
devel/git/pkg-descr-lite
devel/hs-haskell-language-server/Makefile.cabal.default
devel/hs-haskell-language-server/Makefile.cabal.ghc810
devel/hs-haskell-language-server/Makefile.cabal.ghc92
devel/llvm-cheri/Makefile.COMMANDS
devel/llvm-cheri/Makefile.MAN1SRCS
devel/llvm-cheri/Makefile.snapshot
devel/llvm-cheriot/Makefile.COMMANDS
devel/llvm-cheriot/Makefile.MAN1SRCS
devel/llvm-cheriot/Makefile.snapshot
devel/llvm-devel/Makefile.COMMANDS
devel/llvm-devel/Makefile.LICENSE
devel/llvm-devel/Makefile.MAN1SRCS
devel/llvm-devel/Makefile.RUNTIMES
devel/llvm-devel/Makefile.snapshot
devel/llvm-morello/Makefile.COMMANDS
devel/llvm-morello/Makefile.MAN1SRCS
devel/llvm-morello/Makefile.snapshot
devel/llvm10/Makefile.COMMANDS
devel/llvm10/Makefile.MAN1SRCS
devel/llvm11/Makefile.COMMANDS
devel/llvm11/Makefile.MAN1SRCS
devel/llvm12/Makefile.COMMANDS
devel/llvm12/Makefile.MAN1SRCS
devel/llvm13/Makefile.COMMANDS
devel/llvm13/Makefile.MAN1SRCS
devel/llvm14/Makefile.COMMANDS
devel/llvm14/Makefile.MAN1SRCS
devel/llvm15/Makefile.COMMANDS
devel/llvm15/Makefile.MAN1SRCS
devel/llvm16/Makefile.COMMANDS
devel/llvm16/Makefile.MAN1SRCS
devel/llvm16/Makefile.RUNTIMES
devel/llvm17/Makefile.COMMANDS
devel/llvm17/Makefile.MAN1SRCS
devel/llvm17/Makefile.RUNTIMES
devel/msbuild/nupkg-roslyn_tools
devel/msbuild/nupkg-symreader_converter
devel/msbuild/nupkg-nuget
devel/msbuild/nupkg-dotnet_core
devel/msbuild/nupkg-roslyn
devel/opencl-clang/distinfo.llvm11
devel/opencl-clang/distinfo.llvm12
devel/opencl-clang/distinfo.llvm13
devel/opencl-clang/distinfo.llvm14
devel/opencl-clang/distinfo.llvm15
devel/opencl-clang/distinfo.llvm16
devel/opencl-clang/distinfo.llvm17
devel/p4/Makefile.inc
devel/pear/bsd.pear.channel.mk
devel/pear/pear-deinstall.in
devel/pear/pear-install
devel/py-celery-singleton/Makefile.new
devel/qt5/Makefile.sqldrivers
devel/schilybase/Makefile.master
devel/sdl12/pkg-message.linjoy
devel/sdl12/pkg-message.vgl
devel/snitch/pkg-plist-headers-only
devel/spirv-llvm-translator/distinfo.llvm11
devel/spirv-llvm-translator/distinfo.llvm12
devel/spirv-llvm-translator/distinfo.llvm13
devel/spirv-llvm-translator/distinfo.llvm14
devel/spirv-llvm-translator/distinfo.llvm15
devel/spirv-llvm-translator/distinfo.llvm16
devel/spirv-llvm-translator/distinfo.llvm17
devel/subversion/Makefile.addons
devel/thrift/bsd.thrift.mk
devel/tig/pkg-message-git
dns/bind-tools/pkg-plist-devel
dns/doh-proxy/Makefile.crates
editors/emacs/pkg-descr-canna
editors/libreoffice/Makefile.i18n
editors/libreoffice/pkg-descr.i18n
editors/vim/pkg-plist-tiny
emulators/dolphin-emu/Makefile.tuples
emulators/pcsx2/Makefile.tuples
emulators/qemu/pkg-descr-ga
emulators/qemu/pkg-descr-tools
emulators/qemu/pkg-plist-ga
emulators/qemu/pkg-plist-tools
emulators/qemu/pkg-message.guest-agent
emulators/qemu-cheri/Makefile.snapshot
emulators/qemu7/pkg-descr-tools
emulators/qemu7/pkg-plist-tools
french/aster/bsd.aster.mk
ftp/termscp/bsd.termscp.mk
games/digger-vgl/pkg-message.sound
games/doom-data/Makefile.include
games/openarena/Makefile.include
games/prboom-plus/Makefile.include
games/quake-data/Makefile.include
games/quake-source/Makefile.include
games/quake2-data/Makefile.include
games/quake3-data/Makefile.include
games/redeclipse-data/Makefile.tuples
games/redeclipse-data16/Makefile.tuples
games/simutrans/Makefile.pak
games/xpilot-ng-server/pkg-descr.client
games/xpilot-ng-server/pkg-descr.server
games/xpilot-ng-server/pkg-plist.client
games/xpilot-ng-server/pkg-plist.server
graphics/blender/Makefile.options
graphics/blender/Makefile.versions
graphics/evince/pkg-plist-lite
graphics/drm-510-kmod/Makefile.version
graphics/drm-515-kmod/Makefile.version
graphics/drm-61-kmod/Makefile.version
graphics/frei0r/version.mk
graphics/libkdcraw/pkg-plist.qt5
graphics/libkdcraw/pkg-plist.qt6
graphics/mesa-dri/Makefile.targets
graphics/opencolorio/pkg-plist-docs
graphics/opencolorio/pkg-plist-pyglue
graphics/opencolorio/pkg-plist-tools
graphics/openimageio/pkg-plist-pybind
graphics/openshadinglanguage/pkg-plist-pybind
java/bootstrap-openjdk8/Makefile.update
java/bootstrap-openjdk8/distinfo.aarch64
java/bootstrap-openjdk8/distinfo.amd64
java/bootstrap-openjdk8/distinfo.arm
java/bootstrap-openjdk8/distinfo.i386
java/bootstrap-openjdk8/distinfo.ppc64
java/bootstrap-openjdk8/distinfo.ppc64le
java/eclipse/Makefile.plugins
java/intellij/common.mk
korean/unfonts-core/distinfo.core-ttf
korean/unfonts-core/distinfo.extra-ttf
lang/fsharp/nupkg-nuget
lang/gcc6-aux/Makefile.version
lang/ghc/pkg-plist.hadrian
lang/ghc92/pkg-plist.hadrian
lang/gleam/Makefile.deps
lang/io/Makefile.addons
lang/mecrisp-stellaris/pkg-message-aarch64
lang/mono5.10/pkg-plist.powerpc
lang/mono5.20/pkg-plist.powerpc
lang/mono6.8/pkg-plist.powerpc
lang/perl5-devel/version.mk
lang/perl5.34/version.mk
lang/perl5.36/version.mk
lang/perl5.38/version.mk
lang/php81/pkg-message.mod
lang/php81/pkg-plist.mod
lang/php82/pkg-message.mod
lang/php82/pkg-plist.mod
lang/php83/pkg-message.mod
lang/php83/pkg-plist.mod
lang/python27/Makefile.version
lang/python38/Makefile.version
lang/python39/Makefile.version
lang/python310/Makefile.version
lang/python311/Makefile.version
lang/quilc/Makefile.deps
mail/claws-mail/Makefile.claws
mail/claws-mail/Makefile.ver
mail/courier/Makefile.doc
mail/dk-milter/Makefile.features
mail/dk-milter/pkg-message.postfix
mail/exim/options
mail/opendkim/Makefile.options
mail/panda-cclient/pkg-message-ssl
mail/sendmail/bsd.milter.mk
mail/thunderbird-dictionaries/Makefile.dict
mail/thunderbird-dictionaries/Makefile.options
math/py-keras/Makefile.MASTER_SITES
math/rubygem-narray/Makefile.version
math/suitesparse/bsd.suitesparse.mk
math/vtk9/Makefile.version
misc/compat12x/pkg-plist.armv6
misc/compat12x/pkg-plist.armv7
misc/compat12x/pkg-plist.aarch64
misc/compat4x/pkg-plist.freebsd4
misc/compat4x/pkg-plist.freebsd5
misc/compat12x/pkg-plist.powerpc
misc/dnetc/distinfo.amd64
misc/dnetc/distinfo.i386
misc/dnetc/distinfo.powerpc
multimedia/ffmpeg4/override.mk
multimedia/librespot/Makefile.crates
multimedia/mplayer-skins/Makefile.options
multimedia/mplayer-skins/Makefile.skins
multimedia/mplayer/Makefile.options
multimedia/mplayer/Makefile.optvars
multimedia/phonon/pkg-plist.qt5
multimedia/phonon/pkg-plist.qt6
net-im/tox/pkg-message.daemon
net-mgmt/ndpmon/pkg-message.MACRESOLV
net-mgmt/pandorafms_server/bsd.pandora.mk
net-mgmt/pandorafms_server/pkg-plist.spool
net-mgmt/seafile-server/Makefile.include
net-mgmt/victoria-metrics/Makefile.deps
net-mgmt/zabbix5-server/pkg-plist.agent
net-mgmt/zabbix5-server/pkg-plist.java
net-mgmt/zabbix6-server/pkg-plist.agent
net-mgmt/zabbix6-server/pkg-plist.frontend
net-mgmt/zabbix6-server/pkg-plist.java
net-mgmt/zabbix64-server/pkg-plist.agent
net-mgmt/zabbix64-server/pkg-plist.frontend
net-mgmt/zabbix64-server/pkg-plist.java
net-p2p/qbittorrent/pkg-plist-nox
net-p2p/transmission-components/pkg-descr.cli
net-p2p/transmission-components/pkg-descr.daemon
net-p2p/transmission-components/pkg-descr.docs
net-p2p/transmission-components/pkg-descr.gtk
net-p2p/transmission-components/pkg-descr.qt
net-p2p/transmission-components/pkg-descr.utils
net-p2p/transmission-components/pkg-plist.cli
net-p2p/transmission-components/pkg-plist.daemon
net-p2p/transmission-components/pkg-plist.docs
net-p2p/transmission-components/pkg-plist.gtk
net-p2p/transmission-components/pkg-plist.qt
net-p2p/transmission-components/pkg-plist.utils
net/cvsup-static/Makefile.DragonFly
net/cvsup-static/distinfo.amd64
net/gorss/Makefile.deps
net/ntp/Makefile.inc
net/openldap25-server/pkg-descr.client
net/openldap25-server/pkg-plist.client
net/openldap26-server/pkg-descr.client
net/openldap26-server/pkg-plist.client
net/remmina/pkg-descr-lite
net/samba413/pkg-plist.ad_dc
net/samba413/pkg-plist.cluster
net/samba413/pkg-plist.python
net/samba416/pkg-plist.ad_dc
net/samba416/pkg-plist.cluster
net/samba416/pkg-plist.python
net/storj/Makefile.deps
net/tigervnc-server/Makefile.common.mk
net/trafshow/pkg-message.nodevfs
net/unison/pkg-message.nox11
net/unison240/pkg-message.nox11
net/unison248/pkg-message.nox11
net/unison251/pkg-message.nox11
net/wifi-firmware-kmod/Makefile.inc
net/wifibox-alpine/flavors.mk
net/wifibox-alpine/pkg-message.iptables
news/inn/Makefile.layout
print/pkfonts300/pkg-plist.118
print/pkfonts300/pkg-plist.240
print/pkfonts300/pkg-plist.300
print/pkfonts300/pkg-plist.360
print/pkfonts300/pkg-plist.400
print/pkfonts300/pkg-plist.600
science/InsightToolkit/Makefile.remote_modules
science/InsightToolkit/Makefile.version
science/healpix/pkg-plist-c
science/healpix/pkg-plist-cxx
science/gnudatalanguage/pkg-plist.pymod
science/jmol/pkg-plist-jsmol
science/msms/distinfo-amd64
science/msms/distinfo-i386
science/paraview/Makefile.version
science/py-tensorflow/Makefile.MASTER_SITES
security/boringssl/version.mk
security/courier-authlib/Makefile.dep
security/courier-authlib/Makefile.opt
security/courier-authlib/pkg-descr-base
security/courier-authlib/pkg-descr-ldap
security/courier-authlib/pkg-descr-mysql
security/courier-authlib/pkg-descr-pgsql
security/courier-authlib/pkg-descr-sqlite
security/courier-authlib/pkg-descr-userdb
security/courier-authlib/pkg-descr-usergdbm
security/courier-authlib/pkg-descr-vchkpw
security/courier-authlib/pkg-plist-base
security/courier-authlib/pkg-plist-ldap
security/courier-authlib/pkg-plist-mysql
security/courier-authlib/pkg-plist-pgsql
security/courier-authlib/pkg-plist-sqlite
security/courier-authlib/pkg-plist-userdb
security/courier-authlib/pkg-plist-vchkpw
security/gost-engine/distinfo.openssl30
security/gost-engine/pkg-plist-openssl30
security/libressl/pkg-descr-libtls
security/libressl/pkg-plist-libtls
security/libressl/version.mk
security/libressl-devel/pkg-descr-libtls
security/libressl-devel/pkg-plist-libtls
security/libressl-devel/version.mk
security/openssl/version.mk
security/openssl-quictls/version.mk
security/openssl-unsafe/version.mk
security/openssl111/version.mk
security/openssl31-quictls/version.mk
security/openssl31/version.mk
security/openssl32/version.mk
security/ossec-hids/version.mk
security/ossec-hids-local-config/opt-ar.mk
security/ossec-hids-local-config/opt-cmdout.mk
security/ossec-hids-local-config/pkg-help-agent
security/ossec-hids-local-config/pkg-help-local
security/ossec-hids-local-config/pkg-help-server
security/ossec-hids-local-config/opt-logs.mk
security/ossec-hids-local-config/opt-syscheck.mk
security/ossec-hids-local-config/pkg-plist-server
security/ossec-hids-local-config/opt-rootcheck.mk
security/ossec-hids-local-config/opt-rules.mk
security/ossec-hids-local-config/pkg-plist-local
security/ossec-hids-local-config/pkg-plist-agent
security/ossec-hids-local/pkg-plist-server
security/ossec-hids-local/pkg-plist-local
security/ossec-hids-local/pkg-plist-agent
security/pinentry/pkg-message.gnome
security/py-acme/version.mk
security/trezord/Makefile.modules
security/vuxml/vuln.xml
sysutils/bacula9-server/pkg-plist.client
sysutils/bacula11-server/pkg-plist.client
sysutils/bacula13-server/pkg-plist.client
sysutils/bareos-server/pkg-plist.client
sysutils/bareos20-server/pkg-plist.client
sysutils/bareos21-server/pkg-plist.client
sysutils/bareos22-server/pkg-plist.client
sysutils/jail_exporter/Makefile.crates
sysutils/munin-common/munin.mk
sysutils/rest-server/Makefile.deps
textproc/aspell/Makefile.inc
textproc/aspell/pkg-plist.en
textproc/fcitx5-gtk/pkg-plist.common
textproc/fcitx5-gtk/pkg-plist.gtk2
textproc/fcitx5-gtk/pkg-plist.gtk3
textproc/fcitx5-gtk/pkg-plist.gtk4
textproc/fcitx5-qt/pkg-plist.common
textproc/fcitx5-qt/pkg-plist.qt5
textproc/fcitx5-qt/pkg-plist.qt6
textproc/jdictionary/Makefile.plugin
textproc/jdictionary/pkg-plist.plugin
textproc/xhtml-modularization/contents.inc
www/apache24/Makefile.options
www/apache24/Makefile.options.desc
www/caddy/modules.mk
www/chromium/Makefile.tests
www/firefox/Makefile.options
www/foswiki/bsd.foswiki.mk
www/hs-postgrest/Makefile.modules
www/nginx/Makefile.extmod
www/nginx/Makefile.options.desc
www/nginx-devel/Makefile.extmod
www/nginx-devel/Makefile.options.desc
www/node18/Makefile.version
www/node20/Makefile.version
www/node21/Makefile.version
www/redmine50/bsd.redmine.mk
www/rt44/Makefile.cpan
www/rt50/Makefile.cpan
www/twiki/bsd.twiki.mk
www/ungoogled-chromium/Makefile.tests
www/unit/version.mk
x11-servers/xorg-server/pkg-descr-xephyr
x11-servers/xorg-server/pkg-descr-xnest
x11-servers/xorg-server/pkg-descr-xorg
x11-servers/xorg-server/pkg-descr-xvfb
x11-themes/gnome-icons/bsd.gnome-icons.mk
x11-themes/irssi-themes/Makefile.inc
x11-themes/kde-icons-noia/Makefile.icons
x11-themes/metacity-themes/Makefile.metacity
x11-themes/qtcurve/pkg-plist.gtk2
x11-themes/qtcurve/pkg-plist.kf5
x11-themes/qtcurve/pkg-plist.utils
x11-toolkits/wlroots015/override.mk
x11-toolkits/wlroots016/override.mk
x11/gnome/pkg-descr-lite
x11/gnome/pkg-message-lite
x11/nvidia-driver/Makefile.version
x11/workrave/pkg-descr.xfce
x11/xterm/pkg-message.wchar"

# contains user-defined USE_* variables
whitelist_usermkfile="
devel/cl-asdf/bsd.cl-asdf.mk
mail/squirrelmail/bsd.squirrelmail.mk"

# validate whitelist
for name in ${whitelist_usermkfile} ${whitelist_userfile}; do
	[ -f "${_PORTSDIR}/${name}" ] || echo whitelist: ${name} doesn\'t exist
done

# convert to grep regexp
whitelist="$(echo ${whitelist} | sed -e 's/ /|/g')"

if [ -n "${opt_skip_white}" ]; then
	__whitelist_usermkfile=E_m_P_t_Y_s_E_t
	whitelist_userfile=E_m_P_t_Y_s_E_t
else
	# convert to grep regexp, escape '+'
	__whitelist_usermkfile="$(echo ${whitelist_usermkfile} | \
		sed -e 's/ /|/g;s/+/\\+/g')"
	whitelist_userfile="$(echo ${whitelist_userfile} | \
		sed -e 's/ /|/g;s/+/\\+/g')"
fi

find "${_PORTSDIR}" -mindepth 3 -maxdepth 3 -type f | \
	grep -vwE "${whitelist}|${__whitelist_usermkfile}|${whitelist_userfile}"
echo
unset __whitelist_usermkfile

[ -n "${opt_all}" ] && \
{
	echo missing, nonstandard or duplicated lines in distinfo:
	whitelist_userdistinfo=E_m_P_t_Y_s_E_t

	# validate whitelist
	for name in ${whitelist_userdistinfo}; do
		[ "${name}" = E_m_P_t_Y_s_E_t -o -f "${_PORTSDIR}/${name}" ] || \
		echo whitelist: ${name} doesn\'t exist
	done

	if [ -n "${opt_skip_white}" ]; then
		whitelist_userdistinfo=E_m_P_t_Y_s_E_t
	else
		# convert to grep regexp
		whitelist_userdistinfo="$(echo ${whitelist_userdistinfo} | \
			sed -e 's/ /|/g')"
	fi

	DISTINFOLIST=$(find "${_PORTSDIR}" -mindepth 3 -maxdepth 3 -name distinfo\*)

	for file in $(echo "${DISTINFOLIST}" | \
		grep -vE "${whitelist_userdistinfo}"); do
		NAMELIST=$(while read alg fname equal chksum; do \
			case "${chksum}" in \
				*) \
					fname="${fname##(}"; \
					fname="${fname%%)}"; \
					case "${alg}" in \
						SIZE) echo "${fname}_size" ;; \
						SHA256) echo "${fname}_sha256" ;; \
						TIMESTAMP) ;; \
						*) echo "${fname}_anomaly" ;; \
					esac ; \
					;; \
			esac ; \
		done < "${file}")

		unset prevname
		unset name
		# __END__ token is necessary to detect incomplete strings
		for name in $(echo ${NAMELIST} | tr ' ' '\n' | sort) __END__; do
			# check for anomalies
			[ "${name%%_anomaly}" != "${name}" ] && \
			{
				echo "${file}: ${name%%_anomaly} ???"
				continue
			}

			if [ -z "${prevname}" ]; then
				prevname="${name}"
			else
				# check for duplicate lines
				[ "${prevname}" = "${name}" ] && \
				{
					echo ${file}: duplicate line ${name%%_s[ih][za][e2]*}
					prevname="${name}"
					continue
				}

				# after sorting $prevname always *_sha256 and $name always *_size
				[ "${prevname%%_sha256}" = "${name%%_size}" ] && \
				{
					unset prevname
					continue
				}
				[ "${prevname%%_sha256}" != "${prevname}" ] && \
					echo ${file}: missing SIZE for ${prevname%%_sha256}
				[ "${prevname%%_size}" != "${prevname}" ] && \
					echo ${file}: missing SHA256 for ${prevname%%_size}
				prevname="${name}"
			fi
		done
	done

	echo
	unset NAMELIST
	unset DISTINFOLIST

	echo BROKEN/IGNORE quoted:

	broken_ignore_re='^(BROKEN|IGNORE)[+]*=[[:space:]]*"[^"]*"'

	find "${_PORTSDIR}" -type f -mindepth 3 -maxdepth 3 -name Makefile\* -exec \
		grep -E "${broken_ignore_re}" {} \+
	echo
}

echo "misspelled(wrong) USE_* variables in Makefile:"
# USE_* arguments for various *_ARGS varibles or USE_*_DESC
whitelist="
biology/seaview/Makefile
devel/py-pyopencl/Makefile
devel/sjasmplus/Makefile
editors/picpas/Makefile
editors/cudatext/Makefile
emulators/mame/Makefile
games/freedoko/Makefile
games/ioquake3/Makefile
graphics/lazpaint/Makefile
java/openjdk11/Makefile
lang/ghc/Makefile
lang/julia/Makefile
mail/postfix/Makefile
mail/postfix-current/Makefile
math/openblas/Makefile
math/primme/Makefile
multimedia/oscam/Makefile
net/haproxy/Makefile
net/haproxy-devel/Makefile
net/haproxy20/Makefile
net/haproxy22/Makefile
net/haproxy24/Makefile
net/haproxy25/Makefile
net/haproxy26/Makefile
net/haproxy27/Makefile
net/haproxy28/Makefile
net-im/signal-desktop/Makefile
net-mgmt/prometheus2/Makefile
net-p2p/awgg/Makefile
security/libreswan/Makefile
www/cgiwrap/Makefile"

whitelist_var="
USE_ANT
USE_APACHE_RUN
USE_BINUTILS
USE_BUDGIE
USE_CABAL
USE_CSTD
USE_CXXSTD
USE_GCC
USE_GECKO
USE_GITHUB
USE_GITLAB
USE_GL
USE_GNOME_SUBR
USE_GNOME
USE_GNUSTEP
USE_GSTREAMER
USE_HORDE_BUILD
USE_HORDE_RUN
USE_JAVA
USE_KDE
USE_LDCONFIG32
USE_LDCONFIG
USE_LINUX_PREFIX
USE_LINUX_RPM_BAD_PERMS
USE_LINUX_RPM
USE_LINUX
USE_LOCALE
USE_LXQT
USE_MATE
USE_MOZILLA
USE_MYSQL
USE_OCAMLFIND_PLIST
USE_OCAML_CAMLP4
USE_OCAML_FINDLIB
USE_OCAML_LDCONFIG
USE_OCAML_TK
USE_OCAML_WASH
USE_OCAML
USE_OPENLDAP
USE_PERL5
USE_PHP
USE_PYQT
USE_PYTHON
USE_QT
USE_RC_SUBR
USE_SDL
USE_SUBMAKE
USE_TEX
USE_WX
USE_XFCE
USE_XORG"

whitelist_uservar="
USE_ASDF_FASL
USE_ASDF
USE_GENERIC_PKGMESSAGE
USE_SBCL
USE_SM_COMPAT"

# validate USE_* whitelists
for name in ${whitelist}; do
	[ -f "${_PORTSDIR}/${name}" ] || echo whitelist: ${name} doesn\'t exist
done

# cache filelist
# remove Scripts dir as optimization and bsd.sanity.mk
# as source of no longer valid vars
FILELIST=$(find "${_PORTSDIR}/Mk/" -type f | \
	grep -Ev '/Scripts|/bsd.sanity.mk')

for var in ${whitelist_var}; do
	n=$(echo ${FILELIST} | xargs grep -m1 -wl "${var}")
	[ -z "${n}" ] && echo "whitelist: ${var} not in Mk/*"
done

# cache filelist
unset FILELIST
for name in ${whitelist_usermkfile}; do
	FILELIST="${FILELIST} ${_PORTSDIR}/${name}"
done

for var in ${whitelist_uservar}; do
	n=$(echo ${FILELIST} | xargs grep -m1 -wl "${var}")
	[ -z "${n}" ] && echo "whitelist: ${var} not in ports/*"
done

# convert to grep regexp
whitelist_var="$(echo ${whitelist_var} | sed -e 's/ /|/g')"

if [ -n "${opt_skip_white}" ]; then
	whitelist=E_m_P_t_Y_s_E_t
	whitelist_uservar=E_m_P_t_Y_s_E_t
else
	# convert to grep regexp
	whitelist="$(echo ${whitelist} | sed -e 's/ /|/g')"
	whitelist_uservar="$(echo ${whitelist_uservar} | sed -e 's/ /|/g')"
fi

# look for USE_* or #USE_* at the beginning of the line
# treat ':' as a separator, sort by second field
find "${_PORTSDIR}" -mindepth 3 -maxdepth 3 -name Makefile\* -print0 | \
	xargs -0 grep '^[[:space:]#]*USE_[^=]*=' | \
	grep -vwE "${whitelist}|${whitelist_var}|${whitelist_uservar}" | \
	sort -t: -k2
echo

echo "misspelled(wrong) USES variables in Makefile:"
whitelist="
devel/llvm-cheri/Makefile
devel/llvm-devel/Makefile
devel/llvm10/Makefile
devel/llvm11/Makefile
devel/llvm12/Makefile
devel/llvm13/Makefile
devel/llvm14/Makefile
devel/llvm15/Makefile
devel/llvm16/Makefile
devel/llvm17/Makefile
multimedia/gstreamer1-plugins/Makefile.common
multimedia/mkvtoolnix/Makefile"

whitelist_var=$(for f in "${_PORTSDIR}"/Mk/Uses/*; do f=${f%%.mk}; echo ${f##*/}; done)

# validate USES whitelists
for name in ${whitelist}; do
	[ -f "${_PORTSDIR}/${name}" ] || echo "whitelist: ${name} doesn\'t exist"
done

# convert to grep regexp
whitelist="$(echo ${whitelist} | sed -e 's/ /|/g')"
whitelist_var="$(echo ${whitelist_var} | sed -e 's/ /|/g')"

# XXX this is only partially works, because some ports have USES in multiple
# lines, more proper way to check them is to invoke make -V USES on each
# port. But it would cause huge performance penalty.
find  "${_PORTSDIR}" -mindepth 3 -maxdepth 3 -name Makefile\* -print0 | \
	xargs -0 grep "^[[:space:]#]*USES[+?]*=" | \
	grep -vwE "${whitelist}|${whitelist_var}" | \
	sort -t: -k2
echo

echo "lines after '.include <bsd.port.mk>|<bsd.port.post.mk>' in Makefile:"
# see pr59254
# typical cases: .endif or different .include <...>
whitelist="
devel/schilybase
graphics/frei0r
lang/tauthon
net/tigervnc-server
net/widentd
net/wifi-firmware-ath10k-kmod
net/wifi-firmware-ath11k-kmod
net/wifi-firmware-mt76-kmod
net/wifi-firmware-rtw88-kmod
net/wifi-firmware-rtw89-kmod
net/yami4
security/john
textproc/libxml\+\+26
x11/nvidia-secondary-driver-390
x11-toolkits/pangomm"

# atypical cases, probably worth investigating
whitelist2="
audio/gstreamer1-plugins-lv2
cad/zcad
devel/xelfviewer
devel/xopcodecalc
devel/xpeviewer
editors/bless
games/nehquake
games/oblige
games/q3cellshading
games/sokobano
games/vanilla-conquer
games/vcmi
games/xray_re-tools
graphics/appleseed
graphics/glew-wayland
graphics/libfpx
graphics/simpleviewer
japanese/p5-Unicode-Japanese
mail/libdkim
misc/gedkeeper
multimedia/gstreamer1-plugins-bad
multimedia/gstreamer1-plugins-assrender
multimedia/gstreamer1-plugins-dts
multimedia/gstreamer1-plugins-dvdread
multimedia/gstreamer1-plugins-mpeg2dec
multimedia/gstreamer1-plugins-mplex
multimedia/gstreamer1-plugins-resindvd
multimedia/gstreamer1-plugins-x264
multimedia/gstreamer1-plugins-x265
net/glib-networking
net-mgmt/victoria-metrics
net-p2p/udpt
sysutils/angrysearch
sysutils/ansible
sysutils/bacula13-client-static
sysutils/gstreamer1-plugins-cdio
sysutils/py-ansible-core
textproc/hunspell
textproc/nuspell
x11/rofi-wayland
x11/ulauncher"

# valid lastlines in port Makefile
# XXX '\s' doesn't work with LANG=C
lastline_re=':.include[[:space:]]+(<bsd\.port\.mk>|<bsd\.port\.post\.mk>|\"\${MASTERDIR}|\"\${\.CURDIR}/|\"\${\.CURDIR:H:H}/)'

# validate whitelist
for name in ${whitelist} ${whitelist2}; do
	# remove meta characters
	name=$(eval echo $name)
	[ -d "${_PORTSDIR}/${name}" ] || { echo whitelist: ${name} was removed; continue; }
	tail -n1 "${_PORTSDIR}/${name}/Makefile" | \
	grep -qE "${lastline_re}" && echo "whitelist: ${name} was fixed"
done

if [ -n "${opt_skip_white}" ]; then
	whitelist=E_m_P_t_Y_s_E_t
	whitelist2=E_m_P_t_Y_s_E_t
else
	# convert to grep regexp
	whitelist="$(echo ${whitelist} | sed -e 's/ /\/|/g')"
	whitelist2="$(echo ${whitelist2} | sed -e 's/ /\/|/g')"
fi

unset file
# parse output of tail -n1: first line is '==>' ${file} '<==',
# second is the last line of Makefile and third is an empty line
# append to the end of printed line ^A so we can convert it
# output to separate lines later
FILELIST=$(while read -r line; do
	# check if $file is set in case if the last Makefile's line was ^$
	[ -z "${line}" -a -z "${file}" ] && continue
	set -- ${line}
	if [ "$1" = '==>' -a "$3" = '<==' ]; then
		file=$2
	elif [ -n ${file} ]; then
		echo "${file}:${line}"
		unset file
	fi
done << EOF
`find "${_PORTSDIR}" -mindepth 3 -maxdepth 3 -name Makefile \
	-exec tail -n1 {} \+`
EOF
)

# '^$' pattern is to remove first (empty) output line
echo ${FILELIST} | tr '' '\n' | grep -vE ${lastline_re} | \
	grep -vE "${whitelist}|${whitelist2}|^$" | sort | sed -e 's/^ //'
echo
