#!/bin/bash -e
#
#   undertaker-kconfigdump - generates models in Linux source trees
#
# Copyright (C) 2009-2011 Christian Dietrich <christian.dietrich@informatik.uni-erlangen.de>
# Copyright (C) 2009-2011 Reinhard Tartler <tartler@informatik.uni-erlangen.de>
# Copyright (C) 2012 Manuel Zerpies <manuel.f.zerpies@ww.stud,uni-erlangen.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# This script is used for precalculating the configuration models of a
# linux tree. Therefore the config is first dumped with dumpconf to an
# rsf file. This rsf file is piped to rsf2model which calculates the
# model which is used by the undertaker afterwards.
#
# dumpconf and rsf2model can be placed in $PREFIX/lib/undertaker or
# /usr/lib/undertaker or /usr/local/lib/undertaker, because they won't
# be needed anywhere else than here.
#
# Enviroment variables:
# - MODELS: the directory where the models are placed (default:
#           models)
# - DEBUG: give some debug informations
#
# Arguments:
# - Architecture models to build


MODELS=${MODELS:-models}
PROCESSORS=${PROCESSORS:-$(getconf _NPROCESSORS_ONLN)}


function debug() {
    if [ -n "$DEBUG" ]; then
        echo -e "$@"
    fi
}

function find_undertaker_basepath () {
    # ensure to follow symbolic links
    local undertaker_path=$(readlink -f `which undertaker`)
    local b=$(dirname $undertaker_path)
    echo "${b}/.."
}

PATH="`find_undertaker_basepath`/lib/undertaker:$PATH"
debug "PATH=$PATH\n"

if ! which dumpconf > /dev/null; then
    echo "No dumpconf binary found."
    exit 1
fi

if ! which  rsf2model > /dev/null; then
    echo "No rsf2model binary found."
    exit 1
fi

debug "rsf2model: $(which rsf2model)"
debug "dumpconf: $(which dumpconf)"

if [ ! -f arch/x86/Kconfig ]; then
    echo "Not run in an linux tree. Please run inside an linux tree without arguments"
    exit 1
fi

ALLARCHS="$(ls arch/*/Kconfig | cut -d '/' -f 2) um"

if [ -z "$1" ]; then
    ARCHS=$ALLARCHS
else
    ARCHS="$@"
fi

mkdir -p "$MODELS"

function pwait() {
    # This functions blocks until less than $1 subprocesses are running
    jobs="$1"
    [ -z "$jobs" ] && jobs=5

    while [ $(jobs -r | wc -l) -ge "$jobs" ]; do
        sleep 0.5
    done
}

function do_convert() {
    ARCH=$1
    UPCASE_ARCH=$(echo $ARCH | tr 'a-z' 'A-Z')
    echo "Calculating model for $ARCH"

  # special case for user mode linux
  # Note that upstream commit 5c48b108ecbf6505d929e64d50dace13ac2bdf34 renamed
  # arch/{um/Kconfig.x86 => x86/um/Kconfig}
  # get the right file even in historic linux trees.
    SUBARCH=$ARCH
    KCONFIG=Kconfig
    if [ x"$ARCH" = x"um" ]; then
        SUBARCH=x86
        if [ -r arch/um/Kconfig ]; then
            KCONFIG=Kconfig
        else
            KCONFIG=Kconfig.um
        fi
    fi

    test -f arch/$ARCH/$KCONFIG || {
       echo "ERROR: Architecture $ARCH not found";
       return
    }

  # dumpconf, remove all the comments because they will confuse rsf2model
    SUBARCH=$SUBARCH ARCH=$ARCH dumpconf arch/$ARCH/$KCONFIG | grep -v '^#' > "$MODELS/$ARCH.rsf"

  # rsf2model, but CONFIG_$UPCASE_ARCH will be replaced by
  # a rule that no other architecture can be selected at the same
  # time. E.g. X86 -> !ARM && !S390

    rsf2model "$MODELS/$ARCH.rsf" | grep -v '^CONFIG_'"$UPCASE_ARCH"'$' > "$MODELS/$ARCH.model"

  # Add CONFIG_$i -> !CONFIG_* for every architecture
    echo $ALLARCHS | sed "s/ *$ARCH */ /" | tr 'a-z' 'A-Z' | \
        sed 's/$/"/; s/\</!CONFIG_/g; s/ / \&\& /g; s/^/'"CONFIG_$UPCASE_ARCH "'"/;' \
        >> "$MODELS/$ARCH.model"
}

for ARCH in $ARCHS
do
    do_convert $ARCH &
    # run many converting processes in parallel
    pwait ${PROCESSORS}
done

while [ $(jobs -r | wc -l) -gt 0 ]; do
    sleep 0.5
done

