#!/bin/sh
set -eu
: "${BASEDIR:=/usr/src}"
: "${PORTSDIR:=/usr/ports}"
TMP="generated_rules.tmp"
OSRELS="11 12 13 14"

export LC_ALL=C

_make() {
	if [ "$1" = "Mk" ]; then
		flags="-f bsd.port.mk"
	else
		flags=""
	fi
	make -C "${PORTSDIR}/$1" ${flags} PORTSDIR="${PORTSDIR}" "$@" | tr ' ' '\n' | awk 'NF' | sort -u
}

exec 1>"constants.c"
echo "/* Generated by generate_rules.sh; do not edit */"
echo '#include "config.h"'
echo '#include <sys/types.h>'
echo '#include <inttypes.h>'
echo '#include "constants.h"'

echo "struct ConstantStaticFlavors static_flavors[] = {"
_make "Mk" USES=emacs -V FLAVORS | sed -e 's/^/	{ "emacs", "/' -e 's/$/" },/'
_make "Mk" USES=lazarus:flavors -V FLAVORS | sed -e 's/^/	{ "lazarus", "/' -e 's/$/" },/'
_make "Mk" USES=lua:module -V FLAVORS | sed -e 's/^/	{ "lua", "/' -e 's/$/" },/'
_make "Mk" USES=php:flavors -V FLAVORS | sed -e 's/^/	{ "php", "/' -e 's/$/" },/'
_make "databases/py-sqlite3" BUILD_ALL_PYTHON_FLAVORS=yes -V FLAVORS | sed -e 's/^/	{ "python", "/' -e 's/$/" },/'
echo "};"
echo "size_t static_flavors_len = nitems(static_flavors);"

printf 'const char *known_architectures[] = {\n'
(
	make -C "${BASEDIR}" targets
	# Some arches are retired in FreeBSD 13 but still valid in other releases
	echo "/arm"
	echo "/mips64el"
	echo "/mips64elhf"
	echo "/mips64hf"
	echo "/mipsel"
	echo "/mipselhf"
	echo "/mipshf"
	echo "/mipsn32"
	echo "/powerpc64le"
	echo "/powerpcspe"
	echo "/sparc64"
) | awk -F/ 'NR > 1 { printf "\t\"%s\",\n", $2 }' | sort -u
echo '};'
echo "size_t known_architectures_len = nitems(known_architectures);"

printf 'uint32_t freebsd_versions[] = {\n'
for rel in ${OSRELS}; do
	printf "\t${rel},\n"
done
echo '};'
echo "size_t freebsd_versions_len = nitems(freebsd_versions);"

exec 1>"constants.h"
cat <<EOF
/* Generated by generate_rules.sh; do not edit */
struct ConstantStaticFlavors {
	const char *uses;
	const char *flavor;
};
extern struct ConstantStaticFlavors static_flavors[];
extern size_t static_flavors_len;
extern const char *known_architectures[];
extern size_t known_architectures_len;
extern uint32_t freebsd_versions[];
extern size_t freebsd_versions_len;
extern const char *use_gnome_rel[];
extern const char *use_kde_rel[];
extern const char *use_pyqt_rel[];
extern const char *use_qt_rel[];
extern const char *static_shebang_langs[];
extern size_t use_gnome_rel_len;
extern size_t use_kde_rel_len;
extern size_t use_pyqt_rel_len;
extern size_t use_qt_rel_len;
extern size_t static_shebang_langs_len;
EOF

echo "#define VAR_BROKEN_RUBY(block, flags, uses) \\"
(cd "${PORTSDIR}/lang"; ls -d ruby[0-9]*) | tr '[a-z]' '[A-Z]' | sort | awk '{ lines[++i] = $0 }
END {
	for (i = 1; lines[i] != ""; i++) {
		printf "%s\t{ block, \"BROKEN_%s\", flags, uses }", start, lines[i]
		start = ", \\\n";
	}
	print ""
}'

printf '#define VAR_FOR_EACH_ARCH(block, var, flags, uses) \\\n'
(
	make -C "${BASEDIR}" targets
	# Some arches are retired in FreeBSD 13 but still valid in other releases
	echo "/arm"
	echo "/mips64el"
	echo "/mips64elhf"
	echo "/mips64hf"
	echo "/mipsel"
	echo "/mipselhf"
	echo "/mipshf"
	echo "/mipsn32"
	echo "/powerpc64le"
	echo "/powerpcspe"
	echo "/sparc64"
) | awk -F/ 'NR > 1 { print $2 }' | sort -u | awk '{ lines[NR] = $1 }
END {
	for (i = 1; lines[i] != ""; i++) {
		printf "%s\t{ block, var \"%s\", flags, uses }", start, lines[i]
		start = ", \\\n";
	}
	print ""
}'

printf '#define VAR_FOR_EACH_FREEBSD_VERSION_AND_ARCH(block, var, flags, uses) \\\n'
printf '	{ block, var "FreeBSD", flags, uses }, \\\n'
for ver in ${OSRELS}; do
	printf '	{ block, var "FreeBSD_%s", flags, uses }, \\\n' "${ver}"
	printf '	VAR_FOR_EACH_ARCH(block, var "FreeBSD_%s_", flags, uses), \\\n' "${ver}"
done
printf '	VAR_FOR_EACH_ARCH(block, var "FreeBSD_", flags, uses)\n'
printf '#define VAR_FOR_EACH_FREEBSD_VERSION(block, var, flags, uses) \\\n'
printf '	{ block, var "FreeBSD", flags, uses }'
for ver in ${OSRELS}; do
	printf ', \\\n	{ block, var "FreeBSD_%s", flags, uses }' "${ver}"
done
echo

printf '#define VAR_FOR_EACH_SSL(block, var, flags, uses) \\\n'
valid_ssl=$(awk '/^# Possible values: / { values = $0; gsub(/(^# Possible values: |,)/, "", values); }
/SSL_DEFAULT/ { print values; exit }' "${PORTSDIR}/Mk/bsd.default-versions.mk")
start=""
for ssl in ${valid_ssl}; do
	[ -n "${start}" ] && echo "${start}"
	printf '	{ block, var "%s", flags, uses }' "${ssl}"
	start=", \\"
done
echo

exec 1>>"constants.c"

echo 'const char *use_gnome_rel[] = {'
_make "Mk" USES=gnome -V _USE_GNOME_ALL >"${TMP}"
sed -e 's/^/	"/' -e 's/$/",/' "${TMP}"
# USES=gnome silently allows for bogus component:build args etc,
# but we do not.
while read -r comp; do
	build=$(_make "Mk" USES=gnome -V "${comp}_BUILD_DEPENDS")
	if [ -n "${build}" ]; then
		echo "${comp}" | sed -e 's/^/	"/' -e 's/$/:build",/'
	fi
done <"${TMP}"
while read -r comp; do
	build=$(_make "Mk" USES=gnome -V "${comp}_RUN_DEPENDS")
	if [ -n "${build}" ]; then
		echo "${comp}" | sed -e 's/^/	"/' -e 's/$/:run",/'
	fi
done <"${TMP}"
echo '};'
echo "size_t use_gnome_rel_len = nitems(use_gnome_rel);"

echo 'const char *use_kde_rel[] = {'
_make "Mk" CATEGORIES=devel USES=kde:5 -V _USE_KDE5_ALL >"${TMP}"
sed -e 's/^/	"/' -e 's/$/",/' "${TMP}"
sed -e 's/^/	"/' -e 's/$/_build",/' "${TMP}"
sed -e 's/^/	"/' -e 's/$/_run",/' "${TMP}"
echo '};'
echo "size_t use_kde_rel_len = nitems(use_kde_rel);"

echo 'const char *use_qt_rel[] = {'
_make "Mk" USES=qt:5 -V _USE_QT_ALL >"${TMP}"
sed -e 's/^/	"/' -e 's/$/",/' "${TMP}"
sed -e 's/^/	"/' -e 's/$/_build",/' "${TMP}"
sed -e 's/^/	"/' -e 's/$/_run",/' "${TMP}"
echo '};'
echo "size_t use_qt_rel_len = nitems(use_qt_rel);"

echo 'const char *use_pyqt_rel[] = {'
_make "Mk" USES=pyqt:5 -V _USE_PYQT_ALL >"${TMP}"
sed -e 's/^/	"/' -e 's/$/",/' "${TMP}"
sed -e 's/^/	"/' -e 's/$/_build",/' "${TMP}"
sed -e 's/^/	"/' -e 's/$/_run",/' "${TMP}"
sed -e 's/^/	"/' -e 's/$/_test",/' "${TMP}"
echo '};'
echo "size_t use_pyqt_rel_len = nitems(use_pyqt_rel);"

echo "const char *static_shebang_langs[] = {"
_make "Mk" USES="lua shebangfix" -V SHEBANG_LANG | sed -e 's/^/	"/' -e 's/$/",/'
echo "};"
echo "size_t static_shebang_langs_len = nitems(static_shebang_langs);"

rm -f "${TMP}"
