#!/bin/bash
#
#  Filebundle generator
#  Copyright (C) 2009 Andreas Ă–man
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

set -u # Fail on undefined vars

READER="cat"
SOURCE=
DEPFILE=
OUTPUT=
PREFIX=
COMPRESS=false
usage()
{
cat << EOF
usage: $0 options

Generate a filebundle .c-file from a directory

OPTIONS:
   -h      Show this message
   -s      Source path
   -d      Dependency file (for use with make)
   -o      Output file (.c file)
   -z      Compress individual files using gzip
   -p      Filebundle prefix
EOF
}


while getopts "s:d:o:zhp:" OPTION
do
  case $OPTION in
      h)
	  usage
	  exit 1
	  ;;
      z)
	  READER="gzip -9"
	  COMPRESS=true
	  ;;
      d)
	  DEPFILE="$OPTARG"
	  ;;
      s)
	  SOURCE="$OPTARG"
	  ;;
      o)
	  OUTPUT="$OPTARG"
	  ;;
      p)
	  PREFIX="$OPTARG"
	  ;;
      esac
  done


if [[ -z $SOURCE ]] || [[ -z $OUTPUT ]] || [[ -z $PREFIX ]]; then
     usage
     exit 1
fi

FILES=`find "${SOURCE}" \( \( -name .svn -or -name *~ \) -and -prune \) -or -printf "%P "`

echo >${OUTPUT} "// auto-generated by $0"

for file in $FILES; do

    if [ -f ${SOURCE}/$file ]; then

	name=`echo $file | sed -e s#[/.-]#_#g`
	
	echo >>${OUTPUT} "// ${SOURCE}/$file"
	echo >>${OUTPUT} "static const unsigned char embedded_$name[]={"
	$READER <${SOURCE}/$file | od -v -An -b | sed s/^\ */0/ | sed s/\ *$$/,/| sed s/\ /,\ 0/g|sed s/$/,/ >>${OUTPUT}
	echo >>${OUTPUT} "};"
    fi
done

echo >>${OUTPUT} "#include <filebundle.h>"
echo >>${OUTPUT} "static const struct filebundle_entry filebundle_entries[] = {"
[[ -z $DEPFILE ]] || echo >${DEPFILE} -n "${OUTPUT}: "

for file in $FILES; do
    [[ -z $DEPFILE ]] || echo >>${DEPFILE} -n "${SOURCE}/$file "

    if [ -f ${SOURCE}/$file ]; then

	if $COMPRESS; then
	    ORIGINAL_SIZE=`stat -c "%s" ${SOURCE}/$file`
	else
	    ORIGINAL_SIZE="-1"
	fi

	N=`echo $file | sed -e s#[/.-]#_#g`
	echo >>${OUTPUT} "{\"$file\", embedded_$N, sizeof(embedded_$N),${ORIGINAL_SIZE}},"
    fi
done

echo >>${OUTPUT}  "{(void *)0, 0, 0, 0}};"
[[ -z $DEPFILE ]] || echo >>${DEPFILE} ""

cat >>${OUTPUT} <<EOF

static struct filebundle fb = {
  .entries = &filebundle_entries[0],
  .prefix = "${PREFIX}"
};

static void  __attribute__((constructor)) filebundle_init(void)
{
  extern struct filebundle *filebundles;

  fb.next = filebundles;
  filebundles = &fb;
}

EOF