#! /bin/sh
#
# This particular script is not generated. Rather, it reads package.in itself.
#
# This script does operations of the package (like installation/uninstallation)
# based on a description file. The description file has a simple sh-like
# format:
#
# #COMMENT
# SYMBOL [PARAMETER...]
#
# package NAME
# 	Gives the name of the package for distribution.
# version VERSION
# 	Gives the version of the package for distribution.
# distrib FILE...
# 	Adds files to the list of files for distribution.
# file SOURCE
# 	Declares a file in the package with the current set of properties.
# dir
# 	Declares a directory in the package with the current set of properties.
# set SYMBOL [PARAMETER...]
# 	Defines a certain property of all following `file' and `dir'
# 	definitions.
# set dir DIRECTORY
# 	Defines in which absolute location following files must be installed.
# set owner OWNER
# 	Defines owner of files when installed.
# set group GROUP
# 	Defines group of files when installed.
# set mode OCTAL
# 	Defines permission mode of file when installed.
# 

# Default values for options.
pkgdir=.
pkgdesc_def=Packfile
pkgdesc="$pkgdesc_def"

# Parse positional parameters.
while true; do case "$1" in

    (-d)
	pkgdir="$2"
	if test ! -d "$pkgdir"; then
		echo "Directory not found: $pkgdir"
		exit 1
	fi
	cd "$pkgdir"
	shift 2 ;;

    (-c)
	pkgdesc="$2"
	if test ! -f "$pkgdesc"; then
		echo "Package description file not found: $pkgdesc"
		exit 1
	fi
	shift 2 ;;

    (*) break ;;
esac; done

# Sanity.
if test ! -f "$pkgdesc"; then echo "$pkgdesc_def description file not found: $pkgdir/$pkgdesc"; exit 1; fi

# Determine in what way we will view the package description file.
if test -n "$1"; then action="$1"; shift; fi
if test -z "$action"; then echo "What do you want to do? {install|uninstall|update|dist}"; exit 1; fi
case "$action" in

    (install)
	# The description file is given by standard input to this function.
	pack_install_f()
	{ while read symbol params; do
		set "" $params; shift
		case "$symbol" in

		    (\#*) continue ;;

		    (file)

			# File name must be valid.
			if test ! -e "$1"; then
				echo "Invalid file name: $1" >/dev/stderr
				continue
			fi

			# Determine destination.
			if test -z "$fdir"
			then echo "Unfiled: $1"; continue;
			fi
			if test -n "$2"
			then filedest="$fdir/$2"
			else filedest="$fdir/`basename "$1"`"
			fi

			# Install the file.
			if test ! -d "$1"; then
				unset installopts
				test -n "$fowner" && \
					installopts="$install -o $fowner"
				test -n "$fgroup" && \
					installopts="$install -g $fgroup"
				test -n "$fmode" && \
					installopts="$install -m $fmode"
				if test -n "$2"
				then install -v $installopts "$1" "$filedest"
				else install -v $installopts "$1" "$fdir"
				fi
			else
				if test -e "$filedest" -a ! -d "$filedest"; then
					rm -vf "$filedest"
				fi
				if test ! -e "$filedest"; then
					mkdir -v $mkdiropts "$filedest"
				fi
				if test -n "$fowner" -o -n "$fgroup"; then
					chown -v "$fowner.$fgroup" "$filedest"
				fi
				if test -n "$fmode"; then
					chmod -v "$fmode" "$filedest"
				fi
				cp -afv "$1"/* "$filedest"
			fi
			;;

		    (dir)

			# Directory name must be given.
			if test -z "$1"; then
				echo "Directory name not given."; continue
			fi

			# Determine destination.
			if test -z "$fdir"; then
				echo "Unfiled dir: $1"; continue
			fi

			# Create the directory.
			unset mkdiropts
			test -n "$fmode" && mkdiropts="-m $fmode"
			mkdir $mkdiropts "$fdir/$1"
			;;

		    (set)
			case "$1" in

			    (dir)
				if test -n "$2"; then
					fdir="$2"

					# Destination directory must exist.
					if test ! -d "$fdir"; then
						echo "Invalid directory: $fdir"
						unset fdir
						continue
					fi
				else
					unset fdir
				fi
				;;

			    (own)
				test -n "$2" && fowner="$2" || unset fowner
				test -n "$3" && fgroup="$3" || unset fgroup ;;

			    (mod)
				test -n "$2" && fmode="$2" || unset fmode ;;
			esac
			;;

		    (cd)
			# Process the referenced file.
			if test ! -d "$1"; then
				echo "Not a subdirectory: $1"; continue
			fi
			case "$1" in (/*|*/*) echo "Not in this directory: $1"
			continue ;; esac
			cd "$1"
			pack_install_f <"$pkgdesc_def"
			cd ..
			;;
		esac
	done }

	# Process the requested file.
	pack_install_f <"$pkgdesc"
	;;

    (uninstall)

	# The description file is given by standard input to this function.
	pack_uninstall_f()
	{ tac | while read symbol params; do
		set "" $params; shift

		case "$symbol" in

		    (\#*) continue ;;

		    (file)
			if test -n "$2"
			then files="$files $2"
			else files="$files `basename "$1"`"
			fi
			;;

		    (dir)
			if test -z "$1"; then
				echo "Directory name not given."; continue
			fi
			dirs="$dirs $1"
			;;

		    (set)
			case "$1" in
			    (dir)
				fdir="$2"

				# Destination directory must exist.
				if test ! -d "$fdir"; then
					echo "Invalid directory: $fdir"
					unset fdir
					continue
				fi

				# Delete files/subdirectories in this directory.
				if test -n "$files"; then for file in $files; do
					rm -Rfv "$fdir/$file"
				done; unset files; fi

				# Delete directories in this directory.
				if test -n "$dirs"; then for dir in $dirs; do
					rmdir "$fdir/$dir"
				done; unset dirs; fi
				;;
			esac
			;;

		    (cd)
			# Process the referenced file.
			if test ! -d "$1"; then
				echo "Not a subdirectory: $1"; continue
			fi
			case "$1" in (/*|*/*) echo "Not in this directory: $1"
			continue ;; esac
			cd "$1"
			pack_install_f <"$pkgdesc_def"
			cd ..
			;;
		esac
	done }

	# Process the requested file.
	pack_uninstall_f <"$pkgdesc"
	;;

    (update)
	# The description file is given by standard input to this function.
	pack_update_f()
	{ while read symbol params; do
		set "" $params; shift

		case "$symbol" in

		    (\#*) continue ;;

		    (file)

			# Determine installed file name.
			if test -z "$fdir"; then echo "Unfiled: $1"; continue; fi
			if test -n "$2"
			then filedest="$fdir/$2"
			else filedest="$fdir/`basename "$1"`"
			fi
			if test ! -e "$filedest"; then
				echo "No installed file: $filedest" >/dev/stderr
				continue
			fi

			# Update the file.
			if test ! -d "$filedest"; then
				cp -vf "$filedest" "$1"
			else
				if test -d "$1"; then
					cp -afv "$filedest"/* "$1"
				else
					test -e "$1" && rm -f "$1"
					cp -Rafv "$filedest" "$1"
				fi
			fi
			;;

		    (set)
			case "$1" in

			    (dir)
				if test -n "$2"; then
					fdir="$2"

					# Installation directory must exist.
					if test ! -d "$fdir"; then
						echo "Invalid directory: $fdir"
						unset fdir; continue
					fi
				else
					unset fdir
				fi
				;;
			esac
			;;

		    (cd)
			# Process the referenced file.
			if test ! -d "$1"; then
				echo "Not a subdirectory: $1"; continue
			fi
			case "$1" in (/*|*/*) echo "Not in this directory: $1"
			continue ;; esac
			cd "$1"
			pack_install_f <"$pkgdesc_def"
			cd ..
			;;
		esac
	done }

	# Process the requested file.
	pack_update_f <"$pkgdesc"
	;;

    (dist)
	unset dist_type
	if test -n "$1"; then dist_type="$1"; shift; fi
	if test -z "$dist_type"; then echo "What kind of distribution do you want? {src|bin}"; exit 1; fi

	# The description file is given by standard input to this function.
	# The output is a list of file and directory names relative to the root source directory.
	pack_dist_f()
	{ while read symbol param1 param2; do
		case "$symbol" in

		    (\#*) continue ;;

		    (package)
			test -n "$package" && continue
			package="$param1"
			;;

		    (version)
			test -n "$version" && continue
			version="$param1"
			;;

		    (dist)
			test "$dist_type" != "$param1" && continue

			# Files for distribution.
			for file in $param2; do
				if test -n "$1"
				then thisfile="$1/$file"
				else thisfile="$file"
				fi
				echo "$thisfile"

				if test ! -e "$file"; then
					echo "Cannot find file: $thisfile"
					continue
				fi

				distfiles="$distfiles $thisfile"
			done
			;;

		    (cd)
			# It's always a little clumsy to do recursion in shell
			# scripts.  Nevertheless, this works.

			# Process the referenced file.
			if test ! -d "$param1"; then
				echo "Not a subdirectory: $param1"; continue
			fi
			case "$param1" in (/*|*/*) echo "Not in this directory: $param1"
				continue ;; esac
			cd "$param1"
			if test -n "$1"
			then pack_dist_f "$1/$param1" <"$pkgdesc_def"
			else pack_dist_f "$param1" <"$pkgdesc_def"
			fi
			cd ..
			;;
		esac
	done }

	# Create .tar.gz file.
	pack_dist_f <"$pkgdesc"
	if test -z "$package"; then
		echo "No package name specified."; exit 1
	fi

	filename="$package"
	if test -n "$version"
	then filename="$filename-$version"
	else filename="$filename-`date "+%Y_%m_%d"`"
	fi
	dirname="$filename"
	filename="$filename.tar.gz"

	mkdir "$dirname" || exit 1
	tar -c $distfiles | tar -C "$dirname" -x || exit 1
	tar -c "$dirname" | gzip --best >"$filename" || exit 1
	rm -r "$dirname"
	;;

    (*)
	echo "I don't know how to '$action' ."
	;;
esac
