#!/bin/sh

# click-compile.in -- script compiles Click elements
# Eddie Kohler
#
# Copyright (c) 1999 Massachusetts Institute of Technology
# Copyright (c) 2001 International Computer Science Institute
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, subject to the conditions
# listed in the Click LICENSE file. These conditions include: you must
# preserve this copyright notice, and you cannot mention the copyright
# holders in advertising related to the Software without their permission.
# The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
# notice is a summary of the Click LICENSE file; the license in that file is
# legally binding.

prefix=/usr/local
exec_prefix=${prefix}
includedir=${prefix}/include
srcdir=/usr/local/share/click/src
linuxdir=NONE
freebsd_includedir=/usr/include

# determine mode
directory=.
target=
package=NONE
cflags=
compileflag=-c
quiet=
while true; do
  bad=x
  case $1 in
    --de|--def|--defs)
      echo -I/usr/include/pcap -I$includedir
      exit 0;;
    --l|--li|--lib|--libs)
      echo -lpcap -ldl 
      exit 0;;
    -d|--di|--dir|--dire|--direc|--direct|--directo|--director|--directory)
      directory=$2; shift 2;;
    --di=*|--dir=*|--dire=*|--direc=*|--direct=*|--directo=*|--director=*|--directory=*)
      directory=`echo "$1" | sed 's/^[^=]*=//'`; shift 1;;
    -t|--t|--ta|--tar|--targ|--targe|--target)
      target=$2; shift 2;;
    --t=*|--ta=*|--tar=*|--targ=*|--targe=*|--target=*)
      target=`echo "$1" | sed 's/[-a-z]*=//'`; shift 1;;
    -p|--p|--pa|--pac|--pack|--packa|--packag|--package)
      package=$2; shift 2;;
    --p=*|--pa=*|--pac=*|--pack=*|--packa=*|--packag=*|--package=*)
      package=`echo "$1" | sed 's/[-a-z]*=//'`; shift 1;;
    -q|--q|--qu|--qui|--quie|--quiet)
      quiet=y; shift 1;;
    -h|--h|--he|--hel|--help)
      cat <<'EOF' 1>&2
`Click-compile' compiles a Click source file, or outputs any compiler options
relevant for userlevel Click drivers.

Usage: click-compile -t TARGET [OPTIONS] SOURCEFILE...

Options:
      --defs              Outputs preprocessor options for userlevel drivers.
      --libs              Outputs link options for userlevel drivers.
  -t, --target TARGET     Sets target to `bsdmodule', `linuxmodule',
                          `userlevel', or `tool'.
  -p, --package PACKAGE   Build a dynamically loadable package named PACKAGE.
  -d, --directory DIR     Change to directory DIR.
  -q, --quiet             Be quiet (don't echo commands or print warnings).
  -h, --help              Print this message and exit.
  Other options are passed to the compiler unchanged.

Report bugs to <click@pdos.lcs.mit.edu>.
EOF
      exit 0;;
    -*)
      if test $1 = -E -o $1 = -c -o $1 = -S; then
        compileflag=$1
      else cflags="$cflags '$1'"; fi
      shift 1;;
    *)
      bad=;;
  esac
  if test -z "$bad"; then break; fi
done

cd $directory

# test directory function
test_dir () {
  test -d "$1" -a -d "$1/elements" -a -d "$1/lib"
}

# analyze CLICKPATH to find sources
path=${CLICKPATH-:}
tried_defaults=
include_source=
while true; do
  case $path in
    :*)
      if test -z "$tried_defaults" && test_dir "$srcdir"; then
        include_source="-I$srcdir"
      else
        tried_defaults=y
      fi
      path=`echo "$path" | sed 's/://'`
      ;;
    *:*)
      dir=`echo "$path" | sed 's/:.*//'`
      if test_dir "$dir"; then include_source="-I$dir"; fi
      path=`echo "$path" | sed 's/[^:]*://'`
      ;;
    *:)
      dir=`echo "$path" | sed 's/:.*//'`
      if test_dir "$dir"; then include_source="-I$dir"; fi
      path=":"
      ;;
    *)
      if test_dir "$path"; then include_source="-I$path"; fi
      path=""
      ;;
  esac
  if test -z "$path" -o -n "$include_source"; then break; fi
done

if test ! -d "$includedir"; then
  echo "click-compile: Cannot find Click include directory!" 1>&2
  echo "  (Have you installed Click yet?)" 1>&2
  exit 1
elif test -z "$include_source"; then
  if test -z "$quiet"; then
    echo "click-compile: warning: cannot find full Click source" 1>&2
  fi
fi


case $target in
  k|ke|ker|kern|kerne|kernel|l|li|lin|linu|linux|linuxm|linuxmo|linuxmod|linuxmodu|linuxmodul|linuxmodule)
    idefs="-DHAVE_CONFIG_H -DCLICK_LINUXMODULE"
    iincludes="${include_source} -I${includedir} -I${linuxdir}/include"
    icxxflags=" -O2"
    icflags=" -O2"
    command="${CXX-g++ -w -Wall -fno-exceptions -fno-rtti -fvtable-thunks} ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-} ${CXXFLAGS-$icxxflags} $cflags $compileflag"
    c_command="${CC-gcc -Wall} ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-} ${CFLAGS-$icflags} $cflags $compileflag"
    target=linuxmodule;;
  u|us|use|user|userl|userle|userlev|userleve|userlevel)
    idefs="-DHAVE_CONFIG_H -DCLICK_USERLEVEL"
    iincludes="${include_source} -I${includedir}"
    icxxflags="-g -O2"
    command="${CXX-g++ -Wp,-w -W -Wall -fno-exceptions -fno-rtti -fvtable-thunks} ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-} ${CXXFLAGS-$icxxflags} $cflags $compileflag"
    target=userlevel;;
  b|bs|bsd|bsdm|bsdmo|bsdmod|bsdmodu|bsdmodul|bsdmodule)
    idefs="-DHAVE_CONFIG_H -DCLICK_BSDMODULE"
    iincludes="${include_source} -I${includedir}"
    icxxflags=" -O2"
    command="${CXX-g++ -w -Wall -fno-exceptions -fno-rtti -fvtable-thunks} ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-} ${CXXFLAGS-$icxxflags} $cflags $compileflag"
    target=bsdmodule;;
  t|to|too|tool)
    idefs="-DHAVE_CONFIG_H -DCLICK_TOOL"
    iincludes="${include_source} -I${includedir}"
    icxxflags="-g -O2"
    command="${CXX-g++ -Wp,-w -W -Wall -fno-exceptions -fno-rtti -fvtable-thunks} ${DEFS-$idefs} ${INCLUDES-$iincludes} ${CPPFLAGS-} ${CXXFLAGS-$icxxflags} $cflags $compileflag"
    target=tool;;
  "")
    echo "click-compile: you must specify a target" 1>&2; exit 1;;
  *)
    echo "click-compile: acceptable targets are \`linuxmodule', \`userlevel', and \`tool'" 1>&2; exit 1;;
esac

exec_command () {
  if test -z "$quiet"; then
    echo "$@" 1>&2
  fi
  eval "$@" || exit 1
}

compile_file () {
  option=
  if test -r "$1"; then
    option=`head -5 $1 | grep '^/\*\* click-compile:' | sed -e 's/\/\*\* click-compile://g' -e 's/\*\///g'`
  fi
  exec_command $command $option $1
}

# do stuff
if test "x$package" != "xNONE"; then
  command="$command -DCLICK_PACKAGE"
  for file; do
    compile_file $file
    files="$files "`echo $file | sed 's/\.c*$/\.o/;s/^.*\///'`
  done
  if test $target = linuxmodule; then
    vfile=kernelversion
    test -f $vfile.c && echo "click-compile: A file \`$vfile.c' already exists in this directory!" 1>&2 && echo "click-compile: You must remove it, or run me somewhere else." 1>&2 && exit 1
    trap 'rm -f $vfile.c $vfile.o' 0
    trap 'rm -f $vfile.c $vfile.o; exit 1' 1 2 15
    cat > $vfile.c << EOF
#include <click/config.h>
#include <linux/module.h>
/* a new version of EXPORT_NO_SYMBOLS that works */
const int __ksymtab_nothing[0] __attribute__((section("__ksymtab"))) = { };
EOF
    exec_command $c_command $vfile.c
    exec_command "ld -r -o $package $files $vfile.o"
    exit 0 
  elif test $target = userlevel -o $target = tool; then
    exec_command "ld -shared -o $package $files"
    exit 0
  elif test $target = bsdmodule; then
    exec_command "ld -Bshareable -o $package $files"
    exit 0
  fi
else
  exec_command "$command $@"
  exit 0
fi
