#!/usr/bin/env bash
#
# IRIX-MIPSpro-wrapper, Copyright 2008,2009 Stuart Shelton
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# 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 .
#
#
# IRIX-MIPSpro-wrapper: A tool to mangle binutils arguments to
# automagically insert the library paths and includes required
# to build software successfully in a prefix-portage environment.
#
# Required tools:
# /bin/uname, /sbin/hinv, tr, grep, cut, GNU sed, sort, head
#
# Version 20090212.1
#
#set -o xtrace
#
# Try to confirm that essential GNU versions of tools are available...
#
sed -r -h &>/dev/null
case $? in
2) # SGI sed?
echo -e "\nWARNING: SGI sed (rather than GNU sed) seems to first in your \$PATH"
echo " Disabling wrapper"
echo
MIPSPRO_WRAPPER=0
;;
4) # GNU sed?
:
;;
*) # Not a clue!
echo -e "\nWARNING: Unknown sed found - here be dragons"
echo " Please check your \$PATH"
echo
;;
esac
#
# Environment variables which will affect operation...
#
wrapper="${MIPSPRO_WRAPPER:-1}"
debug="${MIPSPRO_DEBUG:-0}"
verbose="${MIPSPRO_VERBOSE:-0}"
allownostd="${MIPSPRO_ALLOWNOSTD:-0}"
mangle="${MIPSPRO_MANGLE:-1}"
permissive="${MIPSPRO_PERMISSIVE:-1}"
abort="${MIPSPRO_ABORT:-0}"
# These should be auto-detected, but you may wish to change
# OLIMIT or MIPSPRO_OPT.
MIPSPRO_PLATFORM="${MIPSPRO_PLATFORM:-$( /bin/uname -m | \
tr [:upper:] [:lower:] )}"
MIPSPRO_CPU="${MIPSPRO_CPU:-$( /sbin/hinv -c processor | \
grep ^CPU | cut -d" " -f 3 | tr [:upper:] [:lower:] )}"
MIPSPRO_ISA="${MIPSPRO_ISA:-mips4}"
MIPSPRO_ABI="${MIPSPRO_ABI:--n32}"
OLIMIT="${OLIMIT:-8192}"
OPTIMISE="${MIPSPRO_OPT:--O2}"
#
# Change nothing below here...
#
tool="$( basename "$0" )"
name="IRIX-MIPSpro-wrapper"
function die() {
echo >&2 "$@"
exit 1
} # die()
function ifverbose() {
(( verbose )) && echo -e "$name: $*" >&2
return $(( ! verbose ))
} # ifverbose()
function ifdebug() {
(( debug )) && echo -e "\n$name$*\n" >&2
return $(( ! debug ))
} # ifdebug()
# FIXME for broken sys-libs/db
test "$tool" = "none" && exit 0
test "$tool" = "ranlib" && exit 0
if test "$USER" != "portage"; then
echo -e "\nWARNING: Not using MIPSpro wrapper for non-portage build!"
echo " Please check your \$PATH"
wrapper=0
fi
test -n "${EPREFIX}" || die "FATAL: \${EPREFIX} is not set, cannot continue"
case $tool in
cc|c89|c99|CC|ld)
(( wrapper )) || exec "/bin/$tool" "$@"
;;
cpp)
ifdebug ": !!BUG!!: Incorrect use of legacy (non-ANSI)/Fortran cpp" >&2
(( wrapper )) || exec /lib/cpp "$@"
;;
*)
die "FATAL: Unknown utility \"$tool\""
;;
esac
# Shortcut attempts to find the version (only)
case "$( printf -- "$@" | sed -r 's/[[:space:]]//g' )" in
-v|-dumpversion|-V)
ifdebug ": Shortcutting wrapper for version-check" >&2
exec /bin/$tool -version
;;
*) ifdebug ": No short-cut" >&2
;;
esac
shopt -s extglob || die "FATAL: Cannot enable shell option 'extglob'," \
"is $( type -p bash ) really bash?"
function main() {
local input=( "$@" )
local -a output[]
ifdebug ": input:\t$tool ${input[@]}"
# NB: The same $output array is used throughout the following sub-functions
# Pass 1 - Join arguments where possible
#
# (This code attempts to do this entirely in-shell, but could be greatly
# simplified through the use of sed...)
#
function pass1() {
local input=( "$@" )
local prefix expect argument
local skip=0 squash=0
unset output
for argument in "${input[@]}"; do
case $argument in
-v|-verbose|--verbose)
verbose=1
;;
esac
if test -n "$prefix"; then
case $prefix in
-Ofast=)
expect="ip*"
squash=1
;;
esac
if test -n "$expect"; then
case $argument in
$expect)
ifverbose "NOTICE: pass1: Found expected" \
"argument sequence $prefix $argument"
if (( squash )); then
prefix="$prefix$argument"
else
ifverbose "INFO: pass1: Adding unsquashable argument $prefix"
output=( "${output[@]}" "${prefix}" )
prefix="$argument"
fi
unset argument
unset expect
squash=0
continue
;;
*)
ifverbose "INFO: pass1: Didn't find" \
"anticipated follow-on argument, adding $prefix"
output=( "${output[@]}" "${prefix}" )
unset prefix
unset expect
squash=0
esac
else
ifdebug ": DEBUG: pass1: Squashing \"$prefix $argument\""
argument="$prefix$argument"
unset prefix
fi
fi
# NB: -L is a synonym for -nostdlib, but -Ldir is the same as -L dir
# so we need to know whether the following argument is an option
# -I has different meanings to the compiler and linker (where it
# must be a stand-alone option) so don't squash it
#
if ! (( skip )); then
case $argument in
-D|-J|-l|-U|-W|-Y)
prefix="$argument"
;;
-G)
prefix="$argument"
expect="[0-9]*"
squash=1
;;
-g)
prefix="$argument"
expect="[0-3s]*"
squash=1
;;
-L)
prefix="$argument"
expect="[^-]*"
squash=1
;;
-Ofast)
prefix="$argument"
expect="=*"
squash=1
;;
--)
skip=1
;;
esac
fi
test -z "$prefix" && output=( "${output[@]}" "${argument}" )
done
test -n "$prefix" && output=( "${output[@]}" "${prefix}" )
} # pass1()
function checkcppflags() {
local input=( "$@" )
local skip argument swallow
local found=1
local result=0
unset output
# Check for unknown arguments...
#
while (( found )); do
found=0
skip=0
swallow=0
if [ -n "$output" ]; then
input=( "${output[@]}" )
unset output
fi
for argument in "${input[@]}"; do
if ! (( skip )) && ! (( swallow )); then
case $argument in
-W*([fbalR])p*([fbalR]),*)
local arguments="$( printf -- "$argument" | \
sed 's!^-W[fbalR]*p[fbalR]*,!!' | \
sed 's!,-! -!g' )"
local newarguments
for newarguments in ${arguments}; do
output=( "${output[@]}" "${newarguments}" )
done
unset newarguments
unset arguments
# Now we have that, let's go around again...
#
found=1
skip=1
;;
--)
output=( "${output[@]}" "${argument}" )
skip=1
;;
# These options are correct for MIPSpro 7.4.4m
# Earlier verions may only support a subset, but there
# should be no false negatives.
#
-C|-D*|-I*|-M|-max_rec_depth\=+([0-9])|-MDtarget|-MDupdate?(,*)|-P|-U*)
output=( "${output[@]}" "${argument}" )
;;
-*)
# Try to catch some common issues with passing
# C(XX)FLAGS to cpp...
case $argument in
*)
if (( permissive )); then
ifverbose "WARNING: cpp: Unrecognised preprocessor option \"$argument\" passed"
output=( "${output[@]}" "${argument}" )
else
ifverbose "WARNING: cpp: Unrecognised preprocessor option \"$argument\" dropped"
(( abort )) && exit 1
fi
result=1
;;
esac
;;
*)
output=( "${output[@]}" "${argument}" )
;;
esac
elif (( swallow )); then
ifverbose "WARNING: cpp: Dropping follow-on argument \"$argument\""
swallow=0
else
output=( "${output[@]}" "${argument}" )
fi
done
done
return $result
} # checkcppflags()
function checkldflags() {
local input=( "$@" )
local argument skip swallow
local found=1
local result=0
unset output
# Check for unknown arguments...
#
while (( found )); do
found=0
skip=0
swallow=0
if [ -n "$output" ]; then
input=( "${output[@]}" )
unset output
fi
for argument in "${input[@]}"; do
if ! (( skip )) && ! (( swallow )); then
case $argument in
-W*([pfbaR])l*([pfbaR]),*)
local arguments="$( printf -- "$argument" | \
sed 's!^-W[pfbaR]*l[pfbaR]*,!!' | \
sed 's!,-! -!g' )"
local newarguments
for newarguments in ${arguments}; do
output=( "${output[@]}" "${newarguments}" )
done
unset newarguments
unset arguments
# Now we have that, let's go around again...
#
found=1
skip=1
;;
--)
output=( "${output[@]}" "${argument}" )
skip=1
;;
-L|-nostdlib)
if (( allownostd )); then
output=( "${output[@]}" "${argument}" )
else
ifverbose "WARNING: ld: $argument passed to $tool, option dropped"
result=1
fi
;;
# These options are correct for MIPSpro 7.4.4m
# Earlier verions may only support a subset, but there should be no false negatives.
# Note that the -V (version) option also attempts to link objects, so shouldn't receive special treatment
#
-B?(direct)|-cckr|-cxx|-l*|-L*|-std|-no_archive|-u| \
-?(not)all|-exclude|-from|-make_cmdfile|-MDignore|-MDupdate?(,*)|-objectlist| \
-aoutkeep|-f|-?(no)info|-m|-M|-show?(_unref)|-split_common|-v|-V|-y*| \
-LD_MSG:*|-allow_missing|-demangle|-?(dont_)warn_unused|-ignore_unresolved|-no_unresolved|-wall|-woff| \
-s|-x| \
-?(n)32|-64|-abi|-call_shared|-elf|-mips[2-4]|-?(non_)shared|-r| \
-d|-D*([0-9])|-elsmap|-elspec|-G*([0-9])|-?(no)ivpad|-LD_LAYOUT:*|-n|-N|-rdata_writable|-rdata_shared| \
-T*([0-9a-fA-F])|-Xlocal|-z| \
-LD_DYNAMIC\:rhf_mips_flags\=*|-?(default_)delay_load|-e|-exact_version|-exports?(_file)| \
-exported_symbol|-fini|-force_load|-full_transitive_link|-hiddens_file|-hidden_symbol|-hides|-I| \
-ignore_minor|-ignore_version|-init|-no_library_replacement|-no_rqs|-?(no_)transitive_link| \
-require_minor|-rpath|-set_version| \
-mmap|-read| \
-allow_jump_at_eop|-no_jump_at_eop| \
-check_registry|-update_registry|-create_registry| \
-_SYSTYPE_SVR4|-o|-VS| \
-Wx,-G)
output=( "${output[@]}" "${argument}" )
;;
-a)
output=( "${output[@]}" "-non_shared" )
;;
-ajeop)
output=( "${output[@]}" "-allow_jump_at_eop" )
;;
-dn)
output=( "${output[@]}" "-non_shared" )
;;
-dy)
output=( "${output[@]}" "-call_shared" )
;;
-h)
output=( "${output[@]}" "-shared" "-soname" )
;;
-hides_files)
output=( "${output[@]}" "-hiddens_file" )
;;
-none)
output=( "${output[@]}" "-notall" )
;;
-o32)
output=( "${output[@]}" "-32" )
;;
-OPT:reorg_common)
output=( "${output[@]}" "-ivpad" )
;;
-rpath,*)
output=( "${output[@]}" "$( printf -- "${argument}" | sed -r 's!-rpath,(.*)$!-rpath \1!' )" )
;;
-soname)
output=( "${output[@]}" "-shared" "${argument}" )
;;
-SYSTYPE_SVR4)
output=( "${output[@]}" "-_SYSTYPE_SVR4" )
;;
-U)
output=( "${output[@]}" "-ignore_unresolved" )
;;
-w)
output=( "${output[@]}" "-wall" )
;;
-Xlocaldata)
output=( "${output[@]}" "-Xlocal" )
;;
-?(no)count|-gpinfo|-quickstart_info| \
-Xnobsschange|-X?(no)sortbss|-X?(nd)block|-Xblockrange|-Xndlocaldata|-X?(no)alignbss|-Xcachemisalign| \
-Xcache?(line)size|-Xdefmovemax|-Xsetalign|-Xdebug)
ifverbose "WARNING: ld: Obsolete option \"$argument\" dropped"
result=1
;;
-*)
# Try to catch some common issues with passing C(XX)FLAGS to ld...
case $argument in
-diag_*)
if (( permissive )); then
ifverbose "WARNING: ld: Invalid linker option \"$argument\" passed"
output=( "${output[@]}" "${argument}" )
else
ifverbose "WARNING: ld: Invalid linker option \"$argument\" dropped"
swallow=1
fi
result=1
;;
*)
if (( permissive )); then
ifverbose "WARNING: ld: Unrecognised linker option \"$argument\" passed"
output=( "${output[@]}" "${argument}" )
else
ifverbose "WARNING: ld: Unrecognised linker option \"$argument\" dropped"
(( abort )) && exit 1
fi
result=1
;;
esac
;;
*)
output=( "${output[@]}" "${argument}" )
;;
esac
elif (( swallow )); then
ifverbose "WARNING: ld: Dropping follow-on to invalid argument \"$argument\""
swallow=0
else
output=( "${output[@]}" "${argument}" )
fi
done
done
return $result
} # checkldflags()
function checkcflags() {
local input=( "$@" )
local argument
local -a progress[]
local skip=0
local result=0
unset output
# Check for unknown arguments...
#
for argument in "${input[@]}"; do
if ! (( skip )); then
case $argument in
-?(-)help)
exec "/bin/$tool" "-help"
;;
-?(-)version)
exec "/bin/$tool" "-version"
;;
--)
output=( "${output[@]}" "${argument}" )
skip=1
;;
-nostdinc)
if (( allownostd )); then
output=( "${output[@]}" "${argument}" )
else
ifverbose "WARNING: cc/CC: $argument passed to $tool, option dropped"
fi
result=1
;;
# These options are correct for MIPSpro 7.4.4m
# Earlier verions may only support a subset, but there should be no false negatives.
#
-?([on])32|-64| \
-all|-anach|-?(x)ansi|-cckr|-ansi[EW]|-apo|-apokeep|-apolist|-ar|-?(no_)auto_include| \
-bigp_off|-bigp_on|-brief_diagnostics| \
-c|-cfront|-clist|-CLIST:*|-common| \
-D*|-DEBUG:*|-diag_error|-diag_remark|-diag_suppress|-diag_warning|-dollar| \
-E|-EP|-P| \
-fb|-fb_create|-fb_opt|-FE:*|-float?(_const)|-fullwarn| \
-G+([0-9])|-g?([023])?(slim)|-I*|-INLINE:*|-IPA:*|-ignore_suffix| \
-J*([0-9])| \
-KPIC| \
-L*|-l*|-LANG:*|-LIST:*|-LNO:*| \
-M|-MDupdate?(,*)|-MDtarget|-mips[1-4]|-MP:*|-mp?(list)| \
-nocpp|-noinline|-none| \
-o|-O?([0-3])|-Ofast?(=ip+([0-9]))|-OPT:*| \
-pca|-pcakeep|-pcalist|-pch|-pedantic|-?(no_)prelink|-pta?(ll)|-ptnone|-ptused|-ptv| \
-quiet_prelink| \
-r|-r[458]k|-r[458]000|-r1[0246]k|-r1[0246]000| \
-S|-?(non_)shared|-show|-signed| \
-TARG:*|-TENV:*|-trapuv| \
-U*|-use_readonly_const|-use_readwrite_const|-use_command|-use_suffix| \
-v|-version| \
-w?(off)| \
-Xcpluscomm|-x| \
-Y|-Y+([pfbalRISL]),*)
output=( "${output[@]}" "${argument}" )
;;
-c99)
if [ "$tool" = "c89" ]; then
ifverbose "WARNING: c89: Cannot run this front-end in C99 mode, \"$argument\" dropped"
result=1
else
output=( "${output[@]}" "${argument}" )
fi
;;
# NB: -W by itself should have been squashed by pass1
-W+([pfbalR]),*|-w?(off))
# We need to be careful here, because we don't want to clobber $output
case $argument in
-W*([fbalR])p*([fbalR]),*)
progress=( "${output[@]}" )
unset output
checkcppflags ${argument}
for arguments in "${output[@]}"; do
local checkedargument="$( printf -- "$arguments" | \
sed -r 's/(^|\s)-/\1-Wp,-/g' | \
sed -r 's/(^|\s)([^-])/\1-Wp,\2/g' )"
local newarguments
for newarguments in ${checkedargument}; do
progress=( "${progress[@]}" "${newarguments}" )
done
unset checkedargument
done
unset arguments
output=( "${progress[@]}" )
unset progress
;;
-W*([pfbaR])l*([pfbaR]),*)
progress=( "${output[@]}" )
unset output
checkldflags ${argument}
for arguments in "${output[@]}"; do
local checkedargument="$( printf -- "$arguments" | \
sed -r 's/(^|\s)-/\1-Wl,-/g' | \
sed -r 's/(^|\s)([^-])/\1-Wl,\2/g' )"
local newarguments
for newarguments in ${checkedargument}; do
progress=( "${progress[@]}" "${newarguments}" )
done
unset checkedargument
done
unset arguments
output=( "${progress[@]}" )
unset progress
;;
*)
# There should be no linker or preprocessor options remaining,
# so we'll silently pass remaining values...
output=( "${output[@]}" "${argument}" )
;;
esac
;;
-|--)
# Pass these through regardless, so we don't get tripped up below...
output=( "${output[@]}" "${argument}" )
;;
-*)
if (( permissive )); then
ifverbose "WARNING: cc/CC: Unrecognised compiler option \"$argument\" passed"
output=( "${output[@]}" "${argument}" )
else
# Some builds throw LDFLAGS and CFLAGS in together, without a -Wl to denote what
# they actually are...
progress=( "${output[@]}" )
unset output
checkldflags "${argument}" &>/dev/null
if (( $? )); then
# No idea what it is ;)
ifverbose "WARNING: cc/CC: Unrecognised compiler option \"$argument\" dropped"
output=( "${progress[@]}" )
unset progress
(( abort )) && exit 1
else
# The argument appears to be an LDFLAG
# ... but don't prepend -Wl, since we don't know whether it takes further
# arguments. Additionally, some options such as '-shared' need to be common
# to compiler and linker.
ifverbose "WARNING: cc/CC: Unrecognised compiler option \"$argument\" passed as ld option"
output=( "${progress[@]}" "${output[@]}" )
unset progress
fi
fi
result=1
;;
*)
output=( "${output[@]}" "${argument}" )
;;
esac
else
output=( "${output[@]}" "${argument}" )
fi
done
unset progress
local lastarg currentarg
for argument in "${output[@]}"; do
currentarg="$argument"
if [ -n "$lastarg" ]; then
case "$lastarg" in
-Wl,-rpath*)
if [ -n "$( printf -- "$lastarg $currentarg" | grep -- '-Wl,-rpath -Wl,' )" ]; then
argument="$( printf -- "$lastarg $currentarg" | sed -r 's!-Wl,-rpath -Wl,!-Wl,-rpath,!g' )"
progress=( "${progress[@]}" "${argument}" )
unset lastarg currentarg
fi
;;
*)
progress=( "${progress[@]}" "${lastarg}" )
unset lastarg
;;
esac
fi
lastarg="$currentarg"
done
[ -n "$currentarg" ] && progress=( "${progress[@]}" "${currentarg}" )
unset lastarg currentarg
output=( "${progress[@]}" )
unset progress
return $result
} # checkcflags()
function checkcxxflags() {
local input=( "$@" )
checkcflags "${input[@]}"
return $?
} # checkcxxflags
# Pass 2 - Set default values and filter out GNU arguments
#
function pass2() {
local input=( "$@" )
local argument skip progress
local skip=0
unset output
for argument in "${input[@]}"; do
(( ! skip )) && case $argument in
--)
skip=1
;;
-32|-o32|-n32|-64)
if test "$argument" != "${MIPSPRO_ABI}"; then
ifverbose "WARNING: pass2: ABI $argument upgraded to ${MIPSPRO_ABI}"
argument="${MIPSPRO_ABI}"
fi
;;
# We don't really support O32 code, so this is entirely spurious
-L/usr/lib)
ifverbose "WARNING: pass2: Library option $argument dropped"
unset argument
;;
-mips?)
if test "$argument" != "-${MIPSPRO_ISA}"; then
ifverbose "WARNING: pass2: ISA $argument upgraded to -${MIPSPRO_ISA}"
argument="-${MIPSPRO_ISA}"
fi
;;
esac
(( ! skip )) && case $tool in
cpp|cc|c89|c99|CC)
case $tool in
cpp)
case $argument in
# FIXME for x11-libs/libX11
-undef)
# This is a hack to work around the libX11 'cpp' checks...
ifverbose "WARNING: pass2: GNU option $argument changed to -Uunix (as libX11 workaround)"
argument="-Uunix"
;;
-traditional)
# This is a hack to work around the libX11 'cpp' checks...
ifverbose "WARNING: pass2: GNU option $argument dropped"
unset argument
continue
;;
esac
;;
cc|c89|c99)
case $argument in
-anach|-ansiE|-ansiW|-?(no_)auto_include|-cfront|-FE:*|-g?([023])slim|-J*([0-9])|-?(no_)prelink|-pch|-pta?(ll)|-ptnone|-ptused|-ptv|-quiet_prelink)
ifverbose "WARNING: pass2: CC-only option $argument dropped"
unset argument
continue
;;
esac
;;
CC)
case $argument in
-?(x)ansi|-cckr|-clist|-CLIST:*|-nocpp|-pca|-pcakeep|-pcalist)
ifverbose "WARNING: pass2: cc-only option $argument dropped"
unset argument
continue
;;
esac
;;
esac
case $argument in
-MD)
ifverbose "WARNING: pass2: -MD does not exist on IRIX, $argument changed to -M -MDupdate"
ifverbose "WARNING: pass2: Output is approximated!"
output=( "${output[@]}" "-M" "-MDupdate" )
unset argument
;;
-MF)
ifverbose "WARNING: pass2: -MF does not exist on IRIX, $argument changed to -MDupdate"
argument="-MDupdate"
;;
-MT)
# Although not documented -MDtarget is a valid cc/CC option!
# (it is documented for cpp, but this is supposed to be for legacy
# non-ANSI usage only...)
ifverbose "WARNING: pass2: -MT does not exist on IRIX, $argument changed to -MDtarget"
argument="-MDtarget"
;;
esac
[ "$tool" != "cpp" ] && case $argument in
-fpic|-fPIC)
ifverbose "WARNING: pass2: -KPIC is default on IRIX, $argument dropped"
unset argument
continue
;;
-g?([023])?(slim))
ifverbose "WARNING: pass2: Debug level $argument dropped"
unset argument
continue
;;
# We generally need our standard includes...
#
-nostdinc)
if ! (( allownostd )); then
ifverbose "WARNING: pass2: Standard includes are required, $argument dropped"
unset argument
continue
fi
;;
# Some programs seem keen on uber-optimisation...
#
-O?([0-3]))
# Remember the lowest value of this argument...
[ "$OPTIMISE" = "-O" ] && OPTIMISE="-O2"
[ "$argument" = "-O" ] && argument="-O2"
ifverbose "WARNING: pass2: Changing optimisation to lowest of \"$OPTIMISE\" and \"$argument\"..."
OPTIMISE="$( for argument in $OPTIMISE $argument; do printf -- "$argument\n"; done | sort -g | head -n 1 )"
unset argument
ifverbose "INFO: pass2: Optimisation level is now $OPTIMISE"
;;
-rdynamic)
# I don't know what the MIPSpro equivalent is!
ifverbose "WARNING: pass2: $argument equivalent is unknown, argument dropped"
unset argument
continue
;;
-W+([pfbalR]),*)
# Do nothing here - it's merely a placeholder to make the
# match below easier...
:
;;
-Werror-implicit-function-declaration)
ifverbose "WARNING: pass2: GNU option $argument changed to -diag_error 1196"
output=( "${output[@]}" "-diag_error 1196" )
unset argument
continue
;;
-W*)
# For -Wall, -Wstrict-prototypes, etc.
#
ifverbose "WARNING: pass2: GNU option $argument changed to -fullwarn"
argument="-fullwarn"
;;
--version)
ifverbose "WARNING: pass2: GNU option $argument changed to -version"
argument="-version"
;;
-v)
# For cosmetic reasons only: -v may not be what was
# intended
#
argument="-show"
;;
esac
;;
ld)
case $argument in
# We generally need our standard libraries...
#
-L|-nostdlib)
if ! (( allownostd )); then
ifverbose "WARNING: pass2: Standard libraries are required, $argument dropped"
unset argument
continue
fi
;;
-version|--version)
argument="-V"
;;
esac
;;
esac
test -n "$argument" && output=( "${output[@]}" "${argument}" )
done
# Common options with different meanings:
# -x
#
case $tool in
cc|c89|c99)
checkcflags "${output[@]}"
;;
CC)
checkcxxflags "${output[@]}"
;;
cpp)
checkcppflags "${output[@]}"
;;
ld)
checkldflags "${output[@]}"
;;
esac
} # pass2()
# Pass 3 - Ensure standard arguments are present
#
function pass3() {
local input=( "$@" )
local prefix options argument item found skip pass quotepass drop quiet
unset output
if (( mangle )); then
case "$tool" in
cc|c99|CC)
options="$options -TARG:isa=${MIPSPRO_ISA}:platform=${MIPSPRO_PLATFORM}:processor=${MIPSPRO_CPU} -${MIPSPRO_CPU}"
options="$options -float_const -use_readonly_const -TENV:zeroinit_in_bss=ON"
options="$options -OPT:fast_io=ON:Olimit=${OLIMIT}:reorg_common=ON:swp=ON"
options="$options -LNO:auto_dist=ON:fusion_peeling_limit=8:gather_scatter=2"
(( verbose )) && \
options="$options -Wl,-v"
options="$options -Wl,-s -Wl,-x -Wl,${MIPSPRO_ABI} -Wl,-${MIPSPRO_ISA}"
options="$options -Wl,-allow_jump_at_eop -Wl,-rpath,${EPREFIX}/usr/lib:${EPREFIX}/lib"
options="$options -L${EPREFIX}/usr/lib -L${EPREFIX}/lib"
options="$options -woff 1174,1183,1185,1552,3968,3970"
options="$options -diag_error 1035"
case "$tool" in
# Preprocessor needs -c99 for headers such as stdint.h
# This may generate incorrect results when compiling with
# c89, but there's no way to detect if this will be the case
# if cpp is invoked directly.
# Likewise, we assume that cc really wants C99 compliance.
cpp|cc|c99)
options="-D__attribute__(x)=\"\" $options"
options="-c99 $options"
;;
CC)
# Enable prelinker concurrent compilation
#options="-J4 $options"
options="$options -FE:eliminate_duplicate_inline_copies:template_in_elf_section"
;;
esac
;;
ld)
prefix="-L${EPREFIX}/usr/lib -L${EPREFIX}/lib"
(( verbose )) && options="$options -v"
options="$options -s -x -allow_jump_at_eop -rpath ${EPREFIX}/usr/lib:${EPREFIX}/lib"
;;
esac
else
case "$tool" in
cc|c99|CC)
(( verbose )) && options="$options -Wl,-v"
options="$options -Wl,-rpath,${EPREFIX}/usr/lib:${EPREFIX}/lib"
options="$options -L${EPREFIX}/usr/lib -L${EPREFIX}/lib"
;;
ld)
prefix="-L${EPREFIX}/usr/lib -L${EPREFIX}/lib"
(( verbose )) && options="$options -v"
options="$options -rpath ${EPREFIX}/usr/lib:${EPREFIX}/lib"
;;
esac
fi
if test "$tool" != "cpp"; then
# -I (alone) is also a linker option, so we can't pass the modified
# include path when $tool is being invoked as a linker.
case "$tool" in
ld)
:
;;
*)
options="$options -I${EPREFIX}/usr/include"
;;
esac
input=( "${MIPSPRO_ABI}" "-${MIPSPRO_ISA}" "${prefix}" "${input[@]}" )
for argument in $options; do
input=( "${input[@]}" "$argument" )
done
# If no optimisation options are set, use ${OPTIMISE}
# NB: -O is equivalent to -O2
# No -O is equivalent to -O0 - so technically this is cheating...
if test "$tool" != "ld"; then
found=0
for argument in "${input[@]}"; do
case $argument in
-O?)
found=1
break
;;
esac
done
(( found )) || input=( "${OPTIMISE}" "${input[@]}" )
fi
fi
local lastarg currentarg
for argument in "${input[@]}"; do
currentarg="$argument"
if [ -n "$lastarg" ]; then
case "$lastarg" in
-diag_*)
if [ -n "$( printf -- "$lastarg $currentarg" | grep -E -- '^-diag_[^ ]+ [0-9]+' )" ]; then
argument="$( printf -- "$lastarg $currentarg" | sed -r 's!^(-diag_[^ ]+) ([0-9]+)!\1 \2!g' )"
output=( "${output[@]}" "${argument}" )
unset lastarg currentarg
fi
;;
-rpath*)
if [ -n "$( printf -- "$lastarg $currentarg" | grep -E -- '^-rpath[, ][^ ]+' )" ]; then
argument="$( printf -- "$lastarg $currentarg" | sed -r 's!^-rpath([, ])([^ ]+)!-rpath \2!g' )"
output=( "${output[@]}" "${argument}" )
unset lastarg currentarg
fi
;;
-woff*)
if [ -n "$( printf -- "$lastarg $currentarg" | grep -E -- '^-woff [0-9,]+' )" ]; then
argument="$( printf -- "$lastarg $currentarg" | sed -r 's!^-woff ([0-9,]+)!-woff \1!g' )"
output=( "${output[@]}" "${argument}" )
unset lastarg currentarg
fi
;;
*)
output=( "${output[@]}" "${lastarg}" )
unset lastarg
;;
esac
fi
lastarg="$currentarg"
done
[ -n "$currentarg" ] && output=( "${output[@]}" "${currentarg}" )
unset lastarg currentarg
input=( "${output[@]}" )
unset output
skip=0
pass=0
quotepass=0
drop=0
quiet=0
for argument in "${input[@]}"; do
# Eliminate duplicate arguments before any optional "--" only
test "$argument" = "--" && skip=1
if ! (( skip )); then
if (( quotepass )); then
pass=0
drop=0
ifverbose "NOTICE: pass3: Quoted string <$argument> passed..."
output=( "${output[@]}" "$argument" )
continue
elif (( pass )); then
pass=0
drop=0
if [ -n "$( printf -- "$argument" | grep -- "^-" )" ]; then
ifverbose "NOTICE: pass3: Passing follow-on option <$argument>"
else
ifverbose "NOTICE: pass3: Passing follow-on argument <$argument>"
fi
output=( "${output[@]}" "$argument" )
continue
elif (( drop )); then
drop=0
if [ -n "$( printf -- "$argument" | grep -- "^-" )" ]; then
ifverbose "NOTICE: pass3: Passing follow-on option <$argument>"
else
ifverbose "NOTICE: pass3: Dropping follow-on argument <$argument>"
fi
unset argument
continue
fi
found=0
case $argument in
-c)
ifverbose "NOTICE: pass3: Option <$argument> will always be passed..."
quiet=1
;;
# FIXME for dev-lang/tcl
-DTCL_PACKAGE_PATH=\"*)
if [ -z "$( printf -- "$argument" | grep '"$' )" ]; then
ifverbose "NOTICE: pass3: Correcting trailing space in define when building Tcl"
argument="$( printf -- "$argument" | sed 's/$/"/' )"
drop=1
fi
;;
-MD*)
ifverbose "NOTICE: pass3: Option <$argument> will always be passed..."
pass=1
quiet=1
;;
-o)
ifverbose "NOTICE: pass3: Option <$argument> will always be passed..."
pass=1
quiet=1
;;
?(-W*([pfbaR])l*([pfbaR]),)-rpath)
pass=1
;;
\"|\'|\`)
ifverbose "NOTICE: pass3: Quote character <$argument> passed..."
quiet=1
;;
*\'*\'|*\"*\"|*\`*\`)
if [ -n "$( printf -- "$argument" | grep -- "^-" )" ]; then
ifverbose "NOTICE: pass3: Option with quoted string <$argument> passed..."
else
ifverbose "NOTICE: pass3: Argument with quoted string <$argument> passed..."
fi
quotedpass=0
quiet=1
;;
\'*|\"*|\`*)
ifverbose "NOTICE: pass3: Start of quoted string <$argument> passed..."
quotedpass=1
quiet=1
;;
*\'|*\"|*\`)
ifverbose "NOTICE: pass3: End of quoted string <$argument> passed..."
quotedpass=0
quiet=1
;;
-*)
for item in "${output[@]}"; do
if test "$item" = "$argument"; then
ifverbose "WARNING: pass3: Dropping duplicate option <$argument>"
found=1
break
fi
done
;;
esac
if ! (( found )); then
(( quiet )) || case $argument in
-*)
ifverbose "NOTICE: pass3: Passing option <$argument>"
;;
*)
[ -n "$argument" ] && ifverbose "NOTICE: pass3: Passing argument <$argument>"
;;
esac
[ -n "$argument" ] && output=( "${output[@]}" "$argument" )
quiet=0
fi
else
case $argument in
-*)
ifverbose "NOTICE: pass3: Passing all remaining, option <$argument>"
;;
*)
[ -n "$argument" ] && ifverbose "NOTICE: pass3: Passing all remaining, argument <$argument>"
;;
esac
[ -n "$argument" ] && output=( "${output[@]}" "$argument" )
fi
done
unset input
for argument in "${output[@]}"; do
if [ -n "$( printf -- "$argument" | grep -E -- '^-diag_[^ ]+ [0-9]+$|^-rpath [^ ]+$|^-woff [0-9,]+' )" ]; then
input=( "${input[@]}" "$( printf -- "$argument" | cut -d" " -f 1 )" "$( printf -- "$argument" | cut -d" " -f 2- )" )
else
input=( "${input[@]}" "${argument}" )
fi
done
output=( "${input[@]}" )
} # pass3()
# At each stage, function output is stored in $output
output=( "${input[@]}" )
unset input
pass1 "${output[@]}"
pass2 "${output[@]}"
# Ensure that we actually have some options left to work with...
[ -n "$( printf -- "${output[@]}" | tr -s [:space:] | grep -v "^ *$" )" ] || exit 1
pass3 "${output[@]}"
# This path is weird, because /bin is actually a symlink to /usr/bin
test "$tool" = "cpp" && tool="../../lib/cpp"
ifdebug ": output:\t/bin/$tool" "${output[@]}"
exec "/bin/$tool" "${output[@]}"
} # main()
ifdebug ": INFO: IMpw: Received input \"$@\""
ifdebug ": INFO: IMpw: Optimising at no more than $OPTIMISE"
main "$@"
exit 0
# vi:set syntax=sh ts=4: