#!/bin/sh
#
# Copyright (c) 2001 Michal Moskal <malekith@pld.org.pl>.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#	This product includes software developed by Michal Moskal.
# 4. Neither the name of the author nor the names of any co-contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY MICHAL MOSKAL AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $Id: xksi,v 1.2 2002/07/19 18:26:52 malekith Exp $
#

ksi_compiler=
target=
lang_compiler=
compiler_opt=
out_file=
cflag=
opt_ksi=
opt_lang=
lang=
files=
verbose=

system_conf=/usr/lib/ksi
local_conf=$HOME/.ksi

[ -r $system_conf/config ] && . $system_conf/config
[ -r $local_conf/config ] && . $local_conf/config

mktarget () {
  if [ "$(id -u)" = "0" ] ; then
    umask 022
    target_dir=$system_conf/$1
    test -d $system_conf || mkdir $system_conf
  else
    target_dir=$local_conf/$1
    test -d $local_conf || mkdir $local_conf
  fi
  rm -rf $target_dir
  mkdir $target_dir
cat > $target_dir/config <<EOF
target=$1
ksi_compiler=$2
target_conf=$target_dir/target_conf
EOF
  $2 -x ksi -E - -o $target_dir/target_conf <<EOF
!version 1
ksi_version .ksi_version
c_int_bits .c_int_bits
c_short_bits .c_short_bits
c_long_bits .c_long_bits
c_char_bits .c_char_bits
c_long_long_bits .c_long_long_bits
c_float_bits .c_float_bits
c_double_bits .c_double_bits
c_long_double_bits .c_long_double_bits
c_ptr_bits .c_ptr_bits
c_int_bytes .c_int_bytes
c_short_bytes .c_short_bytes
c_long_bytes .c_long_bytes
c_char_bytes .c_char_bytes
c_long_long_bytes .c_long_long_bytes
c_float_bytes .c_float_bytes
c_double_bytes .c_double_bytes
c_long_double_bytes .c_long_double_bytes
c_ptr_bytes .c_ptr_bytes
bytes_big_endian .bytes_big_endian
words_big_endian .words_big_endian
cpu .cpu
machine .machine
EOF
  exit 0
}

list_targets () {
  for f in $system_conf/* $local_conf/* ; do
    test -d $f || continue
    case "$f" in
      */lang.d )
        ;;
      * )
        . $f/config
        echo "$target:"
	echo "  compiler = $ksi_compiler"
	echo "  target_dir = $f"
	;;
    esac
  done
  exit 0
}

while : ; do
  if [ $# = 0 ] ; then
    break
  fi
  opt="$1"
  arg="$2"
  shift
  case $opt in
    -mktarget )
      mktarget "$1" "$2"
      ;;
    -list-targets )
      list_targets
      ;;
    -x )
      lang="$arg"
      shift
      ;;
    -t | -target )
      target="$arg"
      shift
      ;;
    -o )
      out_file="$arg"
      shift
      ;;
    -c )
      cflag=-c
      ;;
    -O* | -f* | -g* )
      ksi_opt="$ksi_opt $opt"
      ;;
    -W* | -w | -F* )
      lang_opt="$lang_opt $opt"
      ;;
    -v )
      ksi_opt="$ksi_opt $opt"
      verbose=1
      ;;
    -ksi-* )
      ksi_opt="$ksi_opt `echo $opt | sed -e 's/^-ksi//'`"
      ;;
    -lang-* )
      lang_opt="$lang_opt `echo $opt | sed -e 's/^-lang//'`"
      ;;
    -* )
      echo "Bad option: $opt"
      exit 1
      ;;
    * )
      files="$files '$opt'"
      ;;
  esac
done

if [ "X$target" = "X" ] ; then
  cpu=$(uname -p)
  if [ "X$cpu" = "X" ] ; then
    cpu=unknown
  fi
  target=$(echo $(uname -m)-$cpu-$(uname -s) | tr 'A-Z' 'a-z')
fi

verb () {
  if test "$verbose" ; then
    echo "$0: $*" 1>&2
  fi
}

fatal () {
  echo "$0: fatal error: $*" 1>&2
  exit 1
}

call () {
  verb "calling $*"
  "$@"
}

if [ -d $local_conf/$target ] ; then
  . $local_conf/$target/config
elif [ -d $system_conf/$target ] ; then
  . $system_conf/$target/config
else
  fatal "target $target unknown"
fi

verb "using target=$target"

compile () {
  file="$1"
 
  if test $lang ; then
    if [ -r $local_conf/lang.d/$lang ] ; then
      . $local_conf/lang.d/$lang
    elif [ -r $system_conf/lang.d/$lang ] ; then
      . $system_conf/lang.d/$lang
    elif [ $lang = ksi ] ; then
      : ok
    else
      fatal "cannot find language description file for '$lang'"
    fi
  else
    suf=`echo $file | sed -e 's/.*\.//'`
    s=
    # first look for driver
    for f in $local_conf/lang.d/* $system_conf/lang.d/* ; do
      [ -r $f ] || continue
      . $f
      for s in $suffixes ; do
        if [ "X$suf" = "X$s" ] ; then
          break 2
        fi
      done
    done
    
    if [ "X$s" != "Xksi" -a "X$suf" = "Xksi" ] ; then
      lang=ksi
    elif [ "X$suf" != "X$s" ] ; then
      fatal "cannot find compiler suitable for file '$file'"
    fi

    verb "using lang=$lang"
  fi

  umask 077

  if test -d $HOME/tmp ; then
    chmod 700 $HOME/tmp 
  else
    mkdir $HOME/tmp
  fi
  
  tmpout=$HOME/tmp/ksicc-$$.ksi
  target_flags=
  case "$out_file" in
    *.ksi )
      tmpout="$out_file"
      ;;
    *.iksi )
      target_flags=-E
      ;;
    *.s )
      target_flags=-S
      ;;
    * )
      ;;
  esac
 
  if [ $lang = ksi ] ; then
     tmpout="$file"
  else
    call $lang_compiler \
  	-target $target \
	-target-conf $target_conf \
  	$lang_opt \
	-input "$file" \
	-output "$tmpout" || {
      if [ "X$tmpout" != "X$out_file" ] ; then
        rm -f $tmpout
      fi
      exit 1
    }
  fi

  if [ "X$tmpout" != "X$out_file" ] ; then
    if [ "X$out_file" = "X" ] ; then
      if test "$cflag" ; then
        out_file=`echo $file | sed -e "s/\\.$suf//"`.o
      else
        out_file=a.out
      fi
    fi
    
    call $ksi_compiler $add_ksi_opt $ksi_opt $cflag $tmpout -o $out_file || exit 1
    
    if [ "X$file" != "X$tmpout" ] ; then
      rm -f $tmpout
    fi
  fi
}

eval "for f in $files ; do compile \"\$f\" ; done"

exit 0
