#! /bin/sh

cat <<GAZONK
#
# WELCOME TO KLIC SYSTEM CONFIGURAION SCRIPT
#
#  Copyright 1994 Institute for New Generation Computer Technology
#  Read COPYRIGHT for detailed information
#
# In this script, I'll ask you for several options you can make.
# Default values are presented in brackets as in [default].
# If the default is OK, simply hit CR.
# Otherwise, type in whatever is your option.
#

GAZONK

: Find how to suppress newline after echo
if ( echo "test line\c"; echo " ") | grep c >/dev/null 2>/dev/null ; then
    n='-n'
    c=''
else
    n=''
    c='\c'
fi

: Define some handy functions

clean_up_config () {
  rm -f nmout.tmp nmout.list nmout.all testprefix 2>/dev/null
}

give_up_config () {
    echo " "
    for message do
	echo "!!! $message !!!"
    done
    clean_up_config
    echo "Aborting KLIC configuration script"
    echo ' '
    exit 1
}

ask_yes_or_no () {
    default=$1
    default_value=$2
    echo $n " (yes or no)"$c
    while true ; do
	echo $n " [$default] "$c
	read ans
	case $ans in
	'') return $default_value;;
	yes) return 0;;
	no) return 1;;
	esac
	echo $n "Please input yes or no"$c
    done
}

ask_with_default () {
    message=$1
    macroname=$2
    eval default=\$$macroname
    echo $n "Which $message would like to use? [$default] "$c
    read ans
    case $ans in
    none) ans='';;
    '') ans=$default ;;
    esac
    eval $macroname=\$ans
}

locate_file () {
file=$1
shift
kind=$1
shift
for dir in $*; do
    if test -$kind $dir/$file; then
	where=$dir/$file
	return 0
    fi
done
return 1
}

locate_executable () {
    file=$1
    shift
    user_path=$*
    locate_file $file x $user_path
    return
}

locate_directory () {
    test -d $1 ||
    {
	echo $n "Cannot find $1; Create it now? "$c
	if ask_yes_or_no yes 0; then
	    if mkdir $1 ; then
		return 0
	    else
		echo "!!! Couldn't create $1 !!!"
		return 1
	    fi
	else
	    return 1
	fi
    }
}

ask_additional () {
message=$1
macroname=$2
eval default=\$$macroname
case $default in
    '') default="none" ;;
esac
echo "# Default $message are: $default"
echo ' '
echo $n "Any additions to the above list? "$c
while true; do
    read ans
    case $ans in
    '') return 0;;
    *) eval $macroname=\"\$$macroname \$ans\"
    esac
    echo $n "More? "$c
done
}

ask_executable () {
what=$1
macroname=$2
while true; do
    eval default=\$$macroname
    echo $n "Which $what do you plan to use? [$default] "$c
    read ans
    case $ans in
    '') eval result=\$$macroname;;
    *) result=$ans;;
    esac
    case $result in
    /*) {
	  if test -x $result; then
	      eval $macroname=\$result
	      return 0
	  else
	      echo !!! Can\'t find an executable file \"$result\" !!!
	  fi
	};;
    *)	{
	  if locate_executable $result $user_path; then
	      eval $macroname=\$result
	      return 0
	  else
	      echo !!! Can\'t find \"$result\" along your path !!!
	      echo ' '
	  fi
	} ;;
    esac
done
}

ask_directory () {
what=$1
macroname=$2
while true; do
    eval default=\$$macroname
    echo $n "Which $what directory do you plan to use? [$default] "$c
    read ans
    case $ans in
    '') eval result=\$$macroname;;
    *) result=$ans;;
    esac
    if locate_directory $result; then
        eval $macroname=\$result
	return 0
    fi
done
}

check_writable () {
what=$1
macroname=$2
eval filename=\$$macroname
if test -d $filename; then
    if test -w $filename; then
	return
    else
	echo "!!! You do not  have write access to $filename !!!"
    fi
elif test -f $filename; then
    echo "!!! $filename is not a directory"
else
    echo "!!! Directory $filename does not exist !!!"
fi
ask_directory "$what" $macroname
}

if test -f Makefile; then
cat <<GAZONK
# I found Makefile in this directory.  This might mean that you already
# have installed the KLIC system before.

GAZONK
echo $n "May I clean-up the directory by \"make distclean\" first? "$c
if ask_yes_or_no yes 0; then
  make distclean ||
  give_up_config "Make distclean ends with non-zero return code"
  echo ' '
else
  give_up_config "OK, then I'll stop reconfiguration."
fi
fi

user_path=`echo $PATH | sed -e 's/:/ /g'`
export user_path

if locate_executable "gcc" $user_path; then
    CC=gcc
    cat <<GAZONK
# Found gcc in $where.
# I'd recommend using gcc for installing KLIC, as it's been tested
# mainly using gcc.

GAZONK
else
    CC=cc
fi

ask_executable "C compiler" "CC" || exit 1
echo ' '

case $CC in
  gcc)	OPTFLAGS="-O2 -fomit-frame-pointer"
	DEBUGFLAGS="-g"
	UOPTFLAGS="-fomit-frame-pointer";;
  cc)	OPTFLAGS="-O"
	DEBUGFLAGS=""
        UOPTFLAGS="";;
  *)	OPTFLAGS=""
	DEBUGFLAGS=""
        UOPTFLAGS="";;
esac

cat <<GAZONK
# During the installation procedure, the runtime library for the KLIC system
# will be compiled using $CC.  You can choose optimization flags and debug
# flags for this compilation now (I'll ask you later for default setting
# for compiling user programs later).

GAZONK
ask_with_default "optimization flags" OPTFLAGS
ask_with_default "debug flags" DEBUGFLAGS
echo " "

cat <<GAZONK
# When KL1 programs are compiled, they are compiled into C code and then
# compiled into executable using $CC.  You can specify optimization level
# and debug flag for $CC in the command line argument for the KLIC compiler.
#
# You can here select flags that'll be only set for optimized compilation,
# that is, flags that'll be supplied only when you specified -O# when you
# run the KLIC compiler.

GAZONK
ask_with_default "additional optimization flags" UOPTFLAGS
echo " "

if locate_executable "sicstus" $user_path; then
    PROLOG=sicstus
    cat <<GAZONK
# Found SICStus Prolog in $where.
# I'd recommend using SICStus for installing KLIC, as it's been tested
# only with SICStus.  Quintus may also work but I'm not quite sure.

GAZONK
else
    PROLOG=prolog
fi

ask_executable "Prolog" "PROLOG" || exit 1
echo ' '

if locate_executable "ranlib" $user_path; then
    RANLIB=ranlib
else
    RANLIB=true
    cat <<GAZONK
# I couldn't find "ranlib" along your path.
# Use "true" instead if your system doesn't need running ranlib.

GAZONK
    ask_executable "library indexer" "RANLIB" || exit 1
    echo ' '
fi

if locate_executable "make" $user_path; then
    MAKE=make
else
    MAKE=""
    cat <<GAZONK
# I couldn't find "make" along your path.

GAZONK
    ask_executable "make" "MAKE" || exit 1
    echo ' '
fi

if locate_executable "install" $user_path; then
    INSTALL=install
    INSTDIR="install -d"
else
    echo "# I couldn't find \"install\" along your path."
    INSTALL="cp -p"
    ask_executable "program installer" "INSTALL" || exit 1
    INSTDIR="mkdir -p"
    ask_executable "directory installer" "INSTDIR" || exit 1
fi

cat <<GAZONK
# For KLIC to support asynchronous stream I/O, the system should 
# deliver signals such as SIGIO or SIGPOLL when I/O becomes possible.
# However, some systems (such as Linux 1.0) does not support this.

GAZONK
echo $n "Does your system support I/O ready signals?"$c
if ask_yes_or_no yes 0; then
    ASYNCIO="#define"
else
    ASYNCIO="#undef"
fi
echo ' '

cat <<GAZONK
# The KLIC system will be installed under certain directories.
# You have to be able to write into that directory for installation.
# Also, the installed files under the directory should be visible from
# all the KLIC users (only yourself for a private installation).
#
# First, the root of the installation directory tree.

GAZONK

DIRPREFIX="/usr/local"
ask_directory "intallation root" DIRPREFIX ||
give_up_config "Coudn't determine installation root directory"

cat <<GAZONK

# By default, KLIC system will be installed in the subdirectories of
# the directory you specified ($DIRPREFIX).
# In the default setting, subdirectories used are:
#    $DIRPREFIX/bin:     for user command (klic)
#    $DIRPREFIX/lib:     for subprograms and libraries
#    $DIRPREFIX/include: for header files

GAZONK

KLICBIN=$DIRPREFIX/bin
KLICLIB=$DIRPREFIX/lib
KLICINCLUDE=$DIRPREFIX/include

echo $n  "May I use the default setting?"$c
ask_yes_or_no yes 0 ||
{
    ask_directory "user command" KLICBIN
    ask_directory "library" KLICLIB
    ask_directory "include file" KLICINCLUDE
}
check_writable "user command" KLICBIN
check_writable "library" KLICLIB
check_writable "include file" KLICINCLUDE
echo " "

LIBPATH=""
for dir in /lib /usr/lib /usr/local/lib; do
    if test -d $dir; then
	LIBPATH="$LIBPATH $dir"
    fi
done

cat <<GAZONK
# If you have some libraries in directories other than default ones,
# please specify them here.
GAZONK
ask_additional "library directories" LIBPATH
echo ' '

INCLUDEDIR=/usr/include
while test ! -d $INCLUDEDIR; do
    echo "# I couldn't find $INCLUDEDIR"
    ask_directory "default include file directory" INCLUDEDIR
done
cat <<GAZONK
# You can specify include directories for KL1 compilation in addition to:
#    $KLICINCLUDE
#
GAZONK
ask_additional "include directory for compiling KLIC" KLICINCLUDE
echo ' '

ADDLIBS=""
if locate_file libelf.a f $LIBPATH; then
  ADDLIBS="$ADDLIBS libelf"
fi
if locate_file libsocket.a f $LIBPATH; then
  ADDLIBS="$ADDLIBS libsocket"
fi
if locate_file libnsl.a f $LIBPATH; then
  ADDLIBS="$ADDLIBS libnsl"
fi

MORELIBS=""
echo "# You can specify more library archives in addition to the following."
echo "#    libc libm $ADDLIBS"
ask_additional "library archives" MORELIBS
echo ' '

ADDLIBS="$ADDLIBS $MORELIBS"
LIBFILES=''

echo $n "# Using library file(s):"$c
for lib in libc libm $ADDLIBS; do
  if locate_file $lib.a f $LIBPATH; then
    LIBFILES="$LIBFILES $where"
    echo $n " $where"$c
  else
    give_up_config "Couldn't find $lib.a in $LIBPATH"
  fi
done
echo " "

LIBSWITCHES=`echo " " $ADDLIBS | sed -n -e "s/ lib/ -l/gp"`

for dir in $LIBPATH ; do
   LIBSWITCHES="$LIBSWITCHES -L$dir"
done

USER=${USER:-unknown}
case $USER in
  unknown)
    if locate_executable "whoami" $user_path; then
	USER=`$where`
    fi
esac

locate_executable "nm" $user_path ||
give_up_config "Couldn't find "nm" along your path"

echo "# I'll make a summary of libraries for later use in analysis."
echo $n "# It may take a while."$c

rm -f nmout.all 2>/dev/null
for libfile in $LIBFILES; do
  echo $n .$c
  nm $libfile 2>/dev/null >>nmout.all
done
grep printf <nmout.all >nmout.tmp

try_sed()
{
    echo $n .$c
    sedargs=''
    for arg do
	sedargs="$sedargs -e '$arg'"
    done
    eval sed -n $sedargs <nmout.tmp >nmout.list
    grep '^printf$' nmout.list >/dev/null 2>/dev/null
    return
}

try_sed 's/^.* [ATDSI]  *[_.]*//p' 's/^.* [ATDSI] //p' ||
try_sed 's/^__*//' 's/^\([a-zA-Z_0-9$]*\).*xtern.*/\1/p' ||
try_sed '/|UNDEF/d' '/FUNC..GL/s/^.*|__*//p' ||
try_sed 's/^.* D __*//p' 's/^.* D //p' ||
try_sed 's/^_//' 's/^\([a-zA-Z_0-9]*\).*xtern.*text.*/\1/p' ||
try_sed '/|COMMON/d' '/|DATA/d' '/ file/d' 's/^\([^     ]*\).*/\1/p' ||
try_sed 's/^.*|FUNC |GLOB .*|//p' 's/^.*|FUNC |WEAK .*|//p' ||
try_sed 's/^[         ]*[0-9][0-9a-f]*[       ]*Def. Text[    ]*//p' ||
try_sed 's/^.* [AT]  *_[_.]*//p' 's/^.* [AT] //p' ||
give_up_config "nm didn't seem to work right or libraries are clobbered "

eval sed -n $sedargs <nmout.all >nmout.list

cat <<GAZONK
 done
#
# I now start testing availability of features I might use...

GAZONK

find_label ()
{
    grep "^$1\$" nmout.list >/dev/null 2>/dev/null
    return
}

if find_label nlist; then
	:
else
    echo <<GAZONK
# I need "nlist" to continue configuration, which I cannot find in:
#     $LIBFILES
# Please run configuration script again and specify appropriate library.
GAZONK
    give_up_config "nlist was not found"
fi

define="#define"
undef="#undef"

test_label()
{
    if find_label $1; then
	echo "     found \"$1\""
	eval $2=\$define
	return 0
    else
	echo "     cannot find \"$1\"; I'll try without it."
	eval $2=\$undef
	return 1
    fi
}

test_either()
{
    test_label $1 $3 ||
    test_label $2 DUMMY ||
    give_up_config "Can't find either $1 or $2"
}

test_include()
{
    file=$1
    shift
    macro=$1
    shift
    if locate_file $file f $INCLUDEDIR; then
	echo "     found \"$file\""
	eval $macro=\$define
	return 0
    else
	echo "     cannot find \"$file\"; I'll try without it."
	eval $macro=\$undef
	return 1
    fi
}

test_include string.h STRINGH

test_label setlinebuf SETLINEBUF
test_label lockf USELOCKF
test_label sigaction USESIG
test_label getrusage GETRUSAGE
test_either bcmp memcmp USEBCMP
test_either bcopy memcpy USEBCOPY
test_either bzero memset USEBZERO
test_either strchr index USESTRCHR
test_either usleep sleep USEUSLEEP

cat <<GAZONK

# Now I'll check whether your system prefixes some character
# to labels defined by C programs...
GAZONK

$CC -o testprefix testprefix.c $LIBSWITCHES ||
give_up_config "Couldn't compile label prefix test program"

NLIST_PREFIX_STRING=`./testprefix`
case $NLIST_PREFIX_STRING in
'') echo "# I'll use no prefixes at all." ;;
*) echo "# I'll use \"$NLIST_PREFIX_STRING\" as prefix." ;;
esac
echo ' '

echo "# Writing out config.h file."
cat <<GAZONK >config.h
/*
  Copyright 1994 Institute for New Generation Computer Technology
  Read COPYRIGHT for detailed information

  KLIC System Configuration Setting
  This file was created by KLIC configuration script.
  Date of Confuguration: `date`
  Configured by: ${USER:-unknown}
*/

/* Directories for installation */

#define KLICBIN "$KLICBIN"
#define KLICLIB "$KLICLIB"
#define KLICINCLUDE "$KLICINCLUDE"
#define KLIC_COMPILER "$KLICLIB/klic/kl1cmp"
#define KLIC_DBMAKER "$KLICLIB/klic/klicdb"

/* Laguage and program processing systems */

#define CC "$CC"
#define LD "$CC"
#define PROLOG "$PROLOG"
#define RANLIB "$RANLIB"

/* Additional CC flags for optimized compilation of KL1 programs */

#define UOPTFLAGS "$UOPTFLAGS"

/* Additional flags for LD */

#define LIBRARIES "-lklic $LIBSWITCHES"
#define LIBRARIES_T "-lklict $LIBSWITCHES"

/* String to be prefixed to C labels */
#define PREFIX_STRING "$NLIST_PREFIX_STRING"

/* Usual C macros depending on availability */

$ASYNCIO ASYNCIO
$STRINGH STRINGH
$SETLINEBUF SETLINEBUF
$USELOCKF USELOCKF
$USESIG USESIG
$GETRUSAGE GETRUSAGE
$USEBCMP USEBCMP
$USEBCOPY USEBCOPY
$USEBZERO USEBZERO
$USESTRCHR USESTRCHR
$USEUSLEEP USEUSLEEP
GAZONK
echo ' '

echo "# Writing out Makefile"
cat <<GAZONK >Makefile
# Copyright 1993, 1994 Institute for New Generation Computer Technology
# Read COPYRIGHT for detailed information
#
# Top-level Makefile for KLIC system
# This file was created by KLIC configuration script.
# Date of Confuguration: `date`
# Configured by: ${USER:-unknown}

########################################
# Directory Names
########################################

# Include file directory
KLICINCLUDE = $KLICINCLUDE

# Library directory
KLICLIB = $KLICLIB

# Executable directory
KLICBIN = $KLICBIN

########################################
# System-dependent switches
########################################

# If you are using Prolog systems different from SICStus Prolog,
# you need to modify the following line.
PROLOG = $PROLOG

# If you are not using gcc, change the following.
CC = $CC
LD = $CC

# Optimization flags for compiling the runtime system by CC.
OPTFLAGS = $OPTFLAGS
DEBUGFLAGS = $DEBUGFLAGS

# Additional CC flags for optimized compilation of KL1 programs.
UOPTFLAGS = $UOPTFLAGS

# Library search flags
LIBSWITCHES = $LIBSWITCHES

# Library archive indexer
RANLIB = $RANLIB

# Make program
MAKE = $MAKE

# Installer
INSTALL = $INSTALL
INSTDIR = $INSTDIR
INSTALLHDR = cp -p

# Prefix string put before C-defined labels
NLIST_PREFIX_STRING = "$NLIST_PREFIX_STRING"

GAZONK
cat <Makefile.tail >>Makefile ||
give_up_config "Can't create makefile properly"
echo ' '

mv config.h include/klic ||
give_up_config "Can't move config.h to an appropriate place"

clean_up_config

cat <<GAZONK
# All set!  Now you can compile the KLIC system by typing in "make all".
# If compilation is OK, I'd recommend testing it by running "make tests".
# You can then install the system by "make install".
#
# Good Luck!  Please report problems to "klic-bugs@icot.or.jp".

GAZONK
