################################################################################
#
# syntax.cygpart - cygport syntax enhancement 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 3/Format
#  INTRODUCTION
#  If the .cygport file defines NAME, VERSION, and RELEASE, the filename may
#  be anything, but is conventionally NAME.cygport.  Otherwise, the filename
#  must be in the form NAME-VERSION-RELEASE.cygport, and the values of NAME,
#  VERSION, and RELEASE will be determined automatically.
#
#  A .cygport file must conform to bash shell syntax.  Comments may be included,
#  beginning with '#' until end-of-line; all comments are ignored during
#  execution of cygport.
#
#  Since a .cygport file is itself not a functioning script, the she-bang
#  header (#!/bin/bash) should be omitted, and the file should not be executable.
#
#  The bare minimum for a working .cygport file includes a SRC_URI definition,
#  and src_compile and src_install functions.  Note that several Cygclasses
#  provide some or all of these, so in some cases a single line inherit
#  command will suffice.
#****

#****** 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*|mmix|*-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*|mmix|*-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*|mmix|*-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*|mmix|*-msdosdjgpp*|msp430|*-rdos*)
		ret=0 ;;
	esac
	return ${ret}
}

#****** Format/Globals
#****
#****v* Globals/NAME
#  DESCRIPTION
#  The Cygwin (primary) package name.  Generally, this is the same as the
#  upstream package name, but need not be.  A common reason for deviating from
#  the upstream name is to append a version "slot" where multiple versions of
#  a package are completely parallel installable (e.g. gtk1.2 and gtk2.0, both
#  from gtk+).  In this case, define ORIG_PN to the upstream package name.
#****
#****v* Globals/VERSION
#  DESCRIPTION
#  The upstream package version number.  PV must begin with a digit 0-9, and
#  subsequent characters can be a digit, letter, dot, hyphen, or underscore.
#****
#****v* Globals/RELEASE
#  DESCRIPTION
#  The Cygwin package release number, e.g. the "1" in foo-2.3.4-1.  The first
#  release of a new version is usually 1, and is incremented if subsequent
#  releases are made of the same version.  PR must be an integer.
#****
#****d* Globals/PN
#  DESCRIPTION
#  A read-only alias for NAME.
#****
#****d* Globals/PV
#  DESCRIPTION
#  A read-only alias for VERSION.
#****
#****d* Globals/PR
#  DESCRIPTION
#  A read-only alias for RELEASE.
#****
#****d* Globals/P
#  DESCRIPTION
#  A read-only alias for NAME-VERSION (PN-PV).
#****
#****d* Globals/PVR
#  DESCRIPTION
#  A read-only alias for VERSION-RELEASE (PV-PR).
#****
#****d* Globals/PF
#  DESCRIPTION
#  A read-only alias for NAME-VERSION-RELEASE (PN-PV-PR).
#****
#****d* Globals/S
#  DESCRIPTION
#  The source directory.  Build tool regeneration (e.g. cygautoreconf) occurs
#  in this directory, but other build steps should occur in B.
#****
#****d* Globals/B
#  DESCRIPTION
#  The build directory.  All configuring and compiling steps should occur in
#  this directory.
#****
#****d* Globals/C
#  DESCRIPTION
#  The CYGWIN-PATCHES directory where Cygwin READMEs, setup.hint files,
#  custom postinstall scripts, and other Cygwin-specific files are placed
#  before packaging.
#****
#****d* Globals/D
#  DESCRIPTION
#  The installation staging directory.  All installation and postinstall steps
#  occur in or into this directory.
#****

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
