#! /bin/sh
# LAST EDIT: Sun Oct 15 19:35:12 1995 by Axel Boldt (boldt@math.ucsb.edu) 
#
# This script is used to configure the linux kernel.
#
# It was inspired by the challenge in the original Configure script
# to ``do something better'', combined with the actual need to ``do
# something better'' because the old configure script wasn't flexible
# enough.
#
# Please send comments / questions / bug fixes to raymondc@microsoft.com.
#
#
#
# Each line in the config file is a command.
#
# 050793 - use IFS='@' to get around a bug in a pre-version of bash-1.13
# with an empty IFS.
#
# 050195 (boldt@math.ucsb.edu) - added help text support
#
# 030995 (storner@osiris.ping.dk) - added support for tri-state answers,
# for selecting modules to compile.

#
# Make sure we're really running bash.
#
# I would really have preferred to write this script in a language with
# better string handling, but alas, bash is the only scripting language
# that I can be reasonable sure everybody has on their linux machine.
#
[ -z "$BASH" ] && { echo "Configure requires bash" 1>&2; exit 1; }

# Disable filename globbing once and for all.
# Enable function cacheing.
set -f -h

#
# readln reads a line into $ans.
#
#	readln prompt default
#
function readln () {
	if [ "$DEFAULT" = "-d" ]; then
		echo "$1"
		ans=$2
	else
		echo -n "$1"
		IFS='@' read ans </dev/tty || exit 1
		[ -z "$ans" ] && ans=$2
	fi
}

#
# comment does some pretty-printing
#
#	comment 'xxx'
# 
function comment () {
	echo "*"; echo "* $1" ; echo "*"
	(echo "" ; echo "#"; echo "# $1" ; echo "#") >>$CONFIG
	(echo "" ; echo "/*"; echo " * $1" ; echo " */") >>$CONFIG_H
}

#
# help prints the corresponding help text from Configure.help to stdout
#
#       help variable
#

function help () {
  if [ -f Documentation/Configure.help ]
  then
     #first escape regexp special characters in the argument:
     var=$(echo "$1"|sed 's/[][\/.^$*]/\\&/g')
     #now pick out the right help text:
     text=$(sed -n "/^$var[ 	]*\$/,\${/^$var[ 	]*\$/b;/^#.*/b;/^[ 	]*\$/q;p;}"  Documentation/Configure.help)
     if [ -z "$text" ]
     then
          echo; echo "  Sorry, no help available for this option yet.";echo
     else
          (echo; echo "$text"; echo) | more
     fi
  else
     echo;
     echo "  Can't access the file Documentation/Configure.help which"
     echo "  should contain the help texts."
     echo
  fi
}

#
# define_bool sets the value of a boolean argument
#
#	define_bool define value
#
function define_bool () {
       case "$2" in
         "y")
                echo "$1=y" >>$CONFIG
                echo "#define $1 1" >>$CONFIG_H
                ;;

         "m")
                echo "$1=m" >>$CONFIG
                echo "#undef  $1" >>$CONFIG_H
                ;;

         "n")
                echo "# $1 is not set" >>$CONFIG
                echo "#undef  $1" >>$CONFIG_H
                ;;
        esac
	eval "$1=$2"
}


#
# bool processes a boolean argument
#
#	bool question define default
#
function bool () {
	def=$(eval echo "\${$2:-$3}")
        case "$def" in
         "y") defprompt="Y/n/?"
              ;;
         "n") defprompt="N/y/?"
              ;;
        esac
        while :
        do 
          readln "$1 ($2) [$defprompt] " "$def"
          case $ans 
          in
            [yY] | [yY]es )    define_bool "$2" "y"
                               break ;;
            [nN] | [nN]o )     define_bool "$2" "n"
                               break ;;
            * )                help "$2"
          esac
        done
}

#
# tristate processes a tristate argument
#
#	tristate question define default
#
function tristate () {
	ans=""
	def=$(eval echo "\${$2:-$3}")
        case "$def" in
         "y") defprompt="Y/m/n/?"
              ;;
         "m") defprompt="M/n/y/?"
              ;;
         "n") defprompt="N/y/m/?"
              ;;
        esac
        while :
        do 
          readln "$1 ($2) [$defprompt] " "$def"
          case $ans 
          in
            [yY] | [yY]es )    define_bool "$2" "y"
                               break ;;
            [nN] | [nN]o )     define_bool "$2" "n"
                               break ;;
            [mM] )             define_bool "$2" "m"
                               break ;;
	    * )                help "$2"
          esac
        done
}

#
# dep_tristate processes a tristate argument
#
#	tristate question define default that depends upon
#	another option.  If the option we depend upon is a module,
#	then the only allowable options are M or N.  If Y, then
#	this is a normal tristate.  This is used in cases where modules
#	are nested, and one module requires the presence of something
#	else in the kernel.
#
function dep_tristate () {
	if [ "$4" != "m" ]; then
		tristate "$1" "$2" "$3"
	else
		def=$(eval echo "\${$2:-$3}")
	        case "$def" in
        	 "y" | "m") defprompt="M/n/?"
		            def="m"
        	            ;;
        	 "n") defprompt="N/m/?"
        	      ;;
	        esac
                while :
                do 
                  readln "$1 ($2) [$defprompt] " "$def"
                  case $ans 
                    in
                      [nN] | [nN]o )     define_bool "$2" "n"
                                         break ;;
                      [mM] )             define_bool "$2" "m"
                                         break ;;
                      [yY] | [yY]es )    echo 
               echo "  This answer is not allowed, because it is not"
               echo "  consistent with your other choices."
               echo "  This driver depends on another one which you"
               echo "  decided to compile as a module. This means that"
               echo "  you can either compile this one as a module too"
               echo "  or leave it out altogether."           
                                         echo
                                         ;;
                      * )                help "$2"
                  esac
                done
	fi
}


#
# define_int sets the value of a integer argument
#
#	define_int define value
#
function define_int () {
	echo "$1=$2" >>$CONFIG
	echo "#define $1 ($2)" >>$CONFIG_H
	eval "$1=$2"
}

#
# int processes an integer argument
#
#	int question define default
#
function int () {
	def=$(eval echo "\${$2:-$3}")
        while :
        do
          readln "$1 ($2) [$def] " "$def"
          if expr match "$ans" "[1-9][0-9]*$" > /dev/null
          then
             break
          else
             help "$2"
          fi
        done
	define_int "$2" "$ans"
}

#
# choice processes a choice list (1-out-of-n)
#
#	choice question choice-list default
#
# The choice list has a syntax of:
#	NAME:VALUE { WHITESPACE '|' NAME:VALUE }
# The user may enter any unique prefix of one of the NAMEs and
# choice will define VALUE as if it were a boolean option.
# VALUE must be in all uppercase.  Normally, VALUE is of the
# form CONFIG_<something>.  Thus, if the user selects <something>,
# the CPP symbol CONFIG_<something> will be defined and the
# shell variable CONFIG_<something> will be set to "y".
#
function choice () {
	question="$1"
	choices="$2"
	def="$3"

	# determine default answer:
	names=""
	set -- $choices
        firstvar=$2
	while [ -n "$2" ]; do
		if [ -n "$names" ]; then
			names="$names, $1"
		else
			names="$1"
		fi
		if [ "$(eval echo \"\${$2}\")" = "y" ]; then
			def=$1
		fi
		shift; shift
	done
        names="$names or ?"

	val=""
        ambg=n
	while [ -z "$val" ]; do
		readln "$question ($names) [$def] " "$def"
		ans=$(echo $ans | tr a-z A-Z)
		set -- $choices
		val=""
		while [ -n "$1" ]; do
			name=$(echo $1 | tr a-z A-Z)
			case "$name" in
				"${ans}"*)
					if [ "$name" = "$ans" ]; then
						val="$2"
						break	# stop on exact match
					fi
					if [ -n "$val" ]; then
						echo \
		"  Sorry, \"$ans\" is ambiguous; please enter a longer string."
						val=""
						ambg=y
                                                break
					else
						val="$2"
					fi;;
			esac
			shift; shift
		done
                if [ "$val" = "" -a "$ambg" = "n" ]; then
                        help $firstvar
                fi
	done
	echo "  defining $val"
	define_bool "$val" "y"
}


CONFIG=.tmpconfig
CONFIG_H=.tmpconfig.h

echo
echo "Linux Kernel Configuration Script"
echo "---------------------------------"
echo
echo "     RET   -- accept (capitalized) default"
echo "      y    -- yes"
echo "      n    -- no"
echo "      m    -- compile as module"
echo "      ?    -- display help"
echo "    Ctrl-C -- abort configuration and discard all changes"
echo


trap "rm -f $CONFIG $CONFIG_H ; exit 1" 1 2

#
# Make sure we start out with a clean slate.
#
echo "#" > $CONFIG
echo "# Automatically generated make config: don't edit" >> $CONFIG
echo "#" >> $CONFIG

echo "/*" > $CONFIG_H
echo " * Automatically generated C config: don't edit" >> $CONFIG_H
echo " */" >> $CONFIG_H

DEFAULT=""
if [ "$1" = "-d" ] ; then
	DEFAULT="-d"
	shift
fi

CONFIG_IN=./config.in
if [ "$1" != "" ] ; then
	CONFIG_IN=$1
fi

if [ -f ./.config ] ; then
	. ./.config
	sed -e 's/# \(.*\) is not.*/\1=n/' <./.config >/tmp/conf.$$
	. /tmp/conf.$$
	rm /tmp/conf.$$
fi
. $CONFIG_IN

if [ "$CONFIG_SOUND" = "y" ] ; then
	$MAKE -C drivers/sound config || exit 1
fi

rm -f .config.old
if [ -f .config ]; then
	mv .config .config.old
fi
mv .tmpconfig .config
mv .tmpconfig.h include/linux/autoconf.h

echo
echo
echo "The linux kernel is now hopefully configured for your setup."
echo "If you made a mistake, just do 'make config' again, or edit"
echo "the file .config and say 'make oldconfig'."
echo "Check the top-level Makefile for additional configuration,"
echo "and do a 'make dep ; make clean' if you want to be sure all"
echo "the files are correctly re-made."
echo

exit 0



