################################################################################
#
# syntax.cygpart - cygport syntax enhancement functions
#
# Copyright (C) 2006-2015 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/>.
#
################################################################################

#****** Format/Syntax
#  DESCRIPTION
#  This section includes functions which provide some syntactical sugar.
#  These functions can be used anywhere.
#****

#****f* Syntax/defined
#  SYNOPSIS
#  if defined VARIABLE_NAME; then [...]; fi
#  DESCRIPTION
#  Tests if the given variable name is defined.  Returns TRUE if so, else FALSE.
#****
defined() {
	if (( $# != 1 ))
	then
		error "defined accepts exactly one argument"
	fi

	if [ -n "${!1}" ]
	then
		return 0;
	else
		return 1;
	fi
}

#****f* Syntax/pushd
#  SYNOPSIS
#  pushd DIRECTORY
#  DESCRIPTION
#  A silent wrapper for the bash pushd directory stack builtin.
#****
pushd() {
	builtin pushd ${@} > /dev/null
}

#****f* Syntax/popd
#  SYNOPSIS
#  popd
#  DESCRIPTION
#  A silent wrapper for the bash popd directory stack builtin.
#****
popd() {
	builtin popd ${@} > /dev/null
}

#****** Format/Messages
#  DESCRIPTION
#  This section includes functions which provide output to the user.
#  These functions may be used anywhere.
#****

#****f* Messages/error
#  SYNOPSIS
#  error MESSAGE
#  DESCRIPTION
#  Declares a fatal error.  The given message is displayed, then cygport exits.
#****
error() {
	case $? in
		0) local errorcode=1 ;;
		*) local errorcode=$? ;;
	esac

	echo -e "\e[1;31m*** ERROR:\e[0;0m ${1:-no error message provided}" >&2;
	exit ${errorcode};
}

#****f* Messages/warning
#  SYNOPSIS
#  warning MESSAGE
#  DESCRIPTION
#  Displays a warning message before continuing.
#****
warning() {
	echo -e "\e[1;33m*** Warning:\e[0;0m ${1}" >&2;
}

#****f* Messages/inform
#  SYNOPSIS
#  inform MESSAGE
#  DESCRIPTION
#  Displays an informational message.
#****
inform() {
	echo -e "\e[1;32m*** Info:\e[0;0m ${1}";
}

#****f* Messages/verbose
#  SYNOPSIS
#  verbose COMMAND
#  DESCRIPTION
#  Echoes the given command before executing it.  Returns the exit code of
#  the given command.
#****
verbose() {
	echo "${@}"
	"${@}"
	return $?
}

__stage() {
	echo -e "\e[1;39m>>> ${1} ${PF}.${ARCH}\e[0;0m";
}

__step() {
	echo -e ">>> ${1}";
}

__log_init() {
	local log=${1}
	rm -f ${log}

	echo -e cygport ${_version} '\n' >> ${log}

	for var in PF S B D C T CBUILD CHOST CTARGET CC CFLAGS CPPFLAGS CXX CXXFLAGS \
	           F77 FFLAGS FC FCFLAGS GCJ GCJFLAGS GOC GOFLAGS OBJC OBJCFLAGS \
	           OBJCXX OBJCXXFLAGS LDFLAGS LIBS MAKEOPTS
	do
		echo ${var} = ${!var} >> ${log}
	done

	echo -e '\n' >> ${log}
}

#****** Syntax/boolean
#  DESCRIPTION
#  A boolean variable is true if set to one of '1', 'on', 'true', or 'yes',
#  and false if set to one of '0', 'off', 'false', or 'no'.  These values
#  are case-insensitive.
#****
__arg_bool() {
	local ret
	local var=${1}

	case ${!var:-${2}} in
		1|[Yy]|[Yy][Ee][Ss]|[Oo][Nn]|[Tt][Rr][Uu][Ee]) # yes | on | true
			ret=0 ;;
		0|[Nn]|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) # no | off | false
			ret=1 ;;
		'')	ret=1 ;;	# unset, assume false
		*)	error "${var}: unknown value: ${!var}" ;;
	esac

	return ${ret}
}

__check_triplet() {
	if ! ${_privgnuconfigdir}/config.sub ${1} &> /dev/null
	then
		error "Unknown or invalid system triplet: ${1}"
	fi
}

#****** Syntax/cross_compiling
#  SYNOPSIS
#  if cross_compiling; then ...; fi
#  DESCRIPTION
#  Tests if the package is being cross-compiled.  Returns TRUE if so, else FALSE.
#****
cross_compiling() {
	return $(test ${CBUILD} != ${CHOST})
}

__cross_compiling_error() {
	if cross_compiling
	then
		error "${BASH_SOURCE[1]##*/} does not yet support cross-compiling"
	fi
}

__host_prefix() {
	local prefix sysroot

	if __host_is_embedded
	then
		sysroot=/usr/${CHOST}
	elif inherited cross
	then
		sysroot=${CROSS_SYSROOT}
	else
		sysroot=
	fi

	# FIXME: certainly other exceptions exist?
	case ${CHOST} in
		*-*-mingw*)	prefix=${sysroot}/mingw ;;
		avr|*-aout|*-coff|*-eabi*|*-elf|*-minix*|*-msdosdjgpp*|msp430|*-rdos*)
				prefix=${sysroot} ;;
		*)		prefix=${sysroot}/usr ;;
	esac

	echo -n ${prefix}
}

__host_is_embedded() {
	local ret=1;
	case ${CHOST} in
	avr|*-aout|*-coff|*-eabi*|*-elf|*-minix*|*-msdosdjgpp*|msp430|*-rdos*)
		ret=0 ;;
	esac
	return ${ret}
}

__target_prefix() {
	local prefix

	# FIXME: certainly other exceptions exist?
	case ${CTARGET} in
		*-*-mingw*)	prefix=/mingw ;;
		avr|*-aout|*-coff|*-eabi*|*-elf|*-minix*|*-msdosdjgpp*|msp430|*-rdos*)
				prefix=/ ;;
		*)		prefix=/usr ;;
	esac

	echo -n ${prefix}
}

__target_is_embedded() {
	local ret=1;
	case ${CTARGET} in
	avr|*-aout|*-coff|*-eabi*|*-elf|*-minix*|*-msdosdjgpp*|msp430|*-rdos*)
		ret=0 ;;
	esac
	return ${ret}
}

readonly -f defined pushd popd error warning inform verbose __stage __step \
	__log_init __check_triplet cross_compiling __cross_compiling_error \
	__host_prefix __host_is_embedded __target_prefix __target_is_embedded
