#!/bin/sh

# SPDX-License-Identifier: BSD-2-Clause

# Our input is the output of something like:
#
#	(cd ${SRCTOP} &&
#	find *bin etc lib* -name Makefile |
#	xargs grep '^PACKAGE[[:space:]]*=' )
#
# With some cleanup and looks like:
#
#	usr.bin/ofed/libibverbs/Makefile:PACKAGE=FreeBSD-rdma
#	usr.bin/last/Makefile:PACKAGE=acct
#	usr.bin/lastcomm/Makefile:PACKAGE=acct
#	usr.bin/users/Makefile:PACKAGE=acct
#	usr.bin/who/Makefile:PACKAGE=acct
#	usr.sbin/ac/Makefile:PACKAGE=acct
#	usr.sbin/accton/Makefile:PACKAGE=acct
#	usr.sbin/lastlogin/Makefile:PACKAGE=acct
#	..
#
# which we use to populate $PACKAGES/*/Makefile.depend
# and $PACKAGES/Makefile.depend to make it easier to keep
# Makefile.depend files throughout the tree up-to-date.
#
# We attempt to handle MK_* knobs that impact DIRDEPS, by
# identifying the intermediate *bin and *lib Makefiles and
# checking if they had a subdir for the current reldir via a construct
# like:
#
# 	SUBDIR.${MK_OPT}+= sub
#
# in which case we extract the option OPT and add the reldir
# to a Makefile.depend.options file in targets/packages/sub/
#
# Of course the above is only *one* way optional SUBDIRs are handled
# in the tree.  We also attempt to handle:
#
#	.if ${MK_OPT} == "yes"
#	SUBDIR+= sub
#	.endif
#

Mydir=`dirname $0`

SKIP_LOG=return

while :
do
    case "$1" in
    *=*) eval "$1"; shift;;
    -v) SKIP_LOG=:; shift;;
    *) break;;
    esac
done

to_reldir() {
    sed "s,$SRCTOP/,,"
}

SRCTOP=${SRCTOP:-$(realpath $Mydir/../../..)}
. ${SRCTOP}/libexec/rc/debug.sh
DebugOn bootstrap-packages

PACKAGES=${PACKAGES:-$(realpath $Mydir/../..)}
case "$PACKAGES" in
/*) ;;
*) PACKAGES=$SRCTOP/$PACKAGES;;
esac

script_name=$(realpath $0 | to_reldir)

log() {
    $SKIP_LOG 0
    echo $1 | to_reldir >&2
}

start_depend() {
    depfile=$1

    log $1
    mkdir -p ${depfile%/*}
    cat <<EOF > $depfile
# Generated by $script_name

DIRDEPS= \\
EOF
}

end_depend() {
    end_options $1.options
    cat <<EOF >> $1

.include <dirdeps.mk>
EOF
}

start_options() {
    ofile=$1

    log $1
    mkdir -p ${ofile%/*}
    opts=$opt
    eq==
    cat <<EOF > $ofile
# Generated by $script_name

DIRDEPS_OPTIONS= $opt
EOF
}

end_options() {
    test -s $1 || return
    cat <<EOF >> $1

.include <dirdeps-options.mk>
EOF
}

no_plus() {
    case "$1" in
    *+*) echo "$1" | sed 's,+,\\\\+,g';;
    *) echo "$1";;
    esac
}

find_opt() {
    mf=$1
    sub="`no_plus $2`"
    shift 2
    egrep "$@" "^[^#].*[[:space:]]$sub([[:space:]]|\$)" $mf |
    tr '{' '\n' |
    sed -n 's,^MK_\([^}]*\).*,\1,p' |
    tr '\n' ' '
}

start_depend $PACKAGES/Makefile.depend || exit 1
sort -t= -k2 "$@" | sed 's,/Makefile:PACKAGE=, ,' |
(
    lpackage=
    while read reldir package
    do
	# use these below
	dname=${reldir%/*}
	bname=${reldir##*/}
	# check parent does not have it commented out
	# otherwise we should ignore it.
	# if the parent makefile does not exist, we will skip it.
	pmf=$SRCTOP/$dname/Makefile
	egrep -q "^[^#].*[[:space:]]`no_plus $bname`([[:space:]]|\$)" $pmf 2> /dev/null || continue
	: reldir=$reldir
	case "$reldir" in
	*lib/*) sub=${reldir#*lib/};;
	*bin/*) sub=${reldir#*bin/};;
	*libexec/*) sub=${reldir#*libexec/};;
	*) opt= sub=;;
	esac
	if [ -n "$sub" ]; then
	    smf=${SRCTOP}/${reldir%/$sub}/Makefile
	    # now we need just the immediate subdir
	    sub=${sub%%/*}
	    # SUBDIR.${MK_OPT}+= sub
	    opt=`find_opt $smf $sub`
	    # .if ${MK_OPT} == "yes"
	    # SUBDIR+= sub
	    opt=${opt:-`find_opt $smf $sub -B2`}
	fi
	case "$reldir" in
	*/tests|*/tests/*) opt=${opt:-TESTS};;
	esac
	# PACKAGES is set to either a simple string like 'runtime'
	# or for some libraries 'lib${LIB}'
	# or even 'lib${LIB:tl}' when LIB contains upper case
	# the majority of libs in FreeBSD use lib${LIB} for their dirname
	# but we allow for just ${LIB} too.
	: package=$package
	case "$package" in \
	lib?{LIB*) package=`echo lib${bname#lib} | tr 'A-Z' 'a-z'`;;
	esac
	if test "$package" != "$lpackage"; then \
	    test -z "$lpackage" || end_depend $ddeps
	    target=$PACKAGES/$package
	    ddeps=$target/Makefile.depend
	    odeps=$ddeps.options
	    rm -f $odeps
	    start_depend $ddeps
	    lpackage=$package
	    echo "	$target \\"
	fi
	if [ -n "$opt" ]; then
	    [ -s $odeps ] || start_options $odeps
	    {
		case " $opts " in
		*" $opt "*) ;;
		*)  echo DIRDEPS_OPTIONS+= $opt
		    opts="$opts $opt"
		    eq==
		    ;;
		esac
		for o in $opt
		do
		    echo DIRDEPS.$o.yes$eq $reldir
		done
		eq=+=
	    } >> $odeps
	else
	    echo "	$reldir \\" >> $ddeps
	fi
    done
    end_depend $ddeps
) | to_reldir >> $PACKAGES/Makefile.depend
end_depend $PACKAGES/Makefile.depend
