#!/bin/sh -e
# config: a KerGIS tools script to build and configure the compilation
# 	tree.
#
# $Id: rkconfig,v 1.77 2007/03/22 16:51:31 tlaronde Exp $
#
#  Copyright 2004 Thierry LARONDE <tlaronde@polynum.com>
#  All rights reserved. 
#  
#  This work is under the KerGIS Public Licence v1.0
# 
#  See the COPYRIGHT file at the root of the source directory or see
#  http://www.kergis.org/licence.txt for complete information.
# 
# !!!THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES!!! 
#                      USE IT AT YOUR OWN RISK 

# NOTES: All the debug messages MUST be sent to stderr since stdout is
# reserved for legal requested values.
# The only message sent to stdout is OBJDIR (allowing a script to 
# retrieve the value and continue 'cd $OBJDIR; make...'.
#
# An alternative method may be to only set transient variables and to
# not echo the values. YMMV.

#========== EXTERNS SETTABLE
# An administrator may adjust this to point to a dir holding local
# conffiles
#
readonly MATRIXCONFDIR=/etc/risk

#================== NOTHING TO CHANGE BELOW! =====================

#========== GLOBALS
# this version supports this api
#
rk_api_version=1.0C

prog_version='$Id: rkconfig,v 1.77 2007/03/22 16:51:31 tlaronde Exp $'

usage="
	$program [-D] [-h] [-V] [-ps] [-d PROJECTDIR] [CONF]
Configure a rkcomp compliant build tree.
If the -d PROJECTDIR option is not given, uses the working dir as PROJECTDIR.

Options:
 -d	use this Dir as PROJECTDIR [default working dir]
 -p	Print the OBJDIR value and exit (do NOT configure)
 -s	Show options and exit
 -D	turn Debug information on
 -h	display this Help and exit
 -V	display Version information and exit

 CONF
	name of a CONF file [optional]

"

version="$prog_version
Written by Thierry Laronde.

Copyright (c) 2004-2005 Thierry Laronde <tlaronde@polynum.com>

All rights reserved. KerGIS Public Licence v1.1. NO WARRANTIES!."

#========== INITIAL SETUP
TMPDIR=${TMPDIR:-/tmp}
tmpdir=$TMPDIR/$$
! [ -d $tmpdir ] && mkdir $tmpdir

# remove temporary files on HUP, INT, QUIT, PIPE, TERM
#
trap " debug F '!!! Unexpected event. Try -d to debug'; clean_tmp; exit 1;"  HUP INT QUIT PIPE TERM

#========== SUBFUNCTIONS

clean_tmp()
{
	rm -fr $tmpdir
}

# rk_exit() shall be used by a PROJECT file to let rkconfig exit cleanly
# in case an error is detected
rk_exit()
{
	clean_tmp
	debug E "PROJECT file exiting on error"
	exit 1
}

# debug writes info (L for LOG), warning (W for WARNING), error
# (E for ERROR) or fatal (F for FATAL) for a programming unrecoverable
# error followed by the message on stderr
#
debug()
{
	case $1 in
	  A) echo "->" | tr -d '\n' 1>&2;;
	  E) echo "$program ERROR: " | tr -d '\n' 1>&2;;
	  F) echo "$program FATAL: " | tr -d '\n' 1>&2;;
	  L) echo "	" | tr -d '\n' 1>&2;;
	  W) echo "WARNING: " | tr -d '\n' 1>&2;;
	  *) echo "$1: " | tr -d '\n' 1>&2;;
	esac
    echo "$2" 1>&2
    return
}

# deref : dereferencing symlinks
#
deref()
{
	pathname="$1"
	while [ -h "$pathname" ]; do
	  wd=$(dirname $pathname)
	  pathname=$(ls -l $pathname | sed 's/^.*-> *//')
	  pathname=$(derel $wd "$pathname")
	done

	echo $pathname
}

# derel suppress the ./ and ../ in a path, and deref symlinks
# derel WORKING_DIR PATH_TO_DERELATIVATE
#
derel()
{
	# if not beginning by a slash, put WORKING_DIR before
	derel_path=$(echo $2 | sed 's@^\([^/]\)@'$1'/\1@')

	derel_path=$(echo $derel_path | sed -e 's@/\./@/@g' -e 's@/\.$@@')
	if echo $derel_path | grep -q '^/\{0,1\}../'; then
	  error invalid_path $derel_path
	fi

	while echo $derel_path | grep -q '/../'; do
	  # just the first occurrence will be replaced. We work from left
	  # to right
	  derel_path=$(echo $derel_path | sed -e 's@/[^/]\{1,\}/\.\./@/@')
	  if echo $derel_path | grep -q '^/\{0,1\}../'; then
	    error invalid_path $derel_path
	  fi
	done
	
	# If there is a last '/..' take this into account.
	# Here, we are guaranteed that there is no more '/../' elsewhere
	# and that there is something before
	derel_path=$(echo $derel_path | sed 's@/[^/]\{1,\}/\.\.$@/@')

	# suppress trailing '/' if something before
	derel_path=$(echo $derel_path | sed 's@\(.\)/$@\1@')

	echo $derel_path
}

error()
{
	case $1 in
	  failed_to_build_tools) debug E "I failed to build the needed tools!";
		debug L "Please debug!";;
	  option) debug E "This option is unknown!";
		debug USAGE "$usage";;
	  missing_confdir) debug E "$TOOLDIR does not lead to my tools!";
	    debug USAGE "$usage";;
	  missing_conffile) debug E "The conffile $2 does not exist!";;
	  missing_deps) debug E "The information about dependencies $PROJECT.deps does not exist!";;
	  missing_list) debug E "The programs list $PROJECT.list does not exist!";;
	  missing_map) debug E "The map $PROJECT.map does not exist!";;
	  missing_projectfile) debug E "The PROJECT is not defined!";;
	  no_project) debug E "No PROJECT defined!";;
	  no_compiler) debug E "There is no compiler found!";;
	  not_a_valid_sysconf) debug E "A sys conf shall not be dired!";
		debug L "Your proposition was: $2";;
	  objdir_exists) debug E "Directory $2 exists! Suppress it first!";;
	  root_notallowed) debug E "You are not allowed to run this as root!";
		debug L "Since you have the means to be root, you have the means not to be!";
		debug L "Create a directory writable by a normal user and config as this very user.";;
	  stdc) debug E "The compiler '$CC' is not STDC compliant!";;
	  sysconf_not_found) debug E "System conf file $2 not found!";
		debug L "Search path was $confpath";;
	  unable_to_mkdir) debug E "Unable to make dir $2!";;
	  wrong_api) debug E "The requested rkcomp version: $RK_API_VERSION doesn't match my version: $rk_api_version!";;
	  wrong_confdir) debug E "$PROJECTDIR/conf has the wrong number of PROJECT files!";;
	  wrong_map_format) debug E "The PROJECT's map has not the required number of fields!";;
	  wrong_projectdir) debug E "Dir: $2 does not exist!";
		debug USAGE "$usage";;

	esac

	# don't suppress temp file if debugging
	[ "x$debug_mode" = "xYES" ] || clean_tmp

	exit 1
}

# Fully Qualifying a conf filename
#
fq_conf()
{
	fqconf=$1
	case $level in
	  SYS) confpath="$TOOLDIR/libdata $PROJECTDIR/conf $MATRIXCONFDIR";;
	  USER) confpath="$MATRIXCONFDIR $PROJECTDIR/conf $TOOLDIR/libdata";;
	esac

	# a normal CONFIG is one in rkcomp/libdata, $PROJECTDIR/conf or 
	# $MATRIXCONFDIR and has no dir specification
	is_dired=`echo $fqconf | sed '/\//!d'`
    if [ "x$is_dired" = "x" ]; then
	  for path in $confpath; do
	    [ ! -f $path/$fqconf ] || { echo $path/$fqconf; return 0; }
	  done
	  echo $fqconf; return 1 # sysconf_not_found
	elif [ $level = "SYS" ]; then
	  echo $fqconf; return 2 # not_a_valid_sysconf
	elif [ -f "$fqconf" ]; then
      echo $fqconf; return 0
	else
	  echo $fqconf; return 3 # missing_conffile
	fi
}

# a CONFIG file will be only sourced once. The complete filename is
# cached, and if it is already in the cache (already sourced) it shall
# not be sourced once more.
# The `define' function handles this, returns 0 when entered in the
# cache, and 1 if already present. The calling function shall not source
# it then.
#
cache=$tmpdir/cache
cat /dev/null >$cache

define()
{
	if grep -q "$1" $cache; then
	  debug L "config pathname $1 already cached"
	  return 1
	else
	  echo $1 >> $cache
	  debug A "config pathname $1 entered in cache"
	  return 0
	fi
}
# to allow inclusion of other conf files in a conf file
#
include()
{
	conf=$(fq_conf $1)	
	case $? in
	  0) ;;
	  1) error sysconf_not_found $conf;;
	  2) error not_a_valid_sysconf $conf;;
	  3) error missing_conffile $conf;;
	esac

	# then simply source
	if define $conf; then
	  debug A "Sourcing $conf"
	   . $conf
	else
	  debug L "$conf already sourced. Skipping"
	fi
}

#========== INITIALIZATIONS
# Name by which this script was invoked.
#
program=`basename $0`

print_objdir=NO
debug_mode=NO
show_options=NO

# The CONF file name. The CONF is a _Bourne Shell_ compliant 
# text that is simply sourced
#
CONF=
PROJECTDIR=
PROJECT_VERSION=
TOOLDIR=
# Unset some variables that are set by some shells (tcsh for example)
# so these variables can not be passed by environment, but only in
# a conf file
#
TARGET=
TARGET_ARCH=
MATRIX=
MATRIX_ARCH=
MATRIX_RELEASE=

#=========== PROCESSING
while [ $# -gt 0 ]; do
	case "$1" in
	  -d) shift;
		readonly PROJECTDIR=$(derel $(pwd) $1);
		[ -d "$PROJECTDIR" ] || error wrong_projectdir $PROJECTDIR;;
	  -D) set -x; debug_mode=YES;;
	  -h|--help) echo "$usage"; clean_tmp; exit 0;;
	  -V|--version) echo "$version"; clean_tmp; exit 0;;
	  -p) print_objdir=YES;;
	  -s) show_options=YES;;
	  -*) error option ;;
	  *) CONF=$1;;
	esac
shift	
done

#========== INITIAL CHECKS
#------ SAFETY
# We refuse to go if we are invoked as root. Period.
#
[ `id -u` -ne 0 ] || error root_notallowed;

#------ MATRIX CONFIGURATION
# If MATRIXCONFDIR is not empty and $MATRIXCONFDIR/rkcomp.conf exists
# this is the main configuration file (decided by the admin so source
# it.
#
if [ "x$MATRIXCONFDIR" != "x" -a -r $MATRIXCONFDIR/rkcomp.conf ]; then
	. $MATRIXCONFDIR/rkcomp.conf
	define $MATRIXCONFDIR/rkcomp.conf
fi

# PROJECTDIR is special: I need it rapidly and it shall not change
# config shall be run from PROJECTDIR
#
[ "x$PROJECTDIR" != "x" ] || readonly PROJECTDIR=`pwd`

# To be here or not to be. To be sure to access what is shipped with
# this. TOOLDIR has been cleared at the beginning and might has been
# set by $MATRIXCONFDIR/rkcomp.conf if exists. So test.
#
if [ "x$TOOLDIR" = "x" ]; then
	if expr "$0" : '\/' 1>/dev/null; then
	  TOOLDIR=$(dirname `deref "$0"`)
	else
	  for path in $(pwd) `echo $PATH | tr ':' ' '`; do
	    # ensure we are feeding deref with absolute path names
		#
	    path=$(derel $(pwd) $path) 
	    [ ! -f $path/$0 ] || { TOOLDIR=`dirname $(deref "$path/$0")`; break; }
	  done
	fi

	# rkconfig is in ./bin, so suppress it to have TOOLDIR
	#
	TOOLDIR=$(derel $(pwd) $TOOLDIR)
	TOOLDIR=${TOOLDIR%/bin}
fi

readonly TOOLDIR

[ "x$TOOLDIR" != "x" ] || error missing_confdir 

# Identify the PROJECT
#
[ -d "$PROJECTDIR/conf" ] || error missing_projectfile

# Set the version if a CID file is here
#
if [ -f $PROJECTDIR/CID ]; then
	PROJECT_ID=`sed -n 's/^USRI:[ 	]*\([0-9A-F.]\{3,\}\)[ 	]*$/\1/p' $PROJECTDIR/CID`
	PROJECT_VERSION=`sed -n 's/^VERSION:[ 	]*\([^ 	]*\)[ 	]*$/\1/p' $PROJECTDIR/CID`
fi

# look for the number of candidate file. Shall be one and only one
#
[ $(find $PROJECTDIR/conf -type f | sed -n '/\/[A-Z0-9_-]\{1,\}$/p' | wc -l) -eq 1 ] || error wrong_confdir

readonly PROJECT=`find $PROJECTDIR/conf -type f | sed -n '/\/[A-Z0-9_-]\{1,\}$/p'`

# PROJECT shall not be sourced more than once, neither included in other
# conf file. 
#
define $PROJECT 

# make available for us meta-informations about PROJECT (PROJECT.cid)
#
VENDOR=unknown
SET_VENDOR=NO
SET_PKGNAME=YES
[ ! -f $PROJECT.cid ] || . $PROJECT.cid

if [ $show_options = "YES" ]; then
	if [ -f "$PROJECT.options" ]; then
	# more is defined as optional...
	cat $PROJECT.options
	else
	 debug L "No options proposed by $(basename $PROJECT)"
	fi
	clean_tmp;
	exit 0
fi

#------ SAFETY
# some var will not be allowed in user's conf.
#
var_not_allowed=$tmpdir/not_allowed
echo IFS PROJECT PROJECTDIR TOOLDIR MATRIXCONFDIR CONF >$var_not_allowed

#----- Required files

# a list shall be provided by the PROJECT
#
[ -f "$PROJECT.list" ] || error missing_list 

# and a map shall be provided too
#
[ -f "$PROJECT.map" ] || error missing_map 

# and a description of dependencies giving chunks to display if a required
# element is missing.
#
[ -f "$PROJECT.deps" ] || error missing_deps

#------TARGET ENVIRONMENT VARIABLES 
# Can I find my stuff?
#
[ ! -f "$TOOLDIR/lib/librkcompsh" ] && error missing_confdir

[ ! -f "$TOOLDIR/libdata/rkcomp" ] && error missing_confdir

# There is a chicken and eggs problem: to build OBJDIR I need OBJROOTDIR
# TARGET TARGET_ARCH MATRIX MATRIX_ARCH that can be set in CONF, because
# some fonctions write data in OBJDIR. So start by defining these
# values.

# First pass on CONF
#
if [ "x$CONF" != "x" ]; then
	level="USER"
	CONF=$(fq_conf $CONF)
	case $? in
	  0) ;;
	  1) error sysconf_not_found $conf;;
	  2) error not_a_valid_sysconf $conf;;
	  3) error missing_conffile $conf;;
	esac
	TARGET=$(sed -n 's/^TARGET=//p' $CONF | tr ' 	' '__')
	TARGET_ARCH=$(sed -n 's/^TARGET_ARCH=//p' $CONF | tr ' 	' '__') 
	MATRIX=$(sed -n 's/^MATRIX=//p' $CONF | tr ' 	' '__') 
	MATRIX_ARCH=$(sed -n 's/^MATRIX_ARCH=//p' $CONF | tr ' 	' '__')
	MATRIX_RELEASE=$(sed -n 's/^MATRIX_RELEASE=//p' $CONF | tr ' 	' '__')
	OBJDIRPREFIX=${OBJDIRPREFIX:-$(sed -n 's/^OBJDIRPREFIX=//p' $CONF | tr ' 	' '__')}
fi

# Defaulting if not set
#
: ${TARGET:=$(uname -s | tr ' 	' '__')}
: ${TARGET_ARCH:=$(uname -m | tr ' 	' '__')}
: ${MATRIX:=$(uname -s | tr ' 	' '__')}
: ${MATRIX_ARCH:=$(uname -m | tr ' 	' '__')}
: ${MATRIX_RELEASE:=$(uname -r | tr ' 	' '__')}

#------ STARTING TO BUILD THE TREE
# if not set in a configfile or on command line
#
: ${OBJDIRPREFIX:=$PROJECTDIR}
OBJDIRPREFIX=$(echo $OBJDIRPREFIX | tr ' 	' '__')

joke=
if [ "x$CONF" = "x" ]; then
	CONF=generic
else
	[ "$(basename $CONF)" != "generic" ] || joke="JOKE"
fi

readonly OBJDIR=$OBJDIRPREFIX/$VENDOR.$(basename $PROJECT)-$(basename $CONF)${joke}_${MATRIX}-${MATRIX_RELEASE}-${MATRIX_ARCH}_${TARGET}-${TARGET_ARCH}

# PKG is the name of the tarball without extension
#
readonly PKG=$VENDOR.$(basename $PROJECT)-$(basename $CONF)${joke}_${TARGET}-${TARGET_ARCH}

# if requested to print OBJDIR, do it and continue
#
[ "$print_objdir" != "YES" ] || { echo "$OBJDIR"; clean_tmp; exit 0;}

if [ -d "$OBJDIR" ]; then
	error objdir_exists "$OBJDIR"
else
	mkdir -p $OBJDIR/.rkcomp || error unable_to_mkdir $OBJDIR
fi

# our own stuff
#
. $TOOLDIR/lib/librkcompsh
level=SYS
include rkcomp

#------ the tree dir and files we are going to use
# the files rkconfig is responsible for
#
my_config=$OBJDIR/.rkcomp/config
cat /dev/null > $my_config

# create the directory where we put ldsonames if not found pointing
# to the shared libraries (needed at compile time only)
# This is defined in librkcompsh
#
mkdir $rk_lddir

# the map
#
rk_map=$OBJDIR/.rkcomp/map
rk_list=$OBJDIR/.rkcomp/list

# create empty libes files
#
rk_static=$OBJDIR/.rkcomp/libes.static
rk_dshared=$OBJDIR/.rkcomp/libes.dshared
touch $rk_static
touch $rk_dshared

# rkpkg stuff
#
mkdir $OBJDIR/.rkcomp/installed
mkdir $OBJDIR/.rkcomp/preserved
mkdir $OBJDIR/.rkcomp/install_bin
mkdir $OBJDIR/.rkcomp/install_data

# variables headers (for example iconv_defs.h)
#
mkdir $OBJDIR/.rkcomp/include

# Trying to be smart...
# XXX the tr arguments are a trick to conform to susV3 and allow use
# on old SysV
#
MATRIX=$(echo $MATRIX | tr '[A-Z]' '[a-z]')
MATRIX_ARCH=$(echo $MATRIX_ARCH | tr '[A-Z]' '[a-z]')
MATRIX_RELEASE=$(echo $MATRIX_RELEASE | tr '[A-Z]' '[a-z]')
TARGET=$(echo $TARGET | tr '[A-Z]' '[a-z]')
TARGET_ARCH=$(echo $TARGET_ARCH | tr '[A-Z]' '[a-z]')

if fq_conf M_$MATRIX 1>/dev/null; then
	include M_$MATRIX
else
	MATRIX=default
fi

if fq_conf T_$TARGET 1>/dev/null; then
	include T_$TARGET
else
	TARGET=default
fi

# time to include the user conf if specified
#
[ "$CONF$joke" = "generic" ] || { level="USER"; include $CONF;}

# PKGDIR stuff
# if ask to prefix with VENDOR do it
#
PKGDIR=$DISTDIR
[ "x$SET_VENDOR" != "xYES" ] || PKGDIR=$PKGDIR/$VENDOR
[ "x$SET_PKGNAME" != "xYES" ] || PKGDIR=$PKGDIR/$PKGNAME

#------ DEFINING THE API AND THE ABI

# Be sure we have at least the POSIX programs
#
rk__check_required $TOOLDIR/libdata/rkcomp.deps MAKE SHELL CC AR LEX YACC CLIB MATHLIB LEXLIB

$CC -E $TOOLDIR/libdata/api.h \
  | sed -n 's/^@@\(.*\) *= *\(.*\)$/\1=\2/p' >>$my_config

$CC -E $TOOLDIR/libdata/abi.h \
  | sed -n 's/^@@\(.*\) *= *\(.*\)$/\1=\2/p' >>$my_config

# ENDIANNESS
# specifications taken from NetBSD sources (http://www.netbsd.org)
#
case $TARGET_ARCH in
	i?86|ia32|ia64) ENDIANNESS=1234;;
	arm|mips|acorn*|cats|evbarm|evbmips|hpcarm|netwinder) ENDIANNESS=;;
	sbmips|sh3|sh5|shark|sh5|evbsh3|evbsh5) ENDIANNESS=;;
	algor|arc|cobalt) ENDIANNESS=1234;;
	alpha) ENDIANNESS=1234;;
	amd64) ENDIANNESS=1234;;
	hpc|hpcmips|hpcsh) ENDIANNESS=1234;;
	m68k|amiga|atari|cesfic|hp300|hp700|luna68k|mac68k|mvme68k) ENDIANNESS=4321;;
	news68k|next68k|sun2|sun3) ENDIANNESS=4321;;
	powerpc|amigappc|bebox|evbppc|ibmnws|macppc|mvmeppc|ofppc|pmppc) ENDIANNESS=4321;;
	power*) ENDIANNESS=4321;;
	prep|sandpoint) ENDIANNESS=4321;;
	dreamcast) ENDIANNESS=1234;;
	hppa|hp700) ENDIANNESS=4321;;
	mipsco|newsmips|sgimips) ENDIANNESS=4321;;
	mmeye) ENDIANNESS=4321;;
	pc532) ENDIANNESS=1234;;
	pdp10) ENDIANNESS=4321;;
	playstation2) ENDIANNESS=1234;;
	pmax) ENDIANNESS=1234;;
	sparc|sparc64) ENDIANNESS=4321;;
	vax) ENDIANNESS=1234;;
	*) ENDIANNESS=;;
esac

[ "$ENDIANNESS" ] || debug W "Endianness is not defined!"

# Rectify the ability set by the compile environment to match the
# supported objects on the host
# SUPPORTED_TYPES are the TYPES finally supported, comma separated
#
SUPPORTED_TYPES=
[ "x$AR" = "x" ] || SUPPORTED_TYPES="static"
[ "x$LD_DSHARED" = "x" ] || SUPPORTED_TYPES="$SUPPORTED_TYPES dshared"
SUPPORTED_TYPES=$(echo $SUPPORTED_TYPES | sed -e 's/^ *//' -e 's/ \{1,\}/ /g' -e 's/ /,/g')

# Suppress some LIB possibilities if not supported
#
for type in static dshared; do
	echo $SUPPORTED_TYPES | grep -q $type || case $type in
	  static) MAKE_STATIC_LIB=NO;;
	  dshared) MAKE_DSHARED_LIB=NO;;
	esac
done


# REQUESTED_TYPES are the types of lib (for creation) requested. It will
# be generally equal to SUPPORTED_TYPES, but user or PROJECT can decide
# to reduce the possibilities.
#
REQUESTED_TYPES=
[ "x$MAKE_STATIC_LIB" != "xYES" ] || REQUESTED_TYPES="static"
[ "x$MAKE_DSHARED_LIB" != "xYES" ] || REQUESTED_TYPES="$REQUESTED_TYPES dshared"

#------ Time to complete the CONFIG 
# make the `config' generated variables present
#
.  $my_config

# if STDC not supported, stop
#
[ "$STDC" = "YES" ] || error stdc

# then source the PROJECT to set variables and functions
#
. $PROJECT

# verify the rkcomp API requested by the PROJECT
#
[ "x$RK_API_VERSION" = "x$rk_api_version" ] || error wrong_api

#------ HANDLING THE MAP
# Preprocessing.
# normalize it: 
# - no empty lines
# - no spaces at beginning
# - no spaces between conditionals '?' and action
# - remove comments
#
map=$tmpdir/map
cat $PROJECT.map $MAP_ADD \
	| sed -e '/^$/d' \
	-e '/^ *#/d' \
	-e 's/^ *//' \
	-e 's/^\(\$[a-zA-Z_][a-zA-Z0-9_]*\)[ 	]*?[ 	]*/\1?/' \
	-e 's/ \{1,\}/ /g' > $map

# and this map has a special format
#
tmp=`awk '
	BEGIN { FS = " "; }
	NF != nbfields { printf "WRONG"; exit; }
' nbfields=6 $map`

[ "x$tmp" =  "x" ] || error wrong_map_format 

# These ones are always replaced in PROJECT.map
#
cat - >$tmpdir/map.sed <<EOT
s@\\\$PROJECTDIR@$PROJECTDIR@g
s@\\\$OBJDIR@$OBJDIR@g
s@\\\$PKGDIR@$PKGDIR@g
s@\\\$TARGETBINDIR@$TARGETBINDIR@g
s@\\\$TARGETSBINDIR@$TARGETSBINDIR@g
EOT

# if PROJECT added variables via MAP_REPLACE, replace these ones too
# copying the map (already normalized)
#
for var in $MAP_REPLACE; do
	eval value=\$$var
	echo 's@\$'$var@$value@g >> $tmpdir/map.sed
done

# if PROJECT added list variables via MAP_GREPLACE, extract the line
# and add as many lines with indices as there are variables
#
for var in $MAP_GREPLACE; do
	eval values=\$$var
	sed -n "/\\\$$var/p" $map > $tmpdir/map_greplace
	ed $map<<EOT
g/\\\$$var/d
w
q
EOT
	for value in $values; do
	  sed "s@\\\$$var@$value@g" $tmpdir/map_greplace >> $map
	done
done

# Conditionals.
# First we retrieve all the conditions i.e. all the alpha-num words
# starting at the beginning of a line until a '?'. If the variable is
# set to uppercase "YES", the remaining of the line is kept. Else, it
# is discarded.
#
for condition in `sed -n 's/^\$\([a-zA-Z_][a-zA-Z0-9_]*\)?.*$/\1/p' $map`; do
	eval value=\$$condition
	if [ "x$value" = "xYES" ]; then 
	  echo "s/^\\\$$condition?//" >> $tmpdir/map.sed
	else # every other value including lowercase yes
	  echo "/^\\\$$condition?/d" >> $tmpdir/map.sed
	fi
done

# doing all the manipulation
#
sed -f $tmpdir/map.sed $map > $rk_map

#------ HANDLING THE LIST
# Normalize it (no comments, no blank lines allowed for Makefile in
# OBJDIR to work correctly)
#
list=$tmpdir/list
cat $PROJECT.list $LIST_ADD \
	| sed -e '/^$/d' \
	-e '/^#/d' $PROJECT.list > $list

# if PROJECT added variables via LIST_REPLACE, replace these ones too
# copying the list (already normalized)
# Ensure $tmpdir/list.sed exists, since LIST_REPLACE may eval to zero
# string
#
cat /dev/null > $tmpdir/list.sed
for var in $LIST_REPLACE; do
	eval value=\$$var
	echo 's@\$'$var@$value@g >> $tmpdir/list.sed
done

# if PROJECT added list variables via LIST_GREPLACE, extract the line
# and clones the line with every value
#
for var in $LIST_GREPLACE; do
	eval values=\$$var
	sed -n "/\\\$$var/p" $list > $tmpdir/list_greplace
	ed $list<<EOT
g/\\\$$var/d
w
q
EOT
	for value in $values; do
	  sed "s@\\\$$var@$value@g" $tmpdir/list_greplace >> $list
	done
done

sed -f $tmpdir/list.sed $list > $OBJDIR/.rkcomp/list

# an easy way to publish how far we are (used in OBJDIR/Makefile)
#
rk_nb_dirs=$(sed -n '$=' $OBJDIR/.rkcomp/list)

#========== LIBRARIES NAMES HANDLING
# Adding the translated lib names (discarding not installable)
# For optimization extract the libes in a separate file
#
sed -n -e '/^[^ ]\{1,\} [^ ]\{1,\} [^ ]\{1,\} \*/d' \
       -e '/lib[^\/]\{1,\}__/p' $rk_map >$tmpdir/libes

# and suppress them in rk_map if this file is not empty
#
if [ -s $rk_map ]; then
ed -s $rk_map<<EOT
g/lib[a-zA-Z0-9_-]*__/d
w
q
EOT
fi

cat /dev/null >$tmpdir/trlib

for type in $REQUESTED_TYPES; do
	case $type in
	  static) sed ${LIB_A_TR} $tmpdir/libes | sed ${LIB_A_TR} >>$tmpdir/trlib; 
	# create symbolic links for LDANAME if used as compile environment
		if [ "$(rk_mk_ldaname libXXX__0)" != "$(rk_mk_realaname libXXX__0)" ]; then
	      sed -n 's/^[^ ]\{1,\} [^ ]\{1,\} [^ ]\{1,\} \([^ ]\{1,\}__[0-9]\{1,\}[0-9.]*\) .*$/+ l \1 \1 * */p' $tmpdir/libes \
	       | sed 's@\(lib[^/]\{1,\}\)__[0-9.]\{1,\} @\1__ @2' \
	       | sed ${LIB_A_TR} | sed  ${LIB_A_TR} \
	       | sed 's/^\(.\) ./\1 l/' >>$tmpdir/trlib
		 fi;; 

	  dshared) sed ${LIB_DSH_TR} $tmpdir/libes | sed ${LIB_DSH_TR}>>$tmpdir/trlib;
	# create symbolic links to SONAME
		if [ "$(rk_mk_elf_soname libXXX__0.0)" != "$(rk_mk_elf_realsoname libXXX__0.0)" ]; then
	   sed -n 's/^[^ ]\{1,\} [^ ]\{1,\} [^ ]\{1,\} \([^ ]\{1,\}__[0-9]\{1,\}[0-9.]*\) .*$/+ l \1 \1 * */p' $tmpdir/libes \
	  | sed 's@\(lib[^/]\{1,\}\)__\([0-9]\{1,\}\)\.[0-9.]\{1,\} @\1__\2 @2' \
	  | sed ${LIB_DSH_TR} | sed  ${LIB_DSH_TR} \
	  | sed 's/^\(.\) ./\1 l/' >>$tmpdir/trlib; 
	  fi

	# create symbolic links for LDSONAME if used as compile environment
		if [ "$(rk_mk_elf_ldsoname libXXX__0.0)" != "$(rk_mk_elf_realsoname libXXX__0.0)" ]; then
	   sed -n 's/^[^ ]\{1,\} [^ ]\{1,\} [^ ]\{1,\} \([^ ]\{1,\}__[0-9]\{1,\}\.[0-9.]\{1,\}\) .*$/+ l \1 \1 * */p' $tmpdir/libes \
	   | sed  's@\(lib[^/]\{1,\}\)__[0-9.]\{1,\} @\1__ @2' \
	  | sed ${LIB_DSH_TR} | sed  ${LIB_DSH_TR} \
	  | sed 's/^\(.\) ./\1 l/' >>$tmpdir/trlib
	  fi;; 
	esac
done

# add the newly generated lines
#
cat $tmpdir/trlib >>$rk_map

[ "$debug_mode" != "YES" ] || set >$my_config.debug

level=SYS
cat $(fq_conf rkcomp) $(fq_conf M_default) $(fq_conf T_default) $(fq_conf C_posix) $PROJECT \
  | sed -n 's@^\([A-Za-z0-9_-]\{1,\}\)=.*$@/^\1=/p;t@p' \
  | sort | uniq  > $tmpdir/sed

# variables temporarily placed in my_config have been set, so we can
# overwrite. 
# The readonly ones not included in the conf
#
(
echo "PROJECTDIR=$PROJECTDIR" 
echo "PROJECT_ID=$PROJECT_ID"
echo "PROJECT_VERSION=$PROJECT_VERSION"
echo "TOOLDIR=$TOOLDIR" 
echo "OBJDIR=$OBJDIR"
echo "PROJECT=$PROJECT" 
echo "CONF=$CONF"
echo "PKGNAME=$PKGNAME"
echo "PKGDIR=$PKGDIR"
echo "PKG=$PKG"
) >$my_config

rkbuild_conf=$OBJDIR/.rkcomp/rkbuild.cf
rkinstall_conf=$OBJDIR/.rkcomp/install_data/rkinstall.cf
rkpkg_conf=$OBJDIR/.rkcomp/rkpkg.cf

# The same for rkpkg, rkbuild and rkinstall
#
cp $my_config $rkbuild_conf
cp $my_config $rkpkg_conf
cp $my_config $rkinstall_conf

# complete rkbuild.cf
#
(
echo "MAKE=$MAKE"
echo "LEXLIB=$LEXLIB"
echo "YACCLIB=$YACCLIB"
echo "LIB_A_TR='$LIB_A_TR'"
echo "LIB_DSH_TR='$LIB_DSH_TR'"
echo "OBJECT_FORMAT=$OBJECT_FORMAT"
echo "LDFLAGS_ELF_SONAME='$LDFLAGS_ELF_SONAME'"
echo "LDFLAGS_ELF_RPATH='$LDFLAGS_ELF_RPATH'"
echo "LDFLAGS_ELF_RPATH_LINK='$LDFLAGS_ELF_RPATH_LINK'"
) >>$rkbuild_conf

#----- rkinstall stuff
# rkinstall use the name of the PROJECT for the pre and post-install
# programs
#
echo PROJECTNAME=$(basename $PROJECT) >>$rkinstall_conf

# export some variables for {pre|post}-install programs
#
echo "export CONF PKGNAME PKGDIR PKG PROJECTNAME" >>$rkinstall_conf

# give a hint to rkinstall about LD_LIBRARY_PATH
#
if [ "x$LDFLAGS_ELF_RPATH" != "x" ]; then
	echo SET_RPATH=YES >>$rkinstall_conf
else
	echo SET_RPATH=NO >>$rkinstall_conf
fi

# rkinstall by itself
#
cp $TOOLDIR/bin/rkinstall $OBJDIR/.rkcomp

# copying the scripts provided
#
if [ -e $PROJECT.pre-install ]; then 
	cp $PROJECT.pre-install $OBJDIR/.rkcomp/install_bin/pre-install
fi
if [ -e $PROJECT.post-install ]; then 
	cp $PROJECT.post-install $OBJDIR/.rkcomp/install_bin/post-install
fi

# the commands library for the target
#
cp $TOOLDIR/libdata/$TARGET.cmds $OBJDIR/.rkcomp/install_bin/cmds

#------ TOOLS NEEDED
# this lib is used by pre/post-install scripts and rkinstall etc.
#
cp $TOOLDIR/lib/libsh $OBJDIR/.rkcomp/install_bin

tools=
for tool in cweb; do
	case $tool in
	  cweb) if [ "x$CTANGLE" = "x" -o "x$CWEAVE" = "x" ]; then
		  tools="$tools ctangle cweave"
		  CTANGLE=$OBJDIR/.rkcomp/bin/ctangle/ctangle
		  CWEAVE=$OBJDIR/.rkcomp/bin/cweave/cweave
		fi;;
	esac
done

# Complete rk.config incorporated in Makefiles
#
set | sed -n -f $tmpdir/sed | tr -d "'" | sort >>$my_config

if [ "x$tools" != "x" ]; then
	# some tools are missing
	mkdir -p $OBJDIR/.rkcomp/bin/.rkcomp
	sed -e s@##TOOLDIR##@$TOOLDIR@g \
	  -e s@##PROJECTDIR##@$TOOLDIR/src@g \
	  -e s@##OBJDIR##@$OBJDIR/.rkcomp/bin@g \
	  -e s@##PKG##@$PKG@g \
	  -e s@##MAKE##@$MAKE@g \
	  -e s@##SHELL##@$SHELL@g \
	  -e s@##NB_DIRS##@$(echo $tools | wc -w | tr -d '	 ')@g \
	$TOOLDIR/libdata/Makefile.objdir > $OBJDIR/.rkcomp/bin/Makefile
	ln -sf $rk_map $OBJDIR/.rkcomp/bin/.rkcomp/map
	ln -sf $rk_static $OBJDIR/.rkcomp/bin/.rkcomp/libes.static
	ln -sf $rk_dshared $OBJDIR/.rkcomp/bin/.rkcomp/libes.dshared
	sed -e 's!^PROJECTDIR=.*$!PROJECTDIR='$TOOLDIR/src'!' \
	  -e 's!^OBJDIR=.*$!OBJDIR='$OBJDIR/.rkcomp/bin'!' \
	  $rkbuild_conf >$OBJDIR/.rkcomp/bin/.rkcomp/rkbuild.cf
	echo "CC=$CC" > $OBJDIR/.rkcomp/bin/.rkcomp/config
	for tool in $tools; do
	  echo "$tool" >>$OBJDIR/.rkcomp/bin/.rkcomp/list
	  eval $(echo $tool | tr '[a-z]' '[A-Z]')=$OBJDIR/.rkcomp/bin/$tool/$tool
	done
	( cd $OBJDIR/.rkcomp/bin; $MAKE save_space 2>/dev/null; ) || error failed_to_build_tools;
	debug L "Tools correctly compiled!"
fi

#------ COPYING THE VARIABLE HEADERS

[ ! "$RK_ICONV_DEFS" ] \
	|| cp $TOOLDIR/libdata/include/$RK_ICONV_DEFS \
	  $OBJDIR/.rkcomp/include/iconv_defs.h

#------ CREATING THE MAKEFILE

sed -e s@##TOOLDIR##@$TOOLDIR@g \
	-e s@##PROJECTDIR##@$PROJECTDIR@g \
	-e s@##OBJDIR##@$OBJDIR@g \
	-e s@##PKG##@$PKG@g \
	-e s@##MAKE##@$MAKE@g \
	-e s@##SHELL##@$SHELL@g \
	-e s@##NB_DIRS##@$rk_nb_dirs@g \
	$TOOLDIR/libdata/Makefile.objdir > $OBJDIR/Makefile

debug L ""
debug L "=================== CONFIGURATION DONE ======================="
debug L ""

# echo OBJDIR to stdout allowing scripts to continue by `cd'ing etc.
#
echo $OBJDIR

#------------------POST PROCESSING

clean_tmp

exit 0
