#! /bin/sh
# $Id: makeheader,v 1.1 2008/05/05 16:53:07 Singular Exp $

#
# makeheader.sh - generate a header file out of several header files.
#
# Type 'makeheader -?' for instructions on syntax/usage.
#

# print usage if necessary
if test "$#" = 0 || test "$1" = "-?" || test "$1" = "-help"; then
    cat 1>&2 << \EOT
usage: makeheader [-?] {-I<includedir>} <templatefile> <outfile>

This is makeheader, a header file generation tool.
With makeheader it is possible to generate a single header
file out of several other header files.

To include a header file into the generated header file
(= <outfile>) use the two lines

/*MAKEHEADER*/
#include "<includefile>"

in <templatefile>.

If you use the alternate form

/*MAKEHEADER PUBLIC ONLY*/
#include "<includefile>"

only sections marked with /*BEGINPUBLIC*/ and /*ENDPUBLIC*/ are
pasted from <includefile> into <outfile>.

<includefile> is looked up in all <includedir>s, then in the
current directory, then in the base directory of <templatefile>.
EOT
    exit 1
fi

# get list of include directories
includes=""
while echo "$1" | grep '^-I' > /dev/null 2> /dev/null; do
    # get argument to option -I
    if test "$1" = "-I"; then
        shift
        includes="$includes$1:"
    else
        include=`echo "$1" | sed 's/^-I//'`
        includes="$includes$include:"
    fi
    shift
done
includes="$includes.:"

# check for rest of arguments
if test "$#" -lt 2; then
    echo "usage: makeheader [-?] {-I<includedir>} <templatefile> <outfile>" 1>&2
    exit 1
fi

infile="$1"
outfile="$2"

# get basename of $infile
if echo "$infile" | grep '.*/' > /dev/null 2> /dev/null; then
    include=`echo "$infile" | sed 's/\/[^\/]*$//'`
    includes="$includes$include:"
fi

if test ! -r "$infile"; then
    echo "makeheader: Cannot open template file $infile for reading" 1>&2
    exit 1
fi

# try to create $outfile if it does not exist
if test -w "$outfile" || cp /dev/null "$outfile" > /dev/null 2> /dev/null; then
    :
else
    echo "makeheader: Cannot open header file $outfile for writing" 1>&2
    exit 1
fi

echo "/* $outfile automatically generated by makeheader from $infile */" > "$outfile"

# scan through template
while read line; do
    if test "$line" = '/*MAKEHEADER*/'; then
	readmode=1
    elif test "$line" = '/*MAKEHEADER PUBLIC ONLY*/'; then
	readmode=2
    else
	echo "$line"
	continue
    fi

    # get include file from next line
    read line
    if echo "$line" | grep -v '^#include ".*"$' > /dev/null 2> /dev/null; then
    	echo "makeheader: Invalid include statement $line" 1>&2
	exit 1
    fi
    includefile=`echo "$line" | sed 's/^#include "//; s/"$//'`

    # search for includefile
    found=0
    saveIFS="$IFS"; IFS=:
    for dir in $includes; do
	if test -r "$dir/$includefile"; then
	    found=1
	    break
	fi
    done
    IFS="$saveIFS"

    if test $found = 0; then
	echo "makeheader: Include file $includefile not found" 1>&2
	exit 1
    else
	includefile="$dir/$includefile"
    fi

    # now paste includefile into outfile
    echo "/* stuff included from $includefile */"
    echo
    if test $readmode = 1; then
	# read whole includefile
	cat "$includefile"
    elif test $readmode = 2; then
	# read only public sections of includefile
	sed -n '
	  \@^/\*BEGINPUBLIC\*/$@!d
	  \@^/\*BEGINPUBLIC\*/$@{
	    : loop
	    n
	    \@^/\*ENDPUBLIC\*/$@d
	    p
	    b loop
	  }' "$includefile"
    fi

done < "$infile" >> "$outfile"
