################################################################################
#
# src_install.cygpart - cygport source installation functions
#
# Copyright (C) 2006-2016 Yaakov Selkowitz
# Provided by the Cygwin Ports project <http://sourceware.org/cygwinports/>
#
# cygport 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.
#
# cygport 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 cygport.  If not, see <http://www.gnu.org/licenses/>.
#
################################################################################

#****** Chapter 10/Installing
#  NOTE
#  In the context of cygport, "installing" always means into the DESTDIR $D.
#  However, the syntax of the convenience functions is as if one were
#  installing to the system.
#****

#****I* Installing/dodir
#  SYNOPSIS
#  dodir DIRECTORY [DIRECTORY] ...
#  DESCRIPTION
#  Creates the given directories under $D.
#****
dodir() {
	local d;

	for d
	do
		if [ ! -d ${D}${d} ]
		then
			mkdir -p ${D}${d} || error "dodir ${d} failed"
		fi
	done
}

#****I* Installing/keepdir
#  SYNOPSIS
#  keepdir DIRECTORY [DIRECTORY] ...
#  DESCRIPTION
#  Preserves the given empty directories under $D from being removed during
#  automatic postinstall steps.
#  SEE ALSO
#  KEEPDIRS
#****
keepdir() {
	for d
	do
		dodir ${d}
		touch ${D}${d}/.keep-${NAME}-${VERSION}-${RELEASE}
	done
}

__doinstall() {
	local mode=${1}
	local file=${2}
	local targetdir=${3}
	local targetfile=${4:-${2##*/}}
	local ltinst

	if [ ! -e "${file}" ]
	then
		error "file ${file} does not exist"
		return 2
	fi

	if [ ! -d ${D}${targetdir} ]
	then
		error "Directory ${targetdir} does not exist"
		return 2
	fi

	ltinst=
	case ${file} in
		*.la)  ltinst="/usr/bin/libtool --mode=install" ;;
		*)     [ -f "${file%/*}/.libs/${file##*/}" ] && ltinst="/usr/bin/libtool --mode=install" ;;
	esac

	verbose ${ltinst} /usr/bin/install -m${mode} "${file}" "${D}${targetdir}/${targetfile}"
	return $?
}

__fix_shebang() {
	local x
	local interp=${1}
	shift

	for x
	do
		if [ $(head -c 2 ${x}) != "#!" ]
		then
			continue
		fi

		sed -i -e "s|#! */[^ ]*\(.*\)|#! ${interp}\1|" ${x}
	done
}


#****I* Installing/dobin
#  SYNOPSIS
#  dobin FILE [FILE] ...
#  DESCRIPTION
#  Installs the given file(s) to the standard bindir and makes them executable.
#****
dobin() {
	local _bindir=$(__host_prefix)/bin

	dodir ${_bindir}
	for i
	do
		__doinstall 0755 ${i} ${_bindir} || error "dobin ${i} failed"
	done
}

#****I* Installing/newbin
#  SYNOPSIS
#  newbin FILE NEW_NAME
#  DESCRIPTION
#  Installs the given file to the standard bindir with the given new name, and makes
#  it executable.
#****
newbin() {
	local _bindir=$(__host_prefix)/bin

	dodir ${_bindir}
	__doinstall 0755 ${1} ${_bindir} ${2} || error "newbin ${1} failed"
}


#****I* Installing/docinto
#  SYNOPSIS
#  docinto [/]SUBDIRECTORY
#  DESCRIPTION
#  Sets the subdirectory into which dodoc and newdoc should install.
#  If the subdirectory is prefixed by a slash, then dodoc and newdoc will use
#  /usr/share/doc/SUBDIRECTORY/; if not, they will use /usr/share/doc/PN/SUBDIRECTORY/.
#****
docinto() {
	if (( $# != 1 ))
	then
		error "docinto accepts exactly one argument";
	fi

	_docinto_dir=${1};
}

#****I* Installing/dodoc
#  SYNOPSIS
#  dodoc FILE [FILE] ...
#  DESCRIPTION
#  Installs the given files or directories into $D/usr/share/doc/PN/, or a
#  subdirectory thereof specified by the previous call to docinto.
#****
dodoc() {
	local docdir d f i

	case "${_docinto_dir}" in
		'')	docdir=/usr/share/doc/${PN} ;;
		/*)	docdir=/usr/share/doc${_docinto_dir} ;;
		*)	docdir=/usr/share/doc/${PN}/${_docinto_dir} ;;
	esac

	dodir ${docdir}

	for i
	do
		if [ -d "${i}" ]
		then
			d=${i%/}
			pushd ${d}/..
			dodir $(find ${d##*/} -type d -exec printf ${docdir}/'{}'" " \;)
			for f in $(find ${d##*/} ! -type d)
			do
				__doinstall 0644 "${f}" ${docdir}/${f%/*} || error "dodoc -r ${d} failed"
			done
			popd
		elif [ -f "${i}" -o -L "${i}" ]
		then
			if [ -s "${i}" -a ! -f "${D}${docdir}/${i}" ]
			then
				__doinstall 0644 "${i}" ${docdir} || error "dodoc ${i} failed"
			fi
		elif [ -f "${i}.md" -o -L "${i}.md" ]
		then
			if [ -s "${i}.md" -a ! -f "${D}${docdir}/${i}.md" ]
			then
				__doinstall 0644 "${i}.md" ${docdir} || error "dodoc ${i}.md failed"
			fi
		elif [ -f "${i}.txt" -o -L "${i}.txt" ]
		then
			if [ -s "${i}.txt" -a ! -f "${D}${docdir}/${i}.txt" ]
			then
				__doinstall 0644 "${i}.txt" ${docdir} || error "dodoc ${i}.txt failed"
			fi
		fi
	done
}

#****I* Installing/newdoc
#  SYNOPSIS
#  newdoc FILE NEW_NAME
#  DESCRIPTION
#  Installs the given file into $D/usr/share/doc/PN/, or a subdirectory thereof
#  specified by the previous call to docinto, with the given new name.
#****
newdoc() {
	case "${_docinto_dir}" in
		'')	docdir=/usr/share/doc/${PN} ;;
		/*)	docdir=/usr/share/doc${_docinto_dir} ;;
		*)	docdir=/usr/share/doc/${PN}/${_docinto_dir} ;;
	esac

	dodir ${docdir}
	__doinstall 0644 ${1} ${docdir} ${2} || error "newdoc ${1} failed"
}


#****I* Installing/exeinto
#  SYNOPSIS
#  exeinto DIRECTORY
#  DESCRIPTION
#  Specifies the directory under $D into which doexe and newexe will install.
#****
exeinto() {
	if (( $# != 1 ))
	then
		error "exeinto accepts exactly one argument";
	fi

	dodir ${1};
	_exeinto_dir=${1};
}

#****I* Installing/doexe
#  SYNOPSIS
#  doexe FILE [FILE] ...
#  DESCRIPTION
#  Installs the given file(s) into the directory under $D specified by the
#  preceding call to exeinto and makes them executable.
#****
doexe() {
	if ! defined _exeinto_dir || [ ! -d ${D}${_exeinto_dir} ]
	then
		error "exeinto must be called before doexe"
	fi

	for i
	do
		__doinstall 0755 ${i} ${_exeinto_dir} || error "doexe ${i} failed"
	done
}

#****I* Installing/newexe
#  SYNOPSIS
#  newexe FILE NEW_NAME
#  DESCRIPTION
#  Installs the given file into the directory under $D specified by the
#  preceding call to exeinto, renaming it as indicated, and makes it executable.
#****
newexe() {
	if ! defined _exeinto_dir || [ ! -d ${D}${_exeinto_dir} ]
	then
		error "exeinto must be called before doexe"
	fi

	__doinstall 0755 ${1} ${_exeinto_dir} ${2} || error "newexe ${1} failed"
}


#****I* Installing/insinto
#  SYNOPSIS
#  insinto DIRECTORY
#  DESCRIPTION
#  Specifies the directory under $D into which doins and newins will install.
#****
insinto() {
	if (( $# != 1 ))
	then
		error "insinto accepts exactly one argument";
	fi

	dodir ${1};
	_insinto_dir=${1};
}

#****I* Installing/doins
#  SYNOPSIS
#  doins FILE [FILE] ...
#  DESCRIPTION
#  Installs the given file(s) into the directory under $D specified by the
#  preceding call to insinto.  Files are made not executable.
#****
doins() {
	if ! defined _insinto_dir || [ ! -d ${D}${_insinto_dir} ]
	then
		error "insinto must be called before doins"
	fi

	for i
	do
		__doinstall 0644 ${i} ${_insinto_dir} || error "doins ${i} failed"
	done
}

#****I* Installing/newins
#  SYNOPSIS
#  newins FILE NEW_NAME
#  DESCRIPTION
#  Installs the given file into the directory under $D specified by the
#  preceding call to insinto, renaming it as indicated.  Files are made not
#  executable.
#****
newins() {
	if ! defined _insinto_dir || [ ! -d ${D}${_insinto_dir} ]
	then
		error "insinto must be called before doins"
	fi

	__doinstall 0644 ${1} ${_insinto_dir} ${2} || error "newins ${1} failed"
}


#****I* Installing/doicon
#  SYNOPSIS
#  doicon FILE [FILE] ...
#  DESCRIPTION
#  Installs the given image file(s) into the legacy icon directory.
#  NOTES
#  * Supported icon formats are PNG, XPM, and SVG.
#  * This location is intended for packages shipping a single icon.  If the
#    same PNG icon is available in different sizes, with or without a
#    corresponding SVG, then these icons should be installed into
#    the Hicolor Icon Theme hierarchy.
#****
doicon() {
	local _icondir=$(__host_prefix)/share/pixmaps

	dodir ${_icondir}
	for i
	do
		__doinstall 0644 ${i} ${_icondir} || error "doicon ${i} failed"
	done
}

#****I* Installing/newicon
#  SYNOPSIS
#  newicon FILE NEW_NAME
#  DESCRIPTION
#  Installs the given image file into the legacy icon directory,
#  renaming it as indicated.
#  NOTE
#  Supported icon formats are PNG, XPM, and SVG.
#****
newicon() {
	local _icondir=$(__host_prefix)/share/pixmaps

	dodir ${_icondir}
	__doinstall 0644 ${1} ${_icondir} ${2} || error "newicon ${1} failed"
}

#****I* Installing/includeinto
#  SYNOPSIS
#  includeinto SUBDIRECTORY
#  DESCRIPTION
#  Sets the subdirectory of the standard includedir into which doinclude should install.
#****
includeinto() {
	if (( $# != 1 ))
	then
		error "includeinto accepts exactly one argument";
	fi

	case ${1} in
		/*)	error "includeinto: argument must be a subdirectory" ;;
	esac

	_includeinto_dir=${1};
}

#****I* Installing/doinclude
#  SYNOPSIS
#  doinclude HEADER [HEADER] ...
#  DESCRIPTION
#  Installs the given headers into the standard includedir, or the subdirectory thereof
#  specified by a previous call to includeinto.
#****
doinclude() {
	local _includedir=$(__host_prefix)/include/${_includeinto_dir}

	dodir ${_includedir}
	for i
	do
		__doinstall 0644 ${i} ${_includedir} || error "doinclude ${i} failed"
	done
}

#****I* Installing/dolib
#  SYNOPSIS
#  dolib LIBRARY [LIBRARY] ...
#  DESCRIPTION
#  Installs the given libtool, static, or import libraries into the standard libdir.
#  NOTES
#  * Library DLLs must be installed with dobin.
#  * Cross-compiled ELF Shared Objects must be installed with doelflib.
#****
dolib() {
	local _libdir=$(__host_prefix)/${MULTILIB_LIBDIR-lib}

	dodir ${_libdir}
	for i
	do
		case ${i} in
			*.la) __doinstall 0755 ${i} ${_libdir} || error "dolib ${i} failed" ;;
			*)    __doinstall 0644 ${i} ${_libdir} || error "dolib ${i} failed" ;;
		esac
	done
}

#****I* Installing/newlib
#  SYNOPSIS
#  newlib LIBRARY NEW_NAME
#  DESCRIPTION
#  Installs the given static or import library into the standard libdir, renaming
#  it as indicated.
#  NOTES
#  * Library DLLs must be installed with dobin.
#  * Libtool libraries must be installed with dolib.
#****
newlib() {
	local _libdir=$(__host_prefix)/${MULTILIB_LIBDIR-lib}

	dodir ${_libdir}
	case ${i} in
		*.la)  error "newlib ${1}: libtool libraries cannot be renamed" ;;
		*)     __doinstall 0644 ${1} ${_libdir} ${2} || error "newlib ${1} failed" ;;
	esac
}

#****I* Installing/doinfo
#  SYNOPSIS
#  doinfo FILE [FILE] ...
#  DESCRIPTION
#  Installs the given Info documentation file(s) into the standard infodir.
#****
doinfo() {
	local _infodir=$(__host_prefix)/share/info

	dodir ${_infodir}
	for i
	do
		__doinstall 0644 ${i} ${_infodir} || error "doinfo ${i} failed"
	done
}

#****I* Installing/doman
#  SYNOPSIS
#  doman [[-l |--lang=]LANGUAGE] MANPAGE [MANPAGE] ...
#  DESCRIPTION
#  Installs the given manpage(s) into the appropriate subdirectory of
#  the standard mandir.  Localized manpages can be installed by specifing
#  the --lang (-l) argument, otherwise manpages are assumed to be in English.
#****
doman() {
	local manroot=$(__host_prefix)/share/man
	local mandir=${manroot}

	for i
	do
		if defined _doman_next_arg_is_lang
		then
			case ${i} in
				C)	mandir=${manroot} ;;
				*)	mandir="${mandir}/${i}" ;;
			esac
			unset _doman_next_arg_is_lang
			continue
		fi

		case ${i} in
			--lang=*)
				case ${i#*=} in
					C)	mandir=${manroot} ;;
					*)	mandir="${mandir}/${i#*=}" ;;
				esac
				continue
			;;
			-l)
				_doman_next_arg_is_lang=1
				continue
			;;			
			*.1|*.1m|*.1x|*.1.bz2|*.1.gz)  mansection=1 ;;
			*.3|*.3pm|*.3t|*.3.gz)  mansection=3 ;;
			*.4|*.4.gz)  mansection=4 ;;
			*.5|*.5.gz)  mansection=5 ;;
			*.6|*.6x|*.6.gz)  mansection=6 ;;
			*.7|*.7.gz)  mansection=7 ;;
			*.8|*.8.gz)  mansection=8 ;;
			*.l|*.l.gz)  mansection=l ;;
			*.n|*.n.gz)  mansection=n ;;
			*)  error "unknown man section" ;;
		esac

		dodir ${mandir}/man${mansection}
		__doinstall 0644 ${i} ${mandir}/man${mansection} || error "doman ${i} failed"
	done
}

#****I* Installing/newman
#  SYNOPSIS
#  newman [[-l |--lang=]LANGUAGE] MANPAGE NEW_NAME
#  DESCRIPTION
#  Installs the given manpage into the appropriate subdirectory of
#  the standard mandir with the given new name.  Localized manpages can be
#  installed by specifing the --lang (-l) argument, otherwise manpages are
#  assumed to be in English.
#****
newman() {
	local manroot=$(__host_prefix)/share/man
	local mandir=${manroot}

	case ${1} in
		--lang=*)
			case ${1#*=} in
				C)	mandir=${manroot} ;;
				*)	mandir="${mandir}/${1#*=}" ;;
			esac
			shift
		;;
		-l)
			case ${2} in
				C)	mandir=${manroot} ;;
				*)	mandir="${mandir}/${2}" ;;
			esac
			shift 2
		;;
	esac

	case ${2} in
		*.1|*.1m|*.1x|*.1.bz2|*.1.gz)  mansection=1 ;;
		*.3|*.3pm|*.3t|*.3.gz)  mansection=3 ;;
		*.4|*.4.gz)  mansection=4 ;;
		*.5|*.5.gz)  mansection=5 ;;
		*.6|*.6x|*.6.gz)  mansection=6 ;;
		*.7|*.7.gz)  mansection=7 ;;
		*.8|*.8.gz)  mansection=8 ;;
		*.l|*.l.gz)  mansection=l ;;
		*.n|*.n.gz)  mansection=n ;;
		*)  error "unknown man section" ;;
	esac

	dodir ${mandir}/man${mansection}
	__doinstall 0644 ${1} ${mandir}/man${mansection} ${2} || error "doman ${1} failed"
}

#****I* Installing/domenu
#  SYNOPSIS
#  domenu DESKTOP_MENU [DESKTOP_MENU] ...
#  DESCRIPTION
#  Installs the given desktop menu entries (.desktop).
#****
domenu() {
	local _menudir=$(__host_prefix)/share/applications

	dodir ${_menudir}
	for i
	do
		__doinstall 0644 ${i} ${_menudir} || error "domenu ${i} failed"
	done
}

#****I* Installing/newmenu
#  SYNOPSIS
#  newmenu DESKTOP_MENU NEW_NAME
#  DESCRIPTION
#  Installs the given desktop menu entry (.desktop) with the given new name.
#****
newmenu() {
	local _menudir=$(__host_prefix)/share/applications

	dodir ${_menudir}
	__doinstall 0644 ${1} ${_menudir} ${2} || error "newmenu ${1} failed"
}

#****I* Installing/dopkgconfig
#  SYNOPSIS
#  dopkgconfig PC_FILE [PC_FILE] ...
#  DESCRIPTION
#  Installs the given pkg-config metadata files.
#****
dopkgconfig() {
	local _pcdir=$(__host_prefix)/${MULTILIB_LIBDIR-lib}/pkgconfig

	dodir ${_pcdir}
	for i
	do
		__doinstall 0644 ${i} ${_pcdir} || error "dopkgconfig ${i} failed"
	done
}

#****I* Installing/dosbin
#  SYNOPSIS
#  dosbin FILE [FILE] ...
#  DESCRIPTION
#  Installs the given file(s) to the standard sbindir and makes them executable.
#****
dosbin() {
	local _sbindir=$(__host_prefix)/sbin

	dodir ${_sbindir}
	for i
	do
		__doinstall 0755 ${i} ${_sbindir} || error "dosbin ${i} failed"
	done
}

#****I* Installing/newsbin
#  SYNOPSIS
#  newsbin FILE NEW_NAME
#  DESCRIPTION
#  Installs the given file to the standard sbindir with the given new name, and makes
#  it executable.
#****
newsbin() {
	local _sbindir=$(__host_prefix)/sbin

	dodir ${_sbindir}
	__doinstall 0755 ${1} ${_sbindir} ${2} || error "newsbin ${1} failed"
}


#****I* Installing/dosym
#  SYNOPSIS
#  dosym TARGET [TARGET] ... DESTINATION
#  DESCRIPTION
#  Creates symlinks from the given target(s) to the given destination.  The
#  destination must be a directory if more than one target is given.  Both
#  relative and absolute targets are supported; relative targets must be given
#  in relation to the destination.
#  NOTE
#  The destination directory must exist under $D before dosym is called,
#  therefore a preceding call to dodir may be necessary.
#****
dosym() {
	local _argv=("dosym" ${@})
	local _argc=$#
	local ln_s

	if ((_argc < 2))
	then
		error "dosym: requires at least two arguments"
	fi

	dest="${_argv[${_argc}]}"

	# cd should allow for relative symlinks
	# e.g. dosym ../share/foo /usr/lib/
	if [ -d ${D}${dest} ]
	then
		pushd ${D}${dest}
	elif [ -d ${D}${dest%/*} ]
	then
		pushd ${D}${dest%/*}
	else
		error "dosym: ${dest%/*} is not a directory"
	fi

	ln -sf ${_argv[*]:1:$((_argc - 1))} ${D}${dest} || error "dosym failed"

	popd
}

#****I* Installing/dotool
#  SYNOPSIS
#  dotool FILE [FILE] ...
#  DESCRIPTION
#  Installs the given compiler tool(s) into the target-specific bindir
#  and a target-prefixed version into the native bindir.
#****
dotool() {
	local _bindir=/usr/bin
	local _tooldir=/usr/${CTARGET}/bin

	dodir ${_bindir} ${_tooldir}
	for i
	do
		__doinstall 0755 ${i} ${_tooldir} || error "dotool ${i} failed"
		__doinstall 0755 ${i} ${_bindir} ${CTARGET}-${i##*/} || error "dotool ${i} failed"
	done
}

#****I* Installing/doenv
#  SYNOPSIS
#  doenv VARIABLE VALUE
#  DESCRIPTION
#  Creates profile.d scripts which set the given environment variable.
#  NOTE
#  If VALUE includes a reference to a variable which is meant to be expanded
#  at runtime, then be sure to escape the leading dollar-sign and, for
#  portability, do not use braces; for example:
#    doenv PATH \$PATH:/foo/bar
#****
doenv() {
	local var=${1}
	shift

	dodir /etc/profile.d
	echo "export ${var}=\"${*}\"" >> ${D}/etc/profile.d/${PN}.sh
	cat >> ${D}/etc/profile.d/${PN}.csh <<-_EOF
		if ( ! \$?${var} ) setenv ${var} ""
		setenv ${var} "${*}"
	_EOF
	echo "set -x ${var} \"${*}\"" >> ${D}/etc/profile.d/${PN}.fish
}

#****I* Installing/make_autostart_entry
#  SYNOPSIS
#  make_autostart_entry COMMAND NAME [ADDITIONAL_FIELDS]
#  DESCRIPTION
#  Creates an autostart entry for desktop applications as follows:
#  * COMMAND: the command line.  May contain arguments, in which case the
#    entire command must be quoted.
#  * NAME: the application name to be shown in autostart configuration menus.
#  * ADDITIONAL_FIELDS: (optional) additional menu entry fields per
#    |html the <a href="http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#recognized-keys">Desktop Entry Specification</a>
#    |html and the <a href="http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html">Desktop Application Autostart Specification</a>.
#****
make_autostart_entry() {
	local dtfile

	if (( $# < 2 ))
	then
		error "make_autostart_entry requires a minimum of two arguments"
	fi

	dodir /etc/xdg/autostart
	dtfile=/etc/xdg/autostart/$(basename ${1%% *}).desktop

	cat > ${D}${dtfile} <<-_EOF
		[Desktop Entry]
		Type=Application
		Name=${2}
		Exec=${1}
	_EOF

	for ((n=3; n <= $#; n++))
	do
		echo ${!n} >> ${D}${dtfile}
	done
}

#****I* Installing/make_desktop_entry
#  SYNOPSIS
#  make_desktop_entry COMMAND NAME [ICON] [CATEGORIES] [COMMENT] [ADDITIONAL_FIELDS]
#  DESCRIPTION
#  Creates a desktop menu entry for GUI applications as follows:
#  * COMMAND: the command line.  May contain arguments, in which case the
#    entire command must be quoted.
#  * NAME: the application name to be shown in the menu.
#  * ICON: (optional) the icon name, excluding the file extension.
#  * CATEGORIES: (optional) a semicolon-separated list of categories and subcategories per
#    |html the <a href="http://standards.freedesktop.org/menu-spec/latest/apa.html">Desktop Menu Specification</a>.
#  * COMMENT: (optional) description of the program
#  * ADDITIONAL_FIELDS: (optional) additional menu entry fields per
#    |html the <a href="http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#recognized-keys">Desktop Entry Specification</a>.
#  NOTES
#  * In order to skip an optional argument but provide a later one, an empty
#    string ("") must be provided as a placeholder for the optional argument.
#  * In most cases, ICON and CATEGORIES should be provided.
#****
make_desktop_entry() {
	local dtfile

	if (( $# < 2 ))
	then
		error "make_desktop_entry requires a minimum of two arguments"
	fi

	dodir $(__host_prefix)/share/applications
	dtfile=$(__host_prefix)/share/applications/$(basename ${1// }).desktop

	cat > ${D}${dtfile} <<-_EOF
		[Desktop Entry]
		Encoding=UTF-8
		Version=1.0
		Name=${2}
		Exec=${1}
		TryExec=${1%% *}
		Type=Application
	_EOF

	if [ -n "${3}" ]
	then
		echo Icon=${3} >> ${D}${dtfile}
	fi
	if [ -n "${4}" ]
	then
		echo Categories=${4}\; >> ${D}${dtfile}
	fi
	if [ -n "${5}" ]
	then
		echo Comment=${5} >> ${D}${dtfile}
	fi
	for ((n=6; n <= $#; n++))
	do
		echo ${!n} >> ${D}${dtfile}
	done
}

#****I* Installing/make_etc_defaults
#  SYNOPSIS
#  make_etc_defaults FILE_PATH [FILE_PATH] ...
#  DESCRIPTION
#  Indicates that the given file(s) or directory/ies under $D contain templates
#  for system-configurable files.  make_etc_defaults moves these files/directories
#  to a special location, creates a postinstall script to install each file to
#  the correct location if it doesn't already exist, and a preremove script which
#  removes the file if still unchanged.
#****
make_etc_defaults() {
	if inherited cross
	then
		warning "make_etc_defaults is not supported when cross-compiling"
		return 0
	fi

	for etc in ${@}
	do
		if [ ! -e ${D}${etc} ]
		then
			error "file ${etc} does not exist"
		fi

		# if passed a directory, then process all files therein
		if [ -d ${D}${etc} ]
		then
			for f in $(find ${D}${etc} -type f ! -name '.keep-*')
			do
				make_etc_defaults ${f#${D}}
			done

			continue
		fi

		dodir /etc/defaults${etc%/*}
		mv ${D}${etc} ${D}/etc/defaults${etc}

		dodir /etc/postinstall
		cat >> ${D}/etc/postinstall/${PN}.sh <<-_EOF
			if [ ! -f ${etc} ]
			then
			    /usr/bin/mkdir -p ${etc%/*}
			    /usr/bin/cp /etc/defaults${etc} ${etc}
			fi

		_EOF

		dodir /etc/preremove
		cat >> ${D}/etc/preremove/${PN}.sh <<-_EOF
			if [ -f ${etc} ] && cmp -s /etc/defaults${etc} ${etc}
			then
			    rm ${etc}
			fi

		_EOF
	done
}

__prepinstalldirs() {
	rm -fr ${D}/*;
}

#****I* Installing/cyginstall
#  SYNOPSIS
#  cyginstall [OPTIONS]
#  DESCRIPTION
#  Runs 'make install' (or 'make install/fast' in CMake packages) with the
#  necessary arguments to install into $D, based on the value of USE_DESTDIR.
#****
cyginstall() {
	local inst_target prefix

	if $(make -n -s install/fast &> /dev/null)
	then
		inst_target="install/fast"
	else
		inst_target="install"
	fi

#****v* cyginstall/USE_DESTDIR
#  DESCRIPTION
#  Set to 1 (the default) if 'make install' supports the DESTDIR variable, or
#  0 if not, in which case the value of prefix and the standard *dir variables
#  will be overriden with $D-prefixed values.
#****
	if __arg_bool USE_DESTDIR true
	then
		make ${MAKEOPTS} ${inst_target} DESTDIR=${D} "${@}" || error "make install DESTDIR failed"
	else
		prefix=$(__host_prefix)
		make ${MAKEOPTS} install \
			prefix=${D}${prefix} \
			exec_prefix=${D}${prefix} \
			bindir=${D}${prefix}/bin/ \
			includedir=${D}${prefix}/include \
			libdir=${D}${prefix}/${MULTILIB_LIBDIR-lib} \
			sbindir=${D}${prefix}/sbin \
			libexecdir=${D}${prefix}/libexec \
			datadir=${D}${prefix}/share \
			datarootdir=${D}${prefix}/share \
			docdir=${D}${prefix}/share/doc/${PN} \
			infodir=${D}${prefix}/share/info \
			mandir=${D}${prefix}/share/man \
			localstatedir=${D}${prefix%/usr}/var \
			sysconfdir=${D}${prefix%/usr}/etc \
			"${@}" \
			|| error "make install No-DESTDIR failed"
	fi
}

#****I* Installing/src_install
#  DESCRIPTION
#  This function must be defined in the .cygport file, or in inherit()ed
#  cygclasses, containing all steps necessary to install the package into
#  $D and prepare it for packaging.
#
#  The default src_install function is shown below.  Several cygclasses
#  provide their own src_install overrides.
#  DEFINITION
src_install() {
	cd ${B}
	cyginstall
}
#****

# protect functions
readonly -f __doinstall __fix_shebang \
            dodir keepdir dobin newbin docinto dodoc newdoc \
            exeinto doexe newexe insinto doins newins doicon newicon \
            dolib doman newman domenu newmenu dosbin newsbin dosym \
            make_autostart_entry make_desktop_entry make_etc_defaults \
            __prepinstalldirs cyginstall
