Files
modules/configure
2025-06-25 07:34:04 +02:00

1275 lines
51 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# CONFIGURE, check requirements then set variables and create Makefiles
# Copyright (C) 2017-2025 Xavier Delaruelle
#
# 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 2 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/>.
##########################################################################
progpath=$0
progdir=${progpath%/*}
# files to translate
targetlist="${progdir}/Makefile.inc ${progdir}/site.exp"
# argument list
arglist="TCLSH PYTHON SPHINXBUILD PS BASENAME RMDIR_IGN_NON_EMPTY SED_ERE \
VERSION RELEASE baseprefix prefix bindir libdir libexecdir etcdir initdir \
datarootdir mandir docdir vimdatadir modulefilesdir setmanpath appendmanpath \
setbinpath appendbinpath setmodulespath docinstall vimaddons \
examplemodulefiles builddoc usemanpath libtclenvmodules SHLIB_SUFFIX \
multilibsupport libdir64 libdir32 versioning silentshdbgsupport \
setshellstartup quarantinesupport autohandling availindepth implicitdefault \
extendeddefault moduleshome initconfin pager pageropts verbosity color \
darkbgcolors lightbgcolors termbg lockedconfigs icase unloadmatchorder \
searchmatch modulepath loadedmodules quarantinevars wa277 advversspec ml \
windowssupport nearlyforbiddendays implicitrequirement tagabbrev \
tagcolorname mcookieversioncheck availoutput availterseoutput listoutput \
listterseoutput editor variantshortcut bashcompletiondir fishcompletiondir \
zshcompletiondir tcllinter tcllinteropts nagelfardatadir nagelfaraddons \
stickypurge uniquenameloaded abortonerror sourcecache logger loggeropts \
loggedevents conflictunload spideroutput spiderterseoutput spiderindepth \
emacsdatadir emacsaddons requirevia"
libarglist=()
# flags to know if argument has been specified on command-line
defpageropts=1
defloggeropts=1
# set argument default values
prefix=/usr/local/Modules
setmanpath=y
appendmanpath=n
setbinpath=y
appendbinpath=n
setmodulespath=n
docinstall=y
vimaddons=y
emacsaddons=y
examplemodulefiles=y
libtclenvmodules=y
SHLIB_SUFFIX='.so'
multilibsupport=n
libdir64=undefined
libdir32=undefined
versioning=n
silentshdbgsupport=n
setshellstartup=n
quarantinesupport=n
autohandling=y
conflictunload=n
requirevia=n
implicitrequirement=y
availindepth=y
spiderindepth=y
implicitdefault=y
extendeddefault=y
advversspec=y
ml=y
wa277=n
loadedmodules=
quarantinevars=
binsearchpath=/usr/bin:/bin:/usr/local/bin
TCLSH=tclsh
PYTHON=python
SPHINXBUILD=sphinx-build
builddoc=y
usemanpath=y
PS='ps'
BASENAME='basename'
RMDIR_IGN_NON_EMPTY='rmdir'
SED_ERE='sed -E'
VERSION=
RELEASE=
# shellcheck disable=SC2034
initconfin=etcdir
loggedevents=
logger='logger'
loggeropts='-t modules'
pager=less
pageropts='-eFKRX'
verbosity=normal
color=y
darkbgcolors='hi=1:db=2:tr=2:se=2:er=91:wa=93:me=95:in=94:mp=1;94:di=94:al=96:va=93:sy=95:de=4:cm=92:aL=100:L=90;47:H=2:F=41:nF=31;43:S=46:sS=44:kL=30;48;5;109:W=30;43'
lightbgcolors='hi=1:db=2:tr=2:se=2:er=31:wa=33:me=35:in=34:mp=1;34:di=34:al=36:va=33:sy=35:de=4:cm=32:aL=107:L=47:H=2:F=101:nF=91;103:S=106:sS=104:kL=48;5;109:W=103'
termbg=dark
lockedconfigs=
uniquenameloaded=n
sourcecache=n
unloadmatchorder=returnlast
searchmatch=starts_with
icase=search
# these args are initialized here but as they depend on other argument value
# they will get their default value later (after command-line parse)
bindir=
libdir=
libexecdir=
etcdir=
initdir=
datarootdir=
mandir=
docdir=
vimdatadir=
emacsdatadir=
nagelfardatadir=
modulefilesdir=
moduleshome=
modulepath=
windowssupport=n
nearlyforbiddendays=14
tagabbrev='auto-loaded=aL:loaded=L:hidden=H:hidden-loaded=H:forbidden=F:nearly-forbidden=nF:sticky=S:super-sticky=sS:keep-loaded=kL:warning=W'
tagcolorname=
stickypurge=error
abortonerror='ml:reload:switch_unload'
mcookieversioncheck=y
availoutput='modulepath:alias:dirwsym:sym:tag:variantifspec:key'
availterseoutput='modulepath:alias:dirwsym:sym:tag:variantifspec'
listoutput='header:idx:variant:sym:tag:key'
listterseoutput='header'
spideroutput='modulepath:alias:dirwsym:sym:tag:variantifspec:via:key'
spiderterseoutput=$availterseoutput
editor='vi'
variantshortcut=
bashcompletiondir=
fishcompletiondir=
zshcompletiondir=
tcllinter='nagelfar.tcl'
tcllinteropts=
nagelfaraddons=y
# check if output/error channels are attached to terminal
for i in 1 2; do
if [ -t $i ]; then
fdisterm[i]=1
else
fdisterm[i]=0
fi
done
# apply SGR code to message if output channel is attached to terminal
sgr() {
local fd=$1
local code=$2
local msg=$3
if [ "${fdisterm[fd]}" -eq 1 ]; then
local out="\033[${code}m${msg}\033[0m"
else
local out=$msg
fi
echo "$out"
}
# print message on stderr then exit
echo_error() {
local firstln=1
while [ $# -gt 0 ]; do
if [ $firstln -eq 1 ]; then
local msg
msg="$(sgr 2 31 ERROR): $1"
firstln=0
elif [ "$1" = 'tryhelp' ]; then
msg="${msg}\n Try \`$progpath --help' for more information"
else
msg="${msg}\n $1"
fi
shift
done
echo -e "${msg}" >&2
exit 1
}
# print message on stderr then exit
echo_warning() {
echo -e "$(sgr 1 33 WARNING): $1"
}
# print usage message
echo_usage() {
# shellcheck disable=SC2028
echo "Usage: $progpath [OPTION]...
Check requirements then set variables and create Makefiles.
Defaults for the options are specified in square brackets.
Configuration:
-h, --help display this help and exit
Installation directories:
--prefix=PREFIX install files in PREFIX [$prefix]
By default, \`make install' will install all the files in
\`$prefix/bin', \`$prefix/libexec', etc. You
can specify an installation prefix other than \`$prefix'
using \`--prefix', for instance \`--prefix=\$HOME'.
For better control, use the options below.
Fine tuning of the installation directories:
--bindir=DIR user executables [PREFIX/bin]
--libdir=DIR object code libraries [PREFIX/lib]
--libexecdir=DIR program executables [PREFIX/libexec]
--etcdir=DIR program configurations [PREFIX/etc]
--initdir=DIR environment initialization scripts [PREFIX/init]
--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
--mandir=DIR man documentation [DATAROOTDIR/man]
--docdir=DIR documentation root [DATAROOTDIR/doc]
--vimdatadir=DIR Vim addons directory [DATAROOTDIR/vim/vimfiles]
--emacsdatadir=DIR Emacs addons directory [DATAROOTDIR/emacs/lisp]
--nagelfardatadir=DIR Nagelfar addons directory [DATAROOTDIR/nagelfar]
--modulefilesdir=DIR system modulefiles [PREFIX/modulefiles]
Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-set-manpath set mandir to MANPATH in init scripts [yes]
--enable-append-manpath append rather prepend mandir to MANPATH [no]
--enable-set-binpath set bindir to PATH in init scripts [yes]
--enable-append-binpath append rather prepend bindir to PATH [no]
--enable-modulespath, --enable-dotmodulespath
configure modules path in modulespath file rather
than initrc file (or respectively in .modulespath
file rather modulerc file if \`--with-initconf-in'
is set to 'initdir') [no]
--enable-doc-install install documentation files in the documentation
directory defined with \'docdir' (no impact on
man pages installation) [yes]
--enable-vim-addons install Vim addon files in the directory defined
with \'vimdatadir' [yes]
--enable-emacs-addons install Emacs addon files in the directory defined
with \'emacsdatadir' [yes]
--enable-nagelfar-addons
install Nagelfar addon files in the directory
defined with \'nagelfardatadir' [yes]
--enable-example-modulefiles
install in 'modulefilesdir' some modulefiles
provided as examples [yes]
--enable-libtclenvmodules
build and install the Modules Tcl extension library
and enable its load in modulecmd.tcl [yes]
--enable-multilib-support
support multilib systems by looking at an alternative
location where to find the Modules Tcl extension lib
depending on current machine architecture. [no]
--enable-versioning append modules version to installation prefix and
deploy a \`versions' modulepath, shared between all
versioning enabled Modules installation, containing
modulefiles that enable to switch from one Modules
version to another [no]
--enable-silent-shell-debug-support
generate code in module function definition to add
support for silencing shell debugging properties [no]
--enable-set-shell-startup
set when module function is defined the shell
startup file to ensure that the module function is
still defined in sub-shells [no]
--enable-quarantine-support
generate code in module function definition to add
support for the environment variable quarantine
mechanism [no]
--enable-auto-handling set modulecmd.tcl to automatically apply automated
modulefiles handling actions, like loading the
pre-requisites of a modulefile when loading this
modulefile [yes]
--enable-conflict-unload
set modulecmd.tcl to automatically unload modules
that conflict with modules to load and the dependent
of these conflicting modules [no]
--enable-require-via set modulecmd.tcl to consider that a module enabling
a modulepath is a requirement for the loaded modules
stored in this modulepath [no]
--enable-implicit-requirement
implicitly define a requirement toward modules
specified on ``module load`` or ``module unload``
commands in modulefile [yes]
--enable-avail-indepth control whether \`avail' search results should
recursively include or not modulefiles from
directories matching search query [yes]
--enable-spider-indepth control whether \`spider' search results should
recursively include or not modulefiles from
directories matching search query [yes]
--enable-implicit-default
implicitly set a default version for modules with
none defined [yes]
--enable-extended-default
allow partial module version specification [yes]
--enable-advanced-version-spec
activate the advanced module version specificers to
specify finer constraints on module version. [yes]
--enable-unique-name-loaded
only allow one module loaded per module name. [no]
--enable-source-cache cache files evaluated through \`source' Tcl command.
[no]
--enable-ml define \`ml' command when Modules initializes [yes]
--enable-color control colored output. \`yes' equals to the \`auto'
color mode. \`no' equals to the \`never' color mode
[yes]
--enable-wa-277 activate workaround for Tcsh history issue [no]
--enable-windows-support
install all required files for Windows platform [no]
--enable-new-features enable all new features that are disabled by default
due to substantial behavior changes they imply on
Modules 5 [no]
--enable-mcookie-version-check
enable check of the version specified right after
Modules magic cookie in modulefiles, which defines
the minimal version of the Modules tool to use to
evaluate the modulefile [yes]
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-bin-search-path=PATHLIST
list of paths to look at when searching the location
of tools required to build and configure Modules
[$binsearchpath]
--with-moduleshome location of the main Modules package file
directory [$prefix]
--with-initconf-in=VALUE
location where to install Modules initialization
configuration files. Either \`initdir' or \`etcdir'
[etcdir]
--with-tclsh=BIN name or full path of Tcl interpreter shell [tclsh]
--with-logger=BIN name or full path of default logger program to use
to log some evaluation information (can be super-
seeded at run-time by environment variable) [$logger]
--with-logger-opts=OPTLIST
settings to apply to default logger program
[$loggeropts]
--with-logged-events=EVENTLIST
events to log. accepted event names in EVENTLIST are
\`auto_eval', \`requested_eval' and \`requested_cmd'
(each event name in EVENTLIST should be separated by
\`:') [$loggedevents]
--with-pager=BIN name or full path of default pager program to use to
paginate informational message output (can be super-
seeded at run-time by environment variable) [$pager]
--with-pager-opts=OPTLIST
settings to apply to default pager program [$pageropts]
--with-verbosity=VALUE specify default message verbosity. accepted values
are \`silent', \`concise', \`normal', \`verbose',
\`verbose2', \`trace', \`debug' and \`debug2'
[$verbosity]
--with-dark-background-colors=SGRLIST
default color set to apply if terminal background
color is defined to \`dark'. Each element in SGRLIST
is an output item associated to a Select Graphic
Rendition (SGR) code (elements in SGRLIST are
separated by \`:')
[$darkbgcolors]
--with-light-background-colors=SGRLIST
default color set to apply if terminal background
color is defined to \`light'. Expect the same syntax
than described for \`--with-dark-background-colors'
[$lightbgcolors]
--with-terminal-background=VALUE
terminal background color which determines the color
set to apply by default between the \`dark' background
colors or the \`light' background colors [$termbg]
--with-locked-configs=CONFIGLIST
ignore environment variable superseding value for
listed configuration options. accepted option names
in CONFIGLIST are \`extra_siteconfig',
\`implicit_default', \`logged_events' and \`logger'
(each option name in CONFIGLIST should be separated
by \` ') [$lockedconfigs]
--with-unload-match-order=VALUE
when unloading a module if multiple loaded modules
match the request, unload module loaded first
(\`returnfirst') or module loaded last (\`returnlast')
[$unloadmatchorder]
--with-search-match=VALUE
when searching for a module, query string should
match the beginning of module name (\`starts_with')
or any part of module name (\`contains')
[$searchmatch]
--with-icase=VALUE apply a case insensitive match to module
specification on search-like sub-commands
(\`search'), on all sub-commands and modulefile Tcl
commands (\`always') or disable case insensitive
match (\`never') [$icase]
--with-nearly-forbidden-days=VALUE
define the number of days a module is considered
nearly forbidden prior reaching its expiry date [$nearlyforbiddendays]
--with-tag-abbrev=ABBRVLIST
define the abbreviation to use when reporting each
module tag. Each element in ABBRVLIST is a tag name
associated to an abbreviation string (elements in
ABBRVLIST are separated by \`:')
[$tagabbrev]
--with-tag-color-name=TAGLIST
define the tags whose graphical rendering should be
applied over their name instead of over the name of
the module they are attached to. Each element in
TAGLIST is a tag name or abbreviation (elements in
TAGLIST are separated by \`:') [$tagcolorname]
--with-sticky-purge=VALUE
define the kind of error to render when unloading
a sticky or super-sticky module during a purge.
Raise an \`error' or report a \`warning' or be
\`silent'. [$stickypurge]
--with-abort-on-error=LIST
list of sub-commands that should abort when a module
evaluation fails instead of continuing their
evaluation sequence. sub-commands accepted in LIST
are: \`load', \`ml', \`mod-to-sh', \`purge',
\`reload', \`switch', \`switch_unload', \`try-load'
and \`unload' (elements in LIST are separated by
\`:') [$abortonerror]
--with-avail-output=LIST
specify content to report on avail sub-command
regular output. elements accepted in LIST are:
\`modulepath', \`alias', \`provided-alias',
\`dirwsym', \`indesym', \`sym', \`tag', \`key',
\`hidden', \`variant', \`variantifspec' and \`via'
(elements in LIST are separated by \`:')
[$availoutput]
--with-avail-terse-output=LIST
specify content to report on avail sub-command
terse output. elements accepted in LIST are:
\`modulepath', \`alias', \`provided-alias',
\`dirwsym', \`indesym', \`sym', \`tag', \`key',
\`hidden', \`variant' and \`variantifspec' (elements
in LIST are separated by \`:')
[$availterseoutput]
--with-list-output=LIST
specify content to report on list sub-command
regular output. elements accepted in LIST are:
\`header', \`idx', \`variant', \`alias', \`indesym',
\`sym', \`tag', \`hidden' and \`key' (elements in
LIST are separated by \`:') [$listoutput]
--with-list-terse-output=LIST
specify content to report on list sub-command terse
output. elements accepted in LIST are: \`header',
\`idx', \`variant', \`alias', \`indesym', \`sym',
\`tag', \`hidden' and \`key' (elements in LIST are
separated by \`:') [$listterseoutput]
--with-spider-output=LIST
specify content to report on spider sub-command
regular output. elements accepted in LIST are:
\`modulepath', \`alias', \`provided-alias',
\`dirwsym', \`indesym', \`sym', \`tag', \`key',
\`hidden', \`variant', \`variantifspec' and \`via'
(elements in LIST are separated by \`:')
[$spideroutput]
--with-spider-terse-output=LIST
specify content to report on spider sub-command
terse output. elements accepted in LIST are:
\`modulepath', \`alias', \`provided-alias',
\`dirwsym', \`indesym', \`sym', \`tag', \`key',
\`hidden', \`variant' and \`variantifspec' (elements
in LIST are separated by \`:')
[$spiderterseoutput]
--with-variant-shortcut=SHORTCUTLIST
define shortcut characters to specify variant names.
Each element in SHORTCUTLIST is a variant name
associated to a shortcut character (elements in
SHORTCUTLIST are separated by \`:') [$variantshortcut]
--with-editor=BIN name or full path of default editor program to use to
edit modulefiles [$editor]
--with-modulepath=PATHLIST
default modulepaths to set in default configuration
file to be enabled (each path in PATHLIST should
be separated by \`:') [PREFIX/modulefiles or
BASEPREFIX/\$MODULE_VERSION/modulefiles if versioning
installation mode enabled]
--with-loadedmodules=MODLIST
default modulefiles to set in default configuration
file to be loaded (each modulefile name in MODLIST
should be separated by \`:') []
--with-quarantine-vars='VARNAME[=VALUE] ...'
environment variables to put in quarantine when
running the module command to ensure it a sane
execution environment (each variable should be
separated by \` '). a value can eventually be set to
a quarantine variable instead of emptying it. []
--with-tcl directory containing the Tcl configuration script
tclConfig.sh.
--with-tclinclude directory containing the Tcl header files.
--with-python=BIN name or full path of Python interpreter command to
use as shebang for helper scripts [$PYTHON]
--with-bashcompletiondir=DIR
Bash completions directory []
--with-fishcompletiondir=DIR
Fish completions directory []
--with-zshcompletiondir=DIR
Zsh completions directory []
--with-tcl-linter=BIN name of full path of program to use to lint Tcl
modulefiles [$tcllinter]
--with-tcl-linter-opts=OPTLIST
settings to apply to tcl linter program [$tcllinteropts]
Depending on the above configuration options the files are approximately
placed in the following directory structure:
PREFIX/
bin/
etc/
init/
lib/
libexec/
share/
doc/
emacs/
lisp/
man/
man1/
man5/
nagelfar/
vim/
vimfiles/
modulefiles/"
}
# check requirement availability
check_requirement() {
typeset req=$1
typeset optmesg=$2
typeset cmdenv=$3
if [ $# -gt 3 ]; then
shift 3
else
shift $#
fi
for cmd in $req "${@}"; do
if [ -n "$cmd" ]; then
echo -n "checking for ${cmd}... "
if [ -n "$cmdenv" ]; then
cmdsearch="$cmdenv command -v $cmd"
else
cmdsearch="command -v $cmd"
fi
reqpath=$(eval "$cmdsearch")
if [ -n "$reqpath" ]; then
echo "$reqpath"
break
else
echo "not found"
fi
fi
done
if [ -z "$reqpath" ]; then
if [ -z "$optmesg" ]; then
echo_error "$req could not be found"
# no message output if message set to '-'
elif [ "$optmesg" != '-' ]; then
echo_warning "$optmesg"
fi
fi
}
# parse optional argument to find if feature is enabled or disabled
get_feature_value() {
typeset val="${1#*=}"
if [ "${1//--enable/}" != "$1" ]; then
if [ "$val" = 'no' ]; then
echo 'n'
else
echo 'y'
fi
else
echo 'n'
fi
}
# parse optional argument to extract package's option
get_package_option() {
typeset option="${1%=*}"
echo "${option/#--without/--with}"
}
# parse optional argument to find package is set or disabled
get_package_value() {
typeset val_raw="${1#*=}"
typeset dfl_without_val="$2"
if [ "${1/#--with-/}" = "$1" ] || [ "$val_raw" = 'no' ]; then
value="$dfl_without_val"
else
value="$val_raw"
fi
echo "$value"
}
check_and_get_package_value() {
typeset arg_raw="$2"
typeset allowed_values="$3"
typeset dfl_without_val="$4"
option=$(get_package_option "$arg_raw")
value=$(get_package_value "$arg_raw" "$dfl_without_val")
if [ "${allowed_values// $value /}" = "$allowed_values" ]; then
echo_error "Bad value for option \`$option'"\
"Allowed values are:$allowed_values"
fi
typeset -g "$1"="$value"
}
check_and_get_package_value_list() {
typeset arg_raw="$2"
typeset allowed_values="$3"
typeset dfl_without_val="$4"
option=$(get_package_option "$arg_raw")
value=$(get_package_value "$arg_raw" "$dfl_without_val")
ORIG_IFS=$IFS
IFS=:
for val in $value; do
if [ "${allowed_values// $val /}" = "$allowed_values" ]; then
echo_error "Bad value '$val' set in option \`$option'"\
"Values allowed in list are:$allowed_values"
fi
done
IFS=$ORIG_IFS
typeset -g "$1"="$value"
}
# parse arguments
for arg in "$@"; do
# set argument value defined with "--arg val" form
if [ -n "${nextargisval+x}" ]; then
declare "$nextargisval"="$arg"
unset nextargisval
continue
# set lib argument value defined with "--arg val" form
elif [ -n "${nextargislibarg+x}" ]; then
libarglist+=("$arg");
unset nextargislibarg
continue
# current arg should be skipped
elif [ -n "${nextargisign+x}" ]; then
unset nextargisign
continue
fi
case "$arg" in
--prefix=*)
prefix="${arg#*=}" ;;
--prefix)
nextargisval=prefix ;;
--bindir=*)
bindir="${arg#*=}" ;;
--bindir)
nextargisval=bindir ;;
--libdir=*)
libdir="${arg#*=}" ;;
--libdir)
nextargisval=libdir ;;
--libexecdir=*)
libexecdir="${arg#*=}" ;;
--libexecdir)
nextargisval=libexecdir ;;
--etcdir=*)
etcdir="${arg#*=}" ;;
--etcdir)
nextargisval=etcdir ;;
--initdir=*)
initdir="${arg#*=}" ;;
--initdir)
nextargisval=initdir ;;
--datarootdir=*)
datarootdir="${arg#*=}" ;;
--datarootdir)
nextargisval=datarootdir ;;
--mandir=*)
mandir="${arg#*=}" ;;
--mandir)
nextargisval=mandir ;;
--docdir=*)
docdir="${arg#*=}" ;;
--docdir)
nextargisval=docdir ;;
--vimdatadir=*)
vimdatadir="${arg#*=}" ;;
--vimdatadir)
nextargisval=vimdatadir ;;
--emacsdatadir=*)
emacsdatadir="${arg#*=}" ;;
--emacsdatadir)
nextargisval=emacsdatadir ;;
--nagelfardatadir=*)
nagelfardatadir="${arg#*=}" ;;
--nagelfardatadir)
nextargisval=nagelfardatadir ;;
--modulefilesdir=*)
modulefilesdir="${arg#*=}" ;;
--modulefilesdir)
nextargisval=modulefilesdir ;;
--enable-set-manpath*|--disable-set-manpath)
# shellcheck disable=SC2034
setmanpath=$(get_feature_value "$arg") ;;
--enable-append-manpath*|--disable-append-manpath)
# shellcheck disable=SC2034
appendmanpath=$(get_feature_value "$arg") ;;
--enable-set-binpath*|--disable-set-binpath)
# shellcheck disable=SC2034
setbinpath=$(get_feature_value "$arg") ;;
--enable-append-binpath*|--disable-append-binpath)
# shellcheck disable=SC2034
appendbinpath=$(get_feature_value "$arg") ;;
--enable-dotmodulespath*|--disable-dotmodulespath|--enable-modulespath*|--disable-modulespath)
setmodulespath=$(get_feature_value "$arg") ;;
--enable-doc-install*|--disable-doc-install)
# shellcheck disable=SC2034
docinstall=$(get_feature_value "$arg") ;;
--enable-vim-addons*|--disable-vim-addons)
# shellcheck disable=SC2034
vimaddons=$(get_feature_value "$arg") ;;
--enable-emacs-addons*|--disable-emacs-addons)
# shellcheck disable=SC2034
emacsaddons=$(get_feature_value "$arg") ;;
--enable-nagelfar-addons*|--disable-nagelfar-addons)
# shellcheck disable=SC2034
nagelfaraddons=$(get_feature_value "$arg") ;;
--enable-example-modulefiles*|--disable-example-modulefiles)
# shellcheck disable=SC2034
examplemodulefiles=$(get_feature_value "$arg") ;;
--enable-libtclenvmodules*|--disable-libtclenvmodules)
libtclenvmodules=$(get_feature_value "$arg") ;;
--enable-multilib-support*|--disable-multilib-support)
multilibsupport=$(get_feature_value "$arg") ;;
--enable-versioning*|--disable-versioning)
versioning=$(get_feature_value "$arg") ;;
--enable-silent-shell-debug-support*|--disable-silent-shell-debug-support)
# shellcheck disable=SC2034
silentshdbgsupport=$(get_feature_value "$arg") ;;
--enable-set-shell-startup*|--disable-set-shell-startup)
# shellcheck disable=SC2034
setshellstartup=$(get_feature_value "$arg") ;;
--enable-quarantine-support*|--disable-quarantine-support)
# shellcheck disable=SC2034
quarantinesupport=$(get_feature_value "$arg") ;;
--enable-auto-handling*|--disable-auto-handling)
# shellcheck disable=SC2034
autohandling=$(get_feature_value "$arg") ;;
--enable-conflict-unload*|--disable-conflict-unload)
# shellcheck disable=SC2034
conflictunload=$(get_feature_value "$arg") ;;
--enable-require-via*|--disable-require-via)
# shellcheck disable=SC2034
requirevia=$(get_feature_value "$arg") ;;
--enable-implicit-requirement*|--disable-implicit-requirement)
# shellcheck disable=SC2034
implicitrequirement=$(get_feature_value "$arg") ;;
--enable-avail-indepth*|--disable-avail-indepth)
# shellcheck disable=SC2034
availindepth=$(get_feature_value "$arg") ;;
--enable-spider-indepth*|--disable-spider-indepth)
# shellcheck disable=SC2034
spiderindepth=$(get_feature_value "$arg") ;;
--enable-implicit-default*|--disable-implicit-default)
# shellcheck disable=SC2034
implicitdefault=$(get_feature_value "$arg") ;;
--enable-extended-default*|--disable-extended-default)
# shellcheck disable=SC2034
extendeddefault=$(get_feature_value "$arg") ;;
--enable-advanced-version-spec*|--disable-advanced-version-spec)
# shellcheck disable=SC2034
advversspec=$(get_feature_value "$arg") ;;
--enable-unique-name-loaded*|--disable-unique-name-loaded)
# shellcheck disable=SC2034
uniquenameloaded=$(get_feature_value "$arg") ;;
--enable-source-cache*|--disable-source-cache)
# shellcheck disable=SC2034
sourcecache=$(get_feature_value "$arg") ;;
--enable-ml*|--disable-ml)
# shellcheck disable=SC2034
ml=$(get_feature_value "$arg") ;;
--enable-wa-277*|--disable-wa-277)
# shellcheck disable=SC2034
wa277=$(get_feature_value "$arg") ;;
--enable-windows-support*|--disable-windows-support)
# shellcheck disable=SC2034
windowssupport=$(get_feature_value "$arg") ;;
--enable-mcookie-version-check*|--disable-mcookie-version-check)
# shellcheck disable=SC2034
mcookieversioncheck=$(get_feature_value "$arg") ;;
--with-bin-search-path=*|--without-bin-search-path)
binsearchpath=$(get_package_value "$arg") ;;
--with-moduleshome=*|--without-moduleshome)
moduleshome=$(get_package_value "$arg") ;;
--with-initconf-in=*|--without-initconf-in)
allowedval=" initdir etcdir " ;
check_and_get_package_value "initconfin" "$arg" "$allowedval" ;;
--with-tclsh=*|--without-tclsh)
tclshbin=$(get_package_value "$arg") ;;
--with-logger=*|--without-logger)
logger=$(get_package_value "$arg" "") ;;
--with-logger-opts=*|--without-logger-opts)
loggeropts=$(get_package_value "$arg" "")
defloggeropts=0 ;;
--with-logged-events=*|--without-logged-events)
allowedval=" auto_eval requested_eval requested_cmd " ;
check_and_get_package_value_list "loggedevents" "$arg" "$allowedval" "" ;;
--with-pager=*|--without-pager)
pager=$(get_package_value "$arg" "") ;;
--with-pager-opts=*|--without-pager-opts)
pageropts=$(get_package_value "$arg" "")
defpageropts=0 ;;
--with-verbosity=*|--without-verbosity)
allowedval=" silent concise normal verbose trace debug debug2 " ;
check_and_get_package_value "verbosity" "$arg" "$allowedval" ;;
--enable-color*|--disable-color)
# shellcheck disable=SC2034
color=$(get_feature_value "$arg") ;;
--enable-new-features*|--disable-new-features)
val=$(get_feature_value "$arg") ;
if [ "$val" = 'y' ]; then
abortonerror='load:ml:reload:switch' ;
# shellcheck disable=SC2034
conflictunload=y ;
# shellcheck disable=SC2034
requirevia=y ;
fi ;;
--with-dark-background-colors=*|--without-dark-background-colors)
darkbgcolors=$(get_package_value "$arg" "") ;;
--with-light-background-colors=*|--without-light-background-colors)
lightbgcolors=$(get_package_value "$arg" "") ;;
--with-terminal-background=*|--without-terminal-background)
allowedval=" dark light " ;
check_and_get_package_value "termbg" "$arg" "$allowedval" ;;
--with-locked-configs=*|--disable-locked-configs)
lockedconfigs=$(get_package_value "$arg" "") ;
allowedval=" extra_siteconfig implicit_default logged_events logger " ;
for val in $lockedconfigs; do
if [ "${allowedval// $val /}" = "$allowedval" ]; then
echo_error "Bad value for option \`--with-locked-configs'"\
"Allowed values are:$allowedval"
fi ;
done ;;
--with-unload-match-order=*|--without-unload-match-order)
allowedval=" returnlast returnfirst " ;
check_and_get_package_value "unloadmatchorder" "$arg" "$allowedval" ;;
--with-search-match=*|--without-search-match)
allowedval=" starts_with contains " ;
check_and_get_package_value "searchmatch" "$arg" "$allowedval" ;;
--with-icase=*|--without-icase)
allowedval=" never search always " ;
check_and_get_package_value "icase" "$arg" "$allowedval" "never";;
--with-nearly-forbidden-days=*|--without-nearly-forbidden-days)
nearlyforbiddendays=$(get_package_value "$arg") ;
if [ -z "$nearlyforbiddendays" ] || ! [ "$nearlyforbiddendays" -eq "$nearlyforbiddendays" ] 2>/dev/null\
|| ! [ "$nearlyforbiddendays" -ge 0 ] || ! [ "$nearlyforbiddendays" -le 365 ]; then
echo_error "Bad value for option \`--with-nearly-forbidden-days'"\
"Value should be an integer comprised between 0 and 365"
fi ;;
--with-tag-abbrev=*|--without-tag-abbrev)
tagabbrev=$(get_package_value "$arg" "") ;;
--with-tag-color-name=*|--without-tag-color-name)
tagcolorname=$(get_package_value "$arg" "") ;;
--with-sticky-purge=*|--without-sticky-purge)
allowedval=" error warning silent " ;
check_and_get_package_value "stickypurge" "$arg" "$allowedval" ;;
--with-abort-on-error=*|--without-abort-on-error)
allowedval=" load ml mod-to-sh purge reload switch switch_unload try-load unload " ;
check_and_get_package_value_list "abortonerror" "$arg" "$allowedval" "" ;;
--with-avail-output=*|--without-avail-output)
allowedval=" modulepath alias provided-alias dirwsym indesym sym tag key hidden variant variantifspec via " ;
check_and_get_package_value_list "availoutput" "$arg" "$allowedval" "" ;;
--with-avail-terse-output=*|--without-avail-terse-output)
allowedval=" modulepath alias provided-alias dirwsym indesym sym tag key hidden variant variantifspec " ;
check_and_get_package_value_list "availterseoutput" "$arg" "$allowedval" "" ;;
--with-list-output=*|--without-list-output)
allowedval=" header idx variant alias indesym sym tag hidden key " ;
check_and_get_package_value_list listoutput "$arg" "$allowedval" "" ;;
--with-list-terse-output=*|--without-list-terse-output)
allowedval=" header idx variant alias indesym sym tag hidden key " ;
check_and_get_package_value_list "listterseoutput" "$arg" "$allowedval" "" ;;
--with-spider-output=*|--without-spider-output)
allowedval=" modulepath alias provided-alias dirwsym indesym sym tag key hidden variant variantifspec via " ;
check_and_get_package_value_list "spideroutput" "$arg" "$allowedval" "" ;;
--with-spider-terse-output=*|--without-spider-terse-output)
allowedval=" modulepath alias provided-alias dirwsym indesym sym tag key hidden variant variantifspec " ;
check_and_get_package_value_list "spiderterseoutput" "$arg" "$allowedval" "" ;;
--with-variant-shortcut=*|--without-variant-shortcut)
variantshortcut=$(get_package_value "$arg" "") ;;
--with-editor=*|--without-editor)
editor=$(get_package_value "$arg") ;;
--with-modulepath=*|--without-modulepath)
modulepath=$(get_package_value "$arg" "") ;;
--with-loadedmodules=*|--without-loadedmodules)
loadedmodules=$(get_package_value "$arg" "") ;;
--with-quarantine-vars=*|--without-quarantine-vars)
# shellcheck disable=SC2034
quarantinevars=$(get_package_value "$arg" "") ;;
--with-bashcompletiondir=*|--without-bashcompletiondir)
# shellcheck disable=SC2034
bashcompletiondir=$(get_package_value "$arg" "") ;;
--with-fishcompletiondir=*|--without-fishcompletiondir)
# shellcheck disable=SC2034
fishcompletiondir=$(get_package_value "$arg" "") ;;
--with-zshcompletiondir=*|--without-zshcompletiondir)
# shellcheck disable=SC2034
zshcompletiondir=$(get_package_value "$arg" "") ;;
--with-tcl-linter=*|--without-tcl-linter)
tcllinter=$(get_package_value "$arg" "") ;;
--with-tcl-linter-opts=*|--without-tcl-linter-opts)
# shellcheck disable=SC2034
tcllinteropts=$(get_package_value "$arg" "") ;;
--with-tcl=*|--without-tcl|--with-tclinclude=*|--without-tclinclude)
libarglist+=("$arg") ;;
--with-python=*|--without-python)
pythonbin=$(get_package_value "$arg") ;;
--with-module-path=*)
echo_warning "Option \`--with-module-path' ignored, use \`--modulepath' instead" ;;
-h|--help)
echo_usage
exit 0
;;
--build|--host|--target)
# pass argument supported by lib to its ./configure script
libarglist+=("$arg") ;
# and set next arg should also be send to lib script
nextargislibarg=y ;;
--build=*|--host=*|--target=*)
# pass argument supported by lib to its ./configure script
libarglist+=("$arg") ;;
--program-prefix|--program-suffix|--program-transform-name|--exec-prefix|\
--sbindir|--sysconfdir|--datadir|--includedir|--localstatedir|\
--sharedstatedir|--infodir|--runstatedir|--oldincludedir|--localedir|\
--htmldir|--dvidir|--pdfdir|--psdir)
# ignore standard configure option and value which has no meaning here
echo_warning "Option \`$arg' ignored" ;
nextargisign=y ;;
--program-prefix=*|--program-suffix=*|--program-transform-name=*|\
--exec-prefix=*|--sbindir=*|--sysconfdir=*|--datadir=*|--includedir=*|\
--localstatedir=*|--sharedstatedir=*|--infodir=*|--runstatedir=*|\
--oldincludedir=*|--localedir=*|--htmldir=*|--dvidir=*|--pdfdir=*|\
--psdir=*)
# ignore standard configure option which has no meaning here
echo_warning "Option \`$arg' ignored" ;;
--enable-*|--disable-*|--with-*|--without-*)
# ignore --enable-*/--with-* options not supported here to comply with
# GNU Configuration specification
# (https://www.gnu.org/prep/standards/html_node/Configuration.html)
echo_warning "Option \`$arg' ignored" ;;
-*)
echo_error "Unrecognized option \`$arg'" tryhelp;;
*=*)
echo -e "Export \`$arg' in environment" ;
export "${arg?}" ;;
*)
# type of system to build the program for (not needed here but useful
# for true autoconf configure script below
libarglist+=("$arg") ;;
esac
done
# test requirements availability
check_requirement uname
kernelname=$(uname -s)
# Makefile for this project are GNU Makefile so we must ensure correct make
# command is available, on Linux/Darwin systems the 'make' bin refers to GNU
# Make whereas on other system it is not the default make flavor, so 'gmake'
# should be checked
case "$kernelname" in
Linux|Darwin|CYGWIN*|MINGW*|MSYS_NT*) make='make' ;;
*) make='gmake'
esac
check_requirement $make
check_requirement sed
check_requirement runtest "Install \`dejagnu' if you want to run the \
testsuite"
check_requirement manpath 'Will rely on MANPATH to get enabled man directories'
# shellcheck disable=SC2034
[ -z "$reqpath" ] && usemanpath=n
# rmdir option may not be available, use || true in any case
# shellcheck disable=SC2034
if [ "$kernelname" = 'Linux' ]; then
RMDIR_IGN_NON_EMPTY='rmdir --ignore-fail-on-non-empty'
else
RMDIR_IGN_NON_EMPTY='rmdir'
fi
# sed -E option may not be available, use -r option otherwise
if [ "$(echo foo | $SED_ERE 's|foo|bar|' 2>/dev/null)" != 'bar' ]; then
SED_ERE='sed -r'
fi
export GIT_DIR="${progdir}/.git"
export GIT_WORK_TREE="${progdir}"
test -e "${GIT_DIR}"
work_from_git_repo=$?
# if we install from git repository, must have git to fetch current release number
if [ $work_from_git_repo -eq 0 ]; then
check_requirement git
fi
# if pre-built docs are available (but not from a previous make run), no doc
# build but install pre-built files
builddocdir="${progdir}/doc/build"
oldbuilddoc=$(sed -n '/^builddoc/{s/.*:= //p;q;}' Makefile.inc 2>/dev/null)
if [ -e "${builddocdir}/changes.txt" ] && [ -e "${builddocdir}/MIGRATING.txt" ] \
&& [ -e "${builddocdir}/INSTALL.txt" ] && [ -e "${builddocdir}/INSTALL-win.txt" ] \
&& [ -e "${builddocdir}/NEWS.txt" ] && [ -e "${builddocdir}/CONTRIBUTING.txt" ] \
&& [ -e "${builddocdir}/module.1.in" ] && [ -e "${builddocdir}/ml.1" ] \
&& [ -e "${builddocdir}/envml.1" ] && [ -e "${builddocdir}/modulefile.5" ] \
&& [ "$oldbuilddoc" != 'y' ]; then
builddoc=p
# test sphinx availability otherwise
else
# pass even if sphinx not there but no doc will be built
check_requirement sphinx-build "Install \`sphinx-build' if you want to \
build the documentation" '' 'sphinx-1.0-build'
# shellcheck disable=SC2034
SPHINXBUILD=$reqpath
# shellcheck disable=SC2034
[ -z "$reqpath" ] && builddoc=n
fi
# get tclsh location from standard PATHs or /usr/local/bin
# or validate location passed as argument
if [ -n "$tclshbin" ]; then
check_requirement "$tclshbin" '' "PATH=$binsearchpath"
else
# also check version-specific names in case no generic tclsh binary exists
check_requirement $TCLSH '' "PATH=$binsearchpath" 'tclsh8.6' 'tclsh8.5' 'tclsh8.4'
fi
TCLSH=$reqpath
# python is mandatory if installing from git repository to build ChangeLog
if [ $work_from_git_repo -eq 0 ]; then
missmsg=''
elif [ -n "$pythonbin" ]; then
missmsg="Specified Python command \`$pythonbin' cannot be found"
else
missmsg='-'
fi
# only look at --with-python specification if set
if [ -n "$pythonbin" ]; then
check_requirement "$pythonbin" "$missmsg" "PATH=$binsearchpath"
else
check_requirement $PYTHON "$missmsg" "PATH=$binsearchpath" 'python3' 'python2'
fi
# define a generic launching name if command not found at build time
if [ -z "$reqpath" ]; then
# use --with-python specification if set
if [ "${pythonbin:0:1}" = '/' ]; then
PYTHON="$pythonbin"
elif [ -n "$pythonbin" ]; then
PYTHON="/usr/bin/env $pythonbin"
else
PYTHON="/usr/bin/env $PYTHON"
fi
else
PYTHON=$reqpath
fi
# gzip is mandatory if installing from git repository to build ChangeLog.gz
if [ $work_from_git_repo -eq 0 ]; then
check_requirement gzip
fi
# get location of commands used 'fullpath' in init scripts
check_requirement 'ps' '' "PATH=$binsearchpath"
# shellcheck disable=SC2034
PS=$reqpath
check_requirement 'basename' '' "PATH=$binsearchpath"
# shellcheck disable=SC2034
BASENAME=$reqpath
# get logger program location from standard PATHs or /usr/local/bin
# or validate location passed as argument
if [ -n "$logger" ]; then
check_requirement "$logger" '' "PATH=$binsearchpath"
logger=$reqpath
fi
# adapt logger program settings dependings of specified args
if [ $defloggeropts -eq 1 ] && [ "${logger##*/}" != 'logger' ]; then
loggeropts=''
echo_warning "As chosen logger is not \`logger', default logger options are cleared"
fi
# get pager program location from standard PATHs or /usr/local/bin
# or validate location passed as argument
if [ -n "$pager" ]; then
check_requirement "$pager" '' "PATH=$binsearchpath"
pager=$reqpath
fi
# adapt pager program settings dependings of specified args
if [ $defpageropts -eq 1 ] && [ "${pager##*/}" != 'less' ]; then
pageropts=''
echo_warning "As chosen pager is not \`less', default pager options are cleared"
fi
if [ -n "$tcllinter" ]; then
check_requirement "$tcllinter" "$tcllinter could not be found" "PATH=$binsearchpath"
if [ -n "$reqpath" ]; then
tcllinter=$reqpath
fi
fi
# fetch modules version from version.inc.in file (which may be raw data to
# refine or exact values if dist has been built by `git archive`)
if [ -r "${progdir}/version.inc.in" ]; then
release=$(sed -n '/^MODULES_RELEASE/{s/.*= //p;q;}' \
"${progdir}/version.inc.in")
build_hash=$(sed -n '/^MODULES_BUILD_HASH/{s/.*= //p;q;}' \
"${progdir}/version.inc.in")
build_refs=$(sed -n '/^MODULES_BUILD_REFS/{s/.*= //p;q;}' \
"${progdir}/version.inc.in")
build_refs=${build_refs//,}
build_refs=${build_refs//origin\/}
else
echo_error "${progdir}/version.inc.in is missing"
fi
# refine build number if working from git repository
# shellcheck disable=SC2016
if [ $work_from_git_repo -eq 0 ]; then
gitcurtag=$(git describe --tags --abbrev=0)
gitcurdesc=$(git describe --tags)
gitcurbranch=$(git rev-parse --abbrev-ref HEAD)
if [ "$gitcurtag" = "$gitcurdesc" ]; then
build=''
elif [ "$gitcurbranch" = 'main' ]; then
build="+${gitcurdesc#"${gitcurtag}"-}"
else
build="+${gitcurbranch}${gitcurdesc#"${gitcurtag}"}"
fi
# set a recognizable build number if one found in version.inc.in is raw data
elif [ "$build_hash" = '$Format:%h' ]; then
build='+XX-gffffffff'
# or compute it from these information as if working from git repository
elif [[ " $build_refs " == *" v$release "* ]]; then
build=''
elif [[ " $build_refs " == *" main "* ]]; then
build="+XX-g$build_hash"
# %D placeholder may not be known by old version of git
elif [ "$build_refs" = "%D" ]; then
build="+XX-g$build_hash"
else
build="+${build_refs##* }-XX-g$build_hash"
fi
VERSION=$release$build
# shellcheck disable=SC2034
RELEASE=$release
if [ -z "$VERSION" ]; then
echo_error "Cannot fetch modules version"
fi
# refer to binary exes and libs to build with the appropriate extension
# shellcheck disable=SC2034
case "$kernelname" in
CYGWIN*) SHLIB_SUFFIX='.dll' ;;
MINGW*|MSYS_NT*) SHLIB_SUFFIX='.dll' ;;
Darwin) SHLIB_SUFFIX='.dylib' ;;
esac
# adapt prefix if versioning enabled
baseprefix=$prefix
if [ "$versioning" = 'y' ]; then
# append modules version to installation prefix
prefix=$prefix/$VERSION
fi
# set argument default values for those depending of other argument
[ -z "$bindir" ] && bindir=$prefix/bin
[ -z "$libdir" ] && libdir=$prefix/lib
[ -z "$libexecdir" ] && libexecdir=$prefix/libexec
[ -z "$etcdir" ] && etcdir=$prefix/etc
[ -z "$initdir" ] && initdir=$prefix/init
[ -z "$datarootdir" ] && datarootdir=$prefix/share
[ -z "$mandir" ] && mandir=$datarootdir/man
[ -z "$docdir" ] && docdir=$datarootdir/doc
[ -z "$vimdatadir" ] && vimdatadir=$datarootdir/vim/vimfiles
[ -z "$emacsdatadir" ] && emacsdatadir=$datarootdir/emacs/lisp
[ -z "$nagelfardatadir" ] && nagelfardatadir=$datarootdir/nagelfar
[ -z "$modulefilesdir" ] && modulefilesdir=$prefix/modulefiles
[ -z "$moduleshome" ] && moduleshome=$prefix
# default modulepath based on MODULE_VERSION if versioning enabled
[ -z "$modulepath" ] && [ "$versioning" = 'y' ] && modulepath=${modulefilesdir/#$prefix/$baseprefix\/\$MODULE_VERSION}
[ -z "$modulepath" ] && modulepath=$modulefilesdir
# define libdir64 and libdir32 based on libdir if multilib support enabled
if [ "$multilibsupport" = 'y' ]; then
# shellcheck disable=SC2034
case "$libdir" in
*64*)
libdir64=$libdir ;
libdir32=${libdir/64} ;;
*)
libdir64=${libdir/lib/lib64} ;
libdir32=$libdir ;;
esac
fi
# check feature requirements are met
if [ "$setmodulespath" = 'y' ] && [ -n "$loadedmodules" ]; then
featmesg="As \`setmodulespath' is enabled beware that \`loadedmodules' may be ignored by init scripts"
echo_warning "$featmesg"
fi
if [ -n "$loadedmodules" ] && [ -z "$modulepath" ]; then
featmesg="A value is set for \`loadedmodules' whereas \`modulepath' is not defined"
echo_warning "$featmesg"
fi
# prepare extension library sources if not yet done whether libtclenvmodules
# is enabled or not to create consistent dist in any cases.
if [ ! -e "${progdir}/lib/configure" ]; then
check_requirement autoreconf
echo "--- preparing extension library sources ----------"
pushd "${progdir}/lib" || exit 1
autoreconf -i || exit 1
popd || exit 1
echo "--------------------------------------------------"
fi
# display configuration set
# and build Makefile translation expression
translation_regexp=()
for arg in ${arglist}; do
echo "$arg = ${!arg}"
translation_regexp+=('-e' "s|@${arg}@|${!arg}|g")
done
# configure extension library sources
if [ "$libtclenvmodules" = 'y' ]; then
echo "--- configuring extension library sources --------"
echo "libarglist = ${libarglist[*]}"
pushd "${progdir}/lib" || exit 1
./configure "${libarglist[@]}" || exit 1
popd || exit 1
echo "--------------------------------------------------"
fi
# generate Makefiles
for target in ${targetlist}; do
# escape any '$' in value for Makefile or testsuite interpretation
if [ "${target/Makefile}" = "${target}" ]; then
extra_regexp=()
else
extra_regexp=('-e' 's|\$|\$\$|g')
fi
echo "creating $target"
sed "${translation_regexp[@]}" "${extra_regexp[@]}" "${target}.in" >"$target"
done
exit 0
# vim:set tabstop=3 shiftwidth=3 expandtab autoindent: