Fabian Groffen says: remove alloca() usage #173998.
authorMike Frysinger <vapier@gentoo.org>
Wed, 11 Apr 2007 08:51:31 +0000 (08:51 +0000)
committerMike Frysinger <vapier@gentoo.org>
Wed, 11 Apr 2007 08:51:31 +0000 (08:51 +0000)
Package-Manager: portage-2.1.2.3

sys-devel/gcc-config/ChangeLog
sys-devel/gcc-config/Manifest
sys-devel/gcc-config/files/digest-gcc-config-1.3.16 [new file with mode: 0644]
sys-devel/gcc-config/files/gcc-config-1.3.16 [new file with mode: 0755]
sys-devel/gcc-config/files/wrapper-1.4.8.c [new file with mode: 0644]
sys-devel/gcc-config/gcc-config-1.3.16.ebuild [new file with mode: 0644]

index 530fd6d2a3406d4e2a8c873423fb45ac036b9b30..e2939bebd8bd0e1808ec22c2a06965258a96a51b 100644 (file)
@@ -1,6 +1,12 @@
 # ChangeLog for sys-devel/gcc-config
 # Copyright 1999-2007 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/sys-devel/gcc-config/ChangeLog,v 1.143 2007/03/12 07:00:10 vapier Exp $
+# $Header: /var/cvsroot/gentoo-x86/sys-devel/gcc-config/ChangeLog,v 1.144 2007/04/11 08:51:31 vapier Exp $
+
+*gcc-config-1.3.16 (11 Apr 2007)
+
+  11 Apr 2007; Mike Frysinger <vapier@gentoo.org> +files/gcc-config-1.3.16,
+  +files/wrapper-1.4.8.c, +gcc-config-1.3.16.ebuild:
+  Fabian Groffen says: remove alloca() usage #173998.
 
 *gcc-config-1.3.15-r1 (12 Mar 2007)
 
index daf1454a6f9a1276f1a31120cc211bc4a1c354e9..9fc904864b409fb23571e080d4d7b297e9f774f3 100644 (file)
@@ -13,10 +13,18 @@ AUX gcc-config-1.3.15 19739 RMD160 925e77e8518d4441b80176aaa214e0f2a62c7dbc SHA1
 MD5 246c06f6a1bff855612dc3626ef393e8 files/gcc-config-1.3.15 19739
 RMD160 925e77e8518d4441b80176aaa214e0f2a62c7dbc files/gcc-config-1.3.15 19739
 SHA256 569197230302488f624a4035062d981b0cbd29cbb8018db77ff48d79ed5ebb32 files/gcc-config-1.3.15 19739
+AUX gcc-config-1.3.16 19739 RMD160 7d5fb164e205951285e2268d0a774fc94e8efda4 SHA1 d165501005ae128c253f5639580d191e54933124 SHA256 fabae178d426ce6dc5baf8fd3b72ac15287f93065e33c0f985b71ab1e494a369
+MD5 60272ce47c8576fe170b715e6277e632 files/gcc-config-1.3.16 19739
+RMD160 7d5fb164e205951285e2268d0a774fc94e8efda4 files/gcc-config-1.3.16 19739
+SHA256 fabae178d426ce6dc5baf8fd3b72ac15287f93065e33c0f985b71ab1e494a369 files/gcc-config-1.3.16 19739
 AUX wrapper-1.4.7.c 9837 RMD160 e4feac8cd8746ad7036ec32ff09f1b02d7eceaf8 SHA1 4aee9df408a84b22b4007bc9b74543dd8a6f4fc8 SHA256 f462c49721d291ce3b91c46e5fb8e567d6344f0e359e788301bac07065987744
 MD5 1b19cf481e2777dff9722f36698c3b24 files/wrapper-1.4.7.c 9837
 RMD160 e4feac8cd8746ad7036ec32ff09f1b02d7eceaf8 files/wrapper-1.4.7.c 9837
 SHA256 f462c49721d291ce3b91c46e5fb8e567d6344f0e359e788301bac07065987744 files/wrapper-1.4.7.c 9837
+AUX wrapper-1.4.8.c 9712 RMD160 1210dc111da9955926dc98264991e39489525f20 SHA1 6189891f1577451e34d4f7cc7ada851d63d2f352 SHA256 a45dec68f7a2b4f1d96e83181693afb10cf73b6fbdcd3456055e2bc64bc114e7
+MD5 a2a6606413d1fd68198bc65ee15d1d06 files/wrapper-1.4.8.c 9712
+RMD160 1210dc111da9955926dc98264991e39489525f20 files/wrapper-1.4.8.c 9712
+SHA256 a45dec68f7a2b4f1d96e83181693afb10cf73b6fbdcd3456055e2bc64bc114e7 files/wrapper-1.4.8.c 9712
 DIST compiler-config-2.0.0_rc1.tar.gz 117180 RMD160 dbcd8120139c75f40ae2405746ab2a5f26e810b4 SHA1 3a1a1605dd0e8b59ba5d796c4583244f46f97a03 SHA256 a911a7b0a1184c576500df8530e77823f976dce387001c581ba89ac8edfe30c2
 EBUILD gcc-config-1.3.13-r4.ebuild 1496 RMD160 bb50b68fb945979eea48dba086b1582c32573377 SHA1 f24baf13a4bbe346274f0863d5e7065a8c43ccf1 SHA256 b6bb88fda5494c5f6e22e3ae885cb7b92dec720cd4bbd86132255dcf2984d544
 MD5 1d90be7823ef441090aded734aef408c gcc-config-1.3.13-r4.ebuild 1496
@@ -26,18 +34,22 @@ EBUILD gcc-config-1.3.14.ebuild 1505 RMD160 d2cf06010de226f0272e44692327d0a2a337
 MD5 74895bad7d863231042d8c82649be091 gcc-config-1.3.14.ebuild 1505
 RMD160 d2cf06010de226f0272e44692327d0a2a33718d0 gcc-config-1.3.14.ebuild 1505
 SHA256 0c515b3c2ceeb89b827c8c4b6ffef9ab172a02df2bf3a50b1157b9064fc5b336 gcc-config-1.3.14.ebuild 1505
-EBUILD gcc-config-1.3.15-r1.ebuild 1521 RMD160 d64e122c6b604ebd83d498549da88eb4a6172f2e SHA1 029aec174489c94513d0e6be0bd11ec8b34963ca SHA256 38e46ac0659a79bc8c78b915e125b975eb090062eb51e1d1b5b677a1743d069b
-MD5 b2e9033bd457f781a227e87113fb2106 gcc-config-1.3.15-r1.ebuild 1521
-RMD160 d64e122c6b604ebd83d498549da88eb4a6172f2e gcc-config-1.3.15-r1.ebuild 1521
-SHA256 38e46ac0659a79bc8c78b915e125b975eb090062eb51e1d1b5b677a1743d069b gcc-config-1.3.15-r1.ebuild 1521
+EBUILD gcc-config-1.3.15-r1.ebuild 1516 RMD160 44c02abbd89d19e29838a608dc50b629cb467bac SHA1 0c2d6d129a38ffad660deb1586162da579c5ba95 SHA256 9e0edfaff3ce5d9e312cf997ee9a058a0cfb658a4668525e953b2a83f6abbb86
+MD5 d7ca8bcd98e815c4d0defcdd4af1d553 gcc-config-1.3.15-r1.ebuild 1516
+RMD160 44c02abbd89d19e29838a608dc50b629cb467bac gcc-config-1.3.15-r1.ebuild 1516
+SHA256 9e0edfaff3ce5d9e312cf997ee9a058a0cfb658a4668525e953b2a83f6abbb86 gcc-config-1.3.15-r1.ebuild 1516
+EBUILD gcc-config-1.3.16.ebuild 1538 RMD160 2e8b5fd123dbb516a9696058b7d76bf60983ff3e SHA1 0c91c38f08e28921775bb811d55b7e7bfd57a667 SHA256 e26ed20bae426d0bc6cc6f43ffb71f9dfb10e54abf43e3cdc1c133facdf1cf1d
+MD5 1552112ea3abf26399bea2e739f936bc gcc-config-1.3.16.ebuild 1538
+RMD160 2e8b5fd123dbb516a9696058b7d76bf60983ff3e gcc-config-1.3.16.ebuild 1538
+SHA256 e26ed20bae426d0bc6cc6f43ffb71f9dfb10e54abf43e3cdc1c133facdf1cf1d gcc-config-1.3.16.ebuild 1538
 EBUILD gcc-config-2.0.0_rc1.ebuild 775 RMD160 a41c99cba464ed16040552f329c067326094174d SHA1 4a7a816e8e3d596369a53e127ac8933bb5fe2aa2 SHA256 5be5dcd340934282c6147d8e90dd47a36b9af54416a301855e5f767f021f0a7a
 MD5 d7781cb8103fd03712bf341e79153ed0 gcc-config-2.0.0_rc1.ebuild 775
 RMD160 a41c99cba464ed16040552f329c067326094174d gcc-config-2.0.0_rc1.ebuild 775
 SHA256 5be5dcd340934282c6147d8e90dd47a36b9af54416a301855e5f767f021f0a7a gcc-config-2.0.0_rc1.ebuild 775
-MISC ChangeLog 27384 RMD160 d8acb62c127e15c9aa213ff7d18c1e5f4673f975 SHA1 f3e9492a26ab6b871950a5585cf8752e740ecd71 SHA256 1b496641402d41a81abfa49c419646ed61cd662f4a7920920b12f5ca08569a62
-MD5 41b427222ea59d8ee4710b968302ddef ChangeLog 27384
-RMD160 d8acb62c127e15c9aa213ff7d18c1e5f4673f975 ChangeLog 27384
-SHA256 1b496641402d41a81abfa49c419646ed61cd662f4a7920920b12f5ca08569a62 ChangeLog 27384
+MISC ChangeLog 27602 RMD160 a49e9d978e6034a4df7cb1935eff343a7dd3f705 SHA1 ceeb62f4d79da80012988230766fb40399f0bb4f SHA256 7803760df5cd246a6adee8b3edafd8fc7091c758f467109fe8aa4bfb34299562
+MD5 f852bf357da0607aa0573aea0e2a7976 ChangeLog 27602
+RMD160 a49e9d978e6034a4df7cb1935eff343a7dd3f705 ChangeLog 27602
+SHA256 7803760df5cd246a6adee8b3edafd8fc7091c758f467109fe8aa4bfb34299562 ChangeLog 27602
 MISC metadata.xml 162 RMD160 d002486a43522f2116b1d9d59828c484956d66e2 SHA1 d6b4923897f6ae673b4f93646f5b4ba61d5a2c3c SHA256 65a915d44de1f01d4b7f72d313b4192c38374a9835d24988c00c1e73dca5805a
 MD5 567094e03359ffc1c95af7356395228d metadata.xml 162
 RMD160 d002486a43522f2116b1d9d59828c484956d66e2 metadata.xml 162
@@ -51,13 +63,16 @@ SHA256 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 files/di
 MD5 d41d8cd98f00b204e9800998ecf8427e files/digest-gcc-config-1.3.15-r1 0
 RMD160 9c1185a5c5e9fc54612808977ee8f548b2258d31 files/digest-gcc-config-1.3.15-r1 0
 SHA256 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 files/digest-gcc-config-1.3.15-r1 0
+MD5 d41d8cd98f00b204e9800998ecf8427e files/digest-gcc-config-1.3.16 0
+RMD160 9c1185a5c5e9fc54612808977ee8f548b2258d31 files/digest-gcc-config-1.3.16 0
+SHA256 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 files/digest-gcc-config-1.3.16 0
 MD5 63440bc21fdf46cc94352893f2fd6e3e files/digest-gcc-config-2.0.0_rc1 277
 RMD160 3b08c6248c4f7f8d14ac66ff0fb70bb8c8276c53 files/digest-gcc-config-2.0.0_rc1 277
 SHA256 ba21ae92f613fd0a6f34b3fda34d1d82c6b284c045481b9686b66fd9e373c21e files/digest-gcc-config-2.0.0_rc1 277
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.3 (GNU/Linux)
 
-iD8DBQFF9YXw8bi6rjpTunYRAiLSAJ9Qqs2OL8R7yhEiFm5w3rNIqpADMwCfc0Dq
-AiPNi3R6ITlNFA+1gnraFM4=
-=O5xL
+iD8DBQFGHKG88bi6rjpTunYRAq9nAKDGfHMt01ExAYbXpdtRPCs4WAClJwCguER9
+bpPvQM3VwP3MGH1idOWHu1k=
+=ybeT
 -----END PGP SIGNATURE-----
diff --git a/sys-devel/gcc-config/files/digest-gcc-config-1.3.16 b/sys-devel/gcc-config/files/digest-gcc-config-1.3.16
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/sys-devel/gcc-config/files/gcc-config-1.3.16 b/sys-devel/gcc-config/files/gcc-config-1.3.16
new file mode 100755 (executable)
index 0000000..18ba735
--- /dev/null
@@ -0,0 +1,757 @@
+#!/bin/bash
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-devel/gcc-config/files/gcc-config-1.3.16,v 1.1 2007/04/11 08:51:31 vapier Exp $
+
+trap ":" INT QUIT TSTP
+
+argv0=${0##*/}
+source /etc/init.d/functions.sh || {
+       echo "${argv0}: Could not source /etc/init.d/functions.sh!"
+       exit 1
+}
+umask 022
+
+usage() {
+cat << "USAGE_END"
+Usage: gcc-config [options] [CC Profile]
+Change the current cc/gcc profile, or give info about profiles.
+
+Options:
+  -O, --use-old              Use the old profile if one was selected.
+  -f, --force                Make sure all config files are regenerated.
+  -P, --use-portage-chost    Only set to given profile if its CHOST is the 
+                             same as that set for portage in /etc/make.conf
+                             (or one of other portage config files...).
+  -c, --get-current-profile  Print current used gcc profile.
+  -l, --list-profiles        Print a list of available profiles.
+  -S, --split-profile        Split profiles into their components
+  -E, --print-environ        Print environment that can be used to setup the
+                             current gcc profile, or a specified one.
+  -B, --get-bin-path         Print path where binaries of the given/current
+                             profile are located.
+  -L, --get-lib-path         Print path where libraries of the given/current
+                             profile are located.
+  -X, --get-stdcxx-incdir    Print path where g++ include files of the
+                             given/current profile are located.
+
+Profile names are of the form:  <CHOST>-<gcc version>
+For example:                    i686-pc-linux-gnu-3.2.1
+USAGE_END
+       exit $1
+}
+[[ $# -lt 1 ]] && usage 1
+
+find_path() {
+       [[ -z $1 ]] && return 0
+
+       local fullpath=$(type -P $1)
+       
+       if [[ -x ${fullpath} ]] ; then
+               echo "${fullpath}"
+               return 0
+       fi
+
+       for x in /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin ; do
+               if [[ -x ${x}/$1 ]] && [[ -r ${x}/$1 ]] ; then
+                       echo "${x}/$1"
+                       return 0
+               fi
+       done
+
+       return 0
+}
+
+cmd_setup() {
+       # Sourcing /etc/env.d/gcc/${CC_COMP} is going to mess up
+       # PATH among things...
+       CP=$(find_path cp)
+       RM=$(find_path rm)
+       MV=$(find_path mv)
+       LN=$(find_path ln)
+       CAT=$(find_path cat)
+       ENV=$(find_path env)
+       SED=$(find_path sed)
+       AWK=$(find_path gawk)
+       GREP=$(find_path grep)
+       FIND=$(find_path find)
+       CHMOD=$(find_path chmod)
+       TOUCH=$(find_path touch)
+       PYTHON=$(find_path python)
+       PORTAGEQ=$(find_path portageq)
+       ENV_UPDATE=$(find_path env-update)
+}
+
+try_real_hard_to_find_CHOST() {
+       #
+       # First we read make.conf
+       #
+
+       local varname=$1
+       local conf=${ROOT}/etc/make.conf
+       local ret=$(source "${conf}" 2>/dev/null ; echo ${!varname})
+       if [[ -z ${ret} ]] ; then
+               # newer portage supports spaces between the var and =
+               # CHOST     =  "this-is-retarded"
+               ret=$(eval $(
+                       ${SED} -n \
+                               -e 's:[[:space:]]::g' \
+                               -e '/^CHOST=/p' \
+                               "${conf}"
+                       ) ; echo ${!varname}
+               )
+       fi
+
+       if [[ -n ${ret} ]] ; then
+               echo ${ret}
+               return 0
+       fi
+
+       #
+       # Then we try /etc/env.d/gcc/config
+       #
+       if [[ -s ${ROOT}/etc/env.d/gcc/config ]] ; then
+               ret=$(split_gcc_ver $(eval $(<"${ROOT}"/etc/env.d/gcc/config) ; echo ${CURRENT}))
+               echo ${ret% *}
+       fi
+}
+
+get_real_chost() {
+       [[ -n ${REAL_CHOST} ]] && return 0
+
+       # shortcut for switching compilers in a cross chroot
+       if [[ -n ${CHOST} && ${ROOT} != "/" ]] ; then
+               REAL_CHOST=${CHOST}
+               return 0
+       fi
+
+       # make sure portage isnt broken
+       if ${PYTHON} -V &>/dev/null ; then
+               export REAL_CHOST=$(${ENV} -i ${PORTAGEQ} envvar CHOST 2>/dev/null)
+       else
+               ewarn "Python seems to be broken, attempting to locate CHOST ourselves ..."
+               export REAL_CHOST=$(try_real_hard_to_find_CHOST)
+       fi
+
+       if [[ -z ${REAL_CHOST} ]] ; then
+               eerror "${argv0}: Could not get portage CHOST!"
+               eerror "${argv0}: You should verify that CHOST is set in one of these places:"
+               eerror "${argv0}:  - ${ROOT}/etc/make.conf"
+               eerror "${argv0}:  - active environment"
+               exit 1
+       fi
+}
+
+is_cross_compiler() {
+       get_real_chost
+       [[ ${CC_COMP/${REAL_CHOST}} == ${CC_COMP} ]]
+}
+
+# bool files_exists(search_path, files)
+#      Return shell true if the specified files exist.
+#      Files with relative paths are searched for in search_path.
+#      Both lists are : delimited.
+files_exist() {
+       local p f ret old_IFS
+       local paths=$1 files=$2
+
+       old_IFS=${IFS}
+       export IFS=":"
+
+       ret=0
+       for f in ${files} ; do
+               if [[ ${f} == /* ]] ; then
+                       [[ ! -f ${f} ]] && ret=1 && break
+               else
+                       # make sure the file exists in at least
+                       # one of the specified paths
+                       ret=1
+                       for p in ${paths} ; do
+                               [[ -f ${p}/${f} ]] && ret=0 && break
+                       done
+                       [[ ${ret} == 1 ]] && break
+               fi
+       done
+
+       export IFS=${old_IFS}
+       if [[ ${ret} == 1 ]] ; then
+               ewarn "Could not locate '${f}' in '${paths}'"
+       fi
+       return ${ret}
+}
+
+switch_profile() {
+       local MY_LDPATH=
+       local GCC_PROFILES=
+       local OLD_CC_COMP=
+       local GCC_BIN_PATH=
+
+       if [[ "$(id -u)" -ne 0 ]] ; then
+               eerror "${argv0}: Must be root."
+               exit 1
+       fi
+
+       if is_cross_compiler ; then
+               ebegin "Switching cross-compiler to ${CC_COMP}"
+       else
+               ebegin "Switching native-compiler to ${CC_COMP}"
+       fi
+
+       # Sourcing /etc/env.d/gcc/${CC_COMP} is going to mess up
+       # PATH among things...
+       cmd_setup
+
+       if ! is_cross_compiler ; then
+               # Order our profiles to have the default first ...
+               # We do this so that we can have them ordered with default
+               # first in /etc/ld.so.conf, as the logical is that all
+               # compilers for default CHOST will be used to compile stuff,
+               # and thus we want all their lib paths in /etc/ld.so.conf ...
+               get_real_chost
+               GCC_PROFILES=$(${FIND} "${GCC_ENV_D}" -maxdepth 1 -name "${REAL_CHOST}-*" -a ! -name "${CC_COMP}")
+               GCC_PROFILES="${GCC_ENV_D}/${CC_COMP} ${GCC_PROFILES}"
+
+               # Extract all LDPATH's for our CHOST
+               MY_LDPATH=""
+               for x in ${GCC_PROFILES} ; do
+                       if [[ -f ${x} ]] ; then
+                               source "${x}"
+
+                               # Handle LDPATH's that have multiple directories
+                               local old_IFS=${IFS}
+                               export IFS=":"
+                               local sub_ldpath=
+                               for sub_ldpath in ${LDPATH} ; do
+                                       if [[ -d ${sub_ldpath} ]] ; then
+                                               if [[ ${MY_LDPATH/:${sub_ldpath}} == ${MY_LDPATH} ]] ; then
+                                                       MY_LDPATH="${MY_LDPATH}:${sub_ldpath}"
+                                               fi
+                                       fi
+                               done
+                               export IFS=${old_IFS}
+                       fi
+               done
+               MY_LDPATH="${MY_LDPATH:1}" # trim leading :
+       fi
+
+       # Setup things properly again for this profile
+       unset GCC_SPECS LDPATH
+       source "${GCC_ENV_D}/${CC_COMP}"
+       OLD_CC_COMP=$(get_current_profile)
+       CTARGET=${CTARGET:-${REAL_CHOST}}
+
+       # What kind of env.d entry are we going to generate ?
+       if is_cross_compiler ; then
+               # Only keep PATH/ROOTPATH
+               ${AWK} '/^(PATH|ROOTPATH)=/ {print $0}' \
+                       "${GCC_ENV_D}/${CC_COMP}" > "${ENV_D}/05gcc-${CTARGET}"
+
+               echo "CURRENT=${CC_COMP}" > "${GCC_ENV_D}/config-${CTARGET}"
+       else
+               # Pass all by default
+               ${AWK} '!/^(STDCXX_INCDIR|LDPATH|CC|CXX|CTARGET|GCCBITS|GCC_SPECS)=/ {print $0}' \
+                       "${GCC_ENV_D}/${CC_COMP}" > "${ENV_D}/05gcc"
+               echo "LDPATH=\"${MY_LDPATH}\"" >> "${ENV_D}/05gcc"
+               if [[ -n ${GCC_SPECS} ]] ; then
+                       if files_exist ${MY_LDPATH} ${GCC_SPECS} ; then
+                               echo "GCC_SPECS=\"${GCC_SPECS}\"" >> "${ENV_D}/05gcc"
+                       else
+                               echo
+                               ewarn "Your GCC spec configurations are broken."
+                               ewarn "Please re-emerge gcc."
+                               echo
+                       fi
+               else
+                       # People need to rebuild their gcc or setting GCC_SPECS to
+                       # "" will cause issues again :(
+                       if [[ ${ROOT} != "/" ]] ; then
+                               echo "GCC_SPECS=\"\"" >> "${ENV_D}/05gcc"
+                       else
+                               if ! GCC_SPECS="" /usr/bin/gcc -v &>/dev/null ; then
+                                       echo
+                                       ewarn "Your gcc has a bug with GCC_SPECS."
+                                       ewarn "Please re-emerge gcc."
+                                       ewarn "http://bugs.gentoo.org/68395"
+                                       echo
+                               else
+                                       echo "GCC_SPECS=\"\"" >> "${ENV_D}/05gcc"
+                               fi
+                       fi
+               fi
+
+               echo "CURRENT=${CC_COMP}" > "${GCC_ENV_D}/config"
+       fi
+
+       # Save PATH
+       GCC_BIN_PATH=${PATH}
+       # Fix environment
+       source /etc/profile >& /dev/null
+       umask 022
+       # Find the bin wrapper
+       local wrapper
+       for wrapper in GENTOO_LIBDIR lib lib64 lib32 lib ; do
+               wrapper="${ROOT}usr/${wrapper}/misc/gcc-config"
+               [[ -e ${wrapper} ]] && break
+       done
+
+       # Update the wrappers for this profile
+       for x in {,${CTARGET}-}{cpp,cc,gcc,c++,g++,f77,g77,gcj,gcjh,gfortran,gdc,gdmd} ; do
+               # Obviously don't want to touch native stuff for cross-compilers
+               [[ ${x} != ${CTARGET}-* ]] && is_cross_compiler && continue
+
+               # Make sure we have no stale wrappers
+               ${RM} -f "${ROOT}/usr/bin/${x}"
+               [[ ${x:${#x}-3} == "gcc" || ${x:${#x}-3} == "g++" ]] \
+                       && ${RM} -f "${ROOT}/usr/bin/${x}"{32,64}
+
+               # Only install a wrapper if the binary exists ...
+               # We want to figure out the 'reference file' for each 
+               # wrapper (the binary we're 'wrapping') so that we can 
+               # sync mtimes together.  This makes things like ccache
+               # happy.  See Bug #70548 for more info.
+               local ref
+               case ${x} in
+                       cc)  ref=${ROOT}/${GCC_BIN_PATH}/gcc;;
+                       f77) ref=${ROOT}/${GCC_BIN_PATH}/g77;;
+                       *)   ref=${ROOT}/${GCC_BIN_PATH}/${x};;
+               esac
+               if [[ -x ${ref} ]] ; then
+                       ${CP} -f "${wrapper}" "${ROOT}/usr/bin/${x}"
+                       ${TOUCH} -r "${ref}" "${ROOT}/usr/bin/${x}"
+
+                       # Install 32bit and 64bit wrappers if need be
+                       # This should probably get folded back into the wrapper ...
+                       if [[ ${x:${#x}-3} == "gcc" ]] || [[ ${x:${#x}-3} == "g++" ]] ; then
+                               for bits in ${GCCBITS} ; do
+                                       ${CP} -f "${wrapper}" "${ROOT}/usr/bin/${x}${bits}"
+                               done
+                       fi
+               fi
+       done
+       # legacy cruft, make sure we dont leave it laying around #143205
+       ${RM} -f "${ROOT}/usr/bin/${CTARGET}-cc"
+       # Only install cpp if switching to a native one
+       if ! is_cross_compiler && [[ ${CTARGET} != *-solaris* ]] ; then
+               ${RM} -f "${ROOT}/lib/cpp"
+               ${CP} -f "${wrapper}" "${ROOT}/lib/cpp"
+       fi
+
+       # We need to make sure that libgcc_s.so / libunwind.so make it into /lib.
+       # On many systems (x86/amd64/etc...), this will probably never matter, 
+       # but on other systems (arm/mips/etc...), this is quite critical.
+       # http://bugs.gentoo.org/60190
+       #
+       # The funky move magic is required for proper updating of in-use files.
+       if ! is_cross_compiler ; then
+               # Need to cut out extra paths in multilib case and pray the first path
+               # is the "root" multilib path ... maybe some day change this to use
+               # `gcc -print-file-name` ...
+               LDPATH=${LDPATH%%:*}
+               for multilib in $("${ROOT}/${GCC_BIN_PATH}"/gcc -print-multi-lib); do
+                       multiarg=${multilib#*;}
+                       multiarg=${multiarg/@/-}
+                       multilibdir=${multilib%;*}
+                       libdir="lib/"$("${ROOT}/${GCC_BIN_PATH}"/gcc ${multiarg} -print-multi-os-directory)
+                       if mkdir -p "${ROOT}/${libdir}"/.gcc.config.new ; then
+                               for gcclib in gcc_s unwind ; do
+                                       if [[ -n $(ls "${ROOT}/${LDPATH}/${multilibdir}"/lib${gcclib}.so.* 2>/dev/null) ]]; then
+                                               ${CP} -pP "${ROOT}/${LDPATH}/${multilibdir}"/lib${gcclib}.so.* "${ROOT}/${libdir}"/.gcc.config.new/
+                                               # no need to sanity remove this as the `mv` should take
+                                               # care of it.  we also need this step to be completly atomic
+                                               # for systems that have even `mv` linked against libgcc_s.so.
+                                               # http://bugs.gentoo.org/150257
+                                               #${RM} -f "${ROOT}/${libdir}"/lib${gcclib}.so*
+                                               ${MV} -f "${ROOT}/${libdir}"/.gcc.config.new/* "${ROOT}/${libdir}"/
+                                       fi
+                               done
+                               rmdir "${ROOT}/${libdir}"/.gcc.config.new
+                       fi
+               done
+               unset multilib
+               unset multilibdir
+               unset multiarg
+               unset libdir
+       fi
+
+       if [[ ${ROOT} == "/" ]] && [[ ${OLD_CC_COMP} != ${CC_COMP} || ${FORCE} == "yes" ]] ; then
+               # in case python is broken ...
+               if ! ${ENV_UPDATE} ; then
+                       echo ""
+                       ewarn "env-update failed to work properly; making sure ld.so.conf paths"
+                       ewarn "are setup properly.  Please rerun gcc-config with the -f option."
+                       echo ""
+                       ${GREP} -h ^LDPATH= "${ROOT}"/etc/env.d/05gcc \
+                               | ${SED} -e 's:^LDPATH=::' -e 's:"::g' -e 's|:|\n|g' \
+                               >> /etc/ld.so.conf
+                       ldconfig
+               fi
+       fi
+
+       eend 0
+
+       if [[ ${ROOT} == "/" ]] && [[ ${OLD_CC_COMP} != ${CC_COMP} ]] ; then
+               echo
+               ewarn "If you intend to use the gcc from the new profile in an already"
+               ewarn "running shell, please remember to do:"
+               echo
+               ewarn "  # source /etc/profile"
+               echo
+       fi
+
+       return 0
+}
+
+get_current_profile() {
+       local conf="${GCC_ENV_D}/config"
+       if [[ -n ${CTARGET} ]] ; then
+               conf="${conf}-${CTARGET}"
+       elif [[ -n ${CC_COMP} ]] && is_cross_compiler ; then
+               conf="${conf}-${CC_COMP}"
+       fi
+
+       if [[ ! -f ${conf} ]] ; then
+               eerror "${argv0}: No gcc profile is active!"
+               return 1
+       fi
+
+       source "${conf}"
+
+       if [[ -z ${CURRENT} ]] ; then
+               eerror "${argv0}: No gcc profile is active!"
+               return 1
+       elif [[ ! -f ${GCC_ENV_D}/${CURRENT} ]] ; then
+               eerror "${argv0}: Active gcc profile is invalid!"
+               return 1
+       fi
+
+       echo "${CURRENT}"
+
+       return 0
+}
+
+list_profiles() {
+       local i=1
+
+       if [[ ${ROOT} != "/" ]] ; then
+               echo "Using gcc-config info in ${ROOT}"
+       fi
+
+       if [[ ! -f ${GCC_ENV_D}/config ]] ; then
+               eerror "${argv0}: No gcc profile is active; please select one!"
+       fi
+
+       eval $(grep -s ^CURRENT= "${GCC_ENV_D}"/config)
+       CURRENT_NATIVE=${CURRENT}
+       local target=
+       for x in "${GCC_ENV_D}"/* ; do
+               if [[ -f ${x} ]] && [[ ${x/\/config} == ${x} ]] ; then
+                       source "${x}"
+                       if [[ ${target} != ${CTARGET} ]] ; then
+                               [[ -n ${target} ]] && echo
+                               target=${CTARGET}
+                               CTARGET=""
+                       fi
+
+                       x=${x##*/}
+                       if [[ ${x} == ${CURRENT_NATIVE} ]] ; then
+                               x="${x} ${GOOD}*${NORMAL}"
+                       elif [[ -e ${GCC_ENV_D}/config-${target} ]] ; then
+                               source "${GCC_ENV_D}/config-${target}"
+                               [[ ${x} == ${CURRENT} ]] && x="${x} ${HILITE}*${NORMAL}"
+                       fi
+                       echo " [${i}] ${x}"
+                       ((++i))
+               fi
+       done
+}
+
+print_environ() {
+       local OLDPATH=${PATH}
+       local ENV_CMD=
+       local SET_ELEMENT=
+
+       source "${GCC_ENV_D}/${CC_COMP}"
+
+       case ${SHELL} in
+               */csh|*/tsch)
+                       ENV_CMD="setenv"
+                       SET_ELEMENT=" "
+                       ;;
+               *)
+                       ENV_CMD="export"
+                       SET_ELEMENT="="
+                       ;;
+       esac
+
+       echo "${ENV_CMD} PATH${SET_ELEMENT}\"${PATH}:${OLDPATH}\""
+}
+
+get_bin_path() {
+       if [[ -e ${GCC_ENV_D}/${CC_COMP} ]] ; then
+               source "${GCC_ENV_D}/${CC_COMP}"
+               echo "${PATH}"
+       else
+               echo "no-config"
+               echo "${GCC_ENV_D}/${CC_COMP} doesnt exist" 1>&2
+       fi
+
+       return 0
+}
+
+get_lib_path() {
+       if [[ -e ${GCC_ENV_D}/${CC_COMP} ]] ; then
+               source "${GCC_ENV_D}/${CC_COMP}"
+               echo "${LDPATH}"
+       else
+               echo "no-config"
+               echo "${GCC_ENV_D}/${CC_COMP} doesnt exist" 1>&2
+       fi
+
+       return 0
+}
+
+get_stdcxx_incdir() {
+       if [[ -e ${GCC_ENV_D}/${CC_COMP} ]] ; then
+               source "${GCC_ENV_D}/${CC_COMP}"
+               echo "${LDPATH}/include/${STDCXX_INCDIR}"
+       else
+               echo "no-config"
+               echo "${GCC_ENV_D}/${CC_COMP} doesnt exist" 1>&2
+       fi
+
+       return 0
+}
+
+split_gcc_ver() {
+       # Split up the gcc profile into components:
+       # TARGET-VER[-specs] -> TARGET VER [specs]
+       # arm-linux-3.3.6 -> arm-linux 3.3.6
+       # x86_64-linux-4.0.1-pre1234 -> x86_64-linux 4.0.1-pre1234
+       # sh-linux-3.4.4-hardened -> sh-linux 3.4.4 hardened
+       #
+       # So below we will start at the end and run a small state machine ...
+       # specs [3]
+       #    accept everything
+       # specs -> version transition [3->2]
+       #    when we find a version component
+       # version [2]
+       #    accept only version components (see the regex)
+       # version -> target transition [2->1]
+       #    when we hit a non version component
+       # target [1]
+       #    accept everything we have left
+       #
+       echo "$@" | ${AWK} -F- '
+       function pushit(onme, pushee) {
+               return (onme == "" ? pushee : pushee"-"onme);
+       }
+       {
+               state=3
+               targ=""
+               ver=""
+               spec=""
+               for (i=NF; i > 0; --i) {
+                       if (state >= 2) {
+                               if ($i ~ /^(alpha|beta|pre|rc|p)?[[:digit:].]+$/) {
+                                       ver=pushit(ver, $i)
+                                       state=2
+                               } else if (state == 3)
+                                       spec=pushit(spec, $i)
+                               else
+                                       state=1
+                       }
+                       if (state == 1)
+                               targ = pushit(targ, $i)
+               }
+
+               if (targ == "") {
+                       if (ver == "") {
+                               ver=spec
+                               spec=""
+                       }
+                       targ=ver
+                       ver=""
+               }
+               print targ " " ver (spec != "" ? " " spec : "")
+       }'
+}
+chop_gcc_ver_spec() {
+       local splitTED=$(split_gcc_ver $@) # target ver spec
+       splitTED=${splitTED#* }            # ver spec
+       echo ${splitTED/ /-}               # ver-spec
+}
+
+cmd_setup
+
+NEED_ACTION="yes"
+DOIT="switch_profile"
+CHECK_CHOST="no"
+FORCE="no"
+
+CC_COMP=
+[[ -z ${ROOT} ]] && ROOT="/"
+[[ ${ROOT:0-1} != "/" ]] && ROOT="${ROOT}/"
+ENV_D="${ROOT}etc/env.d"
+GCC_ENV_D="${ENV_D}/gcc"
+
+for x in "$@" ; do
+       case "${x}" in
+               # Only use specified compiler if one is not already selected.
+               -O|--use-old)
+                       if get_current_profile &>/dev/null ; then
+                               CC_COMP=$(get_current_profile)
+                       else
+                               eerror "No profile selected, unable to utilize --use-old"
+                               exit 1
+                       fi
+                       ;;
+               -f|--force)
+                       FORCE="yes"
+                       ;;
+               -P|--use-portage-chost)
+                       CHECK_CHOST="yes"
+                       ;;
+               -c|--get-current-profile)
+                       if [[ ${NEED_ACTION} == "yes" ]] ; then
+                               NEED_ACTION="no"
+                               DOIT="get_current_profile"
+                       fi
+                       ;;
+               -l|--list-profiles)
+                       if [[ ${NEED_ACTION} == "yes" ]] ; then
+                               NEED_ACTION="no"
+                               DOIT="list_profiles"
+                       fi
+                       ;;
+               -S|--split-profile)
+                       if [[ ( $1 != "-S" && $1 != "--split-profile" ) || $# -eq 1 ]] ; then
+                               usage 1
+                       fi
+                       shift # push -S out
+                       for x in "$@" ; do
+                               split_gcc_ver ${x}
+                       done
+                       exit 0
+                       ;;
+               -E|--print-environ)
+                       if [[ ${NEED_ACTION} == "yes" ]] ; then
+                               NEED_ACTION="no"
+                               DOIT="print_environ"
+                       fi
+                       ;;
+               -B|--get-bin-path)
+                       if [[ ${NEED_ACTION} == "yes" ]] ; then
+                               NEED_ACTION="no"
+                               DOIT="get_bin_path"
+                       fi
+                       ;;
+               -L|--get-lib-path)
+                       if [[ ${NEED_ACTION} == "yes" ]] ; then
+                               NEED_ACTION="no"
+                               DOIT="get_lib_path"
+                       fi
+                       ;;
+               -X|--get-stdcxx-incdir)
+                       if [[ ${NEED_ACTION} == "yes" ]] ; then
+                               NEED_ACTION="no"
+                               DOIT="get_stdcxx_incdir"
+                       fi
+                       ;;
+               -h|--help)
+                       usage 0
+                       ;;
+               -V|--version)
+                       echo "gcc-config-PORTAGE-VERSION"
+                       exit 0
+                       ;;
+               -*)
+                       eerror "${argv0}: Invalid switch!  Run ${argv0} without parameters for help."
+                       exit 1
+                       ;;
+               *)
+                       if [[ -z ${CC_COMP} ]] ; then
+                               if [[ -z $(echo ${x} | tr -d '[:digit:]') ]] ; then
+                                       # User gave us a # representing the profile
+                                       i=1
+                                       for y in "${GCC_ENV_D}"/* ; do
+                                               [[ -f ${y} ]] || continue
+                                               [[ ${y/\/config} != ${y} ]] && continue
+
+                                               if [[ -f ${y} ]] && [[ ${x} == ${i} ]] ; then
+                                                       CC_COMP=${y##*/}
+                                                       break
+                                               fi
+                                               ((++i))
+                                       done
+                               else
+                                       # User gave us a full HOST-gccver
+                                       x=${x##*/}
+                                       if [[ ${DOIT} == "get_current_profile" && -z $(ls "${GCC_ENV_D}"/${x}-* 2>/dev/null) ]] || \
+                                          [[ ${DOIT} != "get_current_profile" && ! -f ${GCC_ENV_D}/${x} ]]
+                                       then
+                                               # Maybe they just gave us a gccver ...
+                                               get_real_chost
+                                               if [[ -f ${GCC_ENV_D}/${REAL_CHOST}-${x} ]] ; then
+                                                       x=${REAL_CHOST}-${x}
+                                               else
+                                                       eerror "${argv0}: Could not locate '$x' in '${GCC_ENV_D}/' !"
+                                                       exit 1
+                                               fi
+                                       fi
+                                       CC_COMP=${x}
+                               fi
+                       else
+                               eerror "${argv0}: Too many arguments!  Run ${argv0} without parameters for help."
+                               exit 1
+                       fi
+                       ;;
+       esac
+done
+
+if [[ ${DOIT} == "switch_profile" ]] && [[ -z ${CC_COMP} ]] ; then
+       usage 1
+fi
+
+if [[ -z ${CC_COMP} ]] ; then
+       CC_COMP=$(get_current_profile)
+       if [[ $? -ne 0 ]] ; then
+               echo "${CC_COMP}"
+               list_profiles
+               exit 1
+       fi
+fi
+
+if [[ ${DOIT} != "get_current_profile" ]] ; then
+       GCC_LIB=$(
+               source "${GCC_ENV_D}/${CC_COMP}"
+               echo ${LDPATH} | ${AWK} -F/ '{ print  "/"$2"/"$3"/"$4"/" }'
+       )
+
+       CC_COMP_VERSION=$(chop_gcc_ver_spec ${CC_COMP})
+       CC_COMP_TARGET=${CC_COMP%-${CC_COMP_VERSION}*}
+
+       if [[ ! -d ${ROOT}/${GCC_LIB}/${CC_COMP_TARGET}/${CC_COMP_VERSION} ]]; then
+               CC_COMP_VERSION=${CC_COMP_VERSION%-*}
+       fi
+
+       if [[ ! -d ${ROOT}/${GCC_LIB}/${CC_COMP_TARGET}/${CC_COMP_VERSION} ]] || \
+          [[ ! -f ${GCC_ENV_D}/${CC_COMP} ]]
+       then
+               eerror "${argv0}: Profile does not exist or invalid setting for ${GCC_ENV_D}/${CC_COMP}" 1>&2
+               #exit 1
+       fi
+fi
+
+if [[ ${CHECK_CHOST} == "yes" ]] ; then
+       # Chosen CHOST are not the same as the real CHOST according to
+       # make.conf, and --use-portage-chost option was given, so do nothing
+       get_real_chost
+       CC_COMP_VERSION=$(chop_gcc_ver_spec ${CC_COMP})
+       CC_COMP_TARGET=${CC_COMP:0:${#CC_COMP}-${#CC_COMP_VERSION}-1}
+       [[ ${CC_COMP_TARGET} != ${REAL_CHOST} ]] && exit 0
+fi
+
+eval ${DOIT}
+
+
+# vim:ts=4
diff --git a/sys-devel/gcc-config/files/wrapper-1.4.8.c b/sys-devel/gcc-config/files/wrapper-1.4.8.c
new file mode 100644 (file)
index 0000000..e93b150
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * Copyright 1999-2005 Gentoo Foundation
+ * Distributed under the terms of the GNU General Public License v2
+ * $Header: /var/cvsroot/gentoo-x86/sys-devel/gcc-config/files/wrapper-1.4.8.c,v 1.1 2007/04/11 08:51:31 vapier Exp $
+ * Author: Martin Schlemmer <azarah@gentoo.org>
+ * az's lackey: Mike Frysinger <vapier@gentoo.org>
+ */
+
+#define _REENTRANT
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <libgen.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#define GCC_CONFIG "/usr/bin/gcc-config"
+#define ENVD_BASE  "/etc/env.d/05gcc"
+
+struct wrapper_data {
+       char name[MAXPATHLEN + 1];
+       char fullname[MAXPATHLEN + 1];
+       char bin[MAXPATHLEN + 1];
+       char tmp[MAXPATHLEN + 1];
+       char *path;
+};
+
+static struct {
+       char *alias;
+       char *target;
+} wrapper_aliases[] = {
+       { "cc",  "gcc" },
+       { "f77", "g77" },
+       { NULL, NULL }
+};
+
+static const char *wrapper_strerror(int err, struct wrapper_data *data)
+{
+       /* this app doesn't use threads and strerror
+        * is more portable than strerror_r */
+       strncpy(data->tmp, strerror(err), sizeof(data->tmp));
+       return data->tmp;
+}
+
+static void wrapper_exit(char *msg, ...)
+{
+       va_list args;
+       fprintf(stderr, "gcc-config error: ");
+       va_start(args, msg);
+       vfprintf(stderr, msg, args);
+       va_end(args);
+       exit(1);
+}
+
+/* check_for_target checks in path for the file we are seeking
+ * it returns 1 if found (with data->bin setup), 0 if not and
+ * negative on error
+ */
+static int check_for_target(char *path, struct wrapper_data *data)
+{
+       struct stat sbuf;
+       int result;
+       char str[MAXPATHLEN + 1];
+       size_t len = strlen(path) + strlen(data->name) + 2;
+
+       snprintf(str, len, "%s/%s", path, data->name);
+
+       /* Stat possible file to check that
+        * 1) it exist and is a regular file, and
+        * 2) it is not the wrapper itself, and
+        * 3) it is in a /gcc-bin/ directory tree
+        */
+       result = stat(str, &sbuf);
+       if ((result == 0) && \
+           ((sbuf.st_mode & S_IFREG) || (sbuf.st_mode & S_IFLNK)) && \
+           (strcmp(str, data->fullname) != 0) && \
+           (strstr(str, "/gcc-bin/") != 0)) {
+
+               strncpy(data->bin, str, MAXPATHLEN);
+               data->bin[MAXPATHLEN] = 0;
+               result = 1;
+       } else
+               result = 0;
+
+       return result;
+}
+
+static int find_target_in_path(struct wrapper_data *data)
+{
+       char *token = NULL, *state;
+       char str[MAXPATHLEN + 1];
+
+       if (data->path == NULL) return 0;
+
+       /* Make a copy since strtok_r will modify path */
+       snprintf(str, MAXPATHLEN + 1, "%s", data->path);
+
+       token = strtok_r(str, ":", &state);
+
+       /* Find the first file with suitable name in PATH.  The idea here is
+        * that we do not want to bind ourselfs to something static like the
+        * default profile, or some odd environment variable, but want to be
+        * able to build something with a non default gcc by just tweaking
+        * the PATH ... */
+       while ((token != NULL) && strlen(token)) {
+               if (check_for_target(token, data))
+                       return 1;
+               token = strtok_r(NULL, ":", &state);
+       }
+
+       return 0;
+}
+
+/* find_target_in_envd parses /etc/env.d/05gcc, and tries to
+ * extract PATH, which is set to the current profile's bin
+ * directory ...
+ */
+static int find_target_in_envd(struct wrapper_data *data, int cross_compile)
+{
+       FILE *envfile = NULL;
+       char *token = NULL, *state;
+       char str[MAXPATHLEN + 1];
+       char *strp = str;
+       char envd_file[MAXPATHLEN + 1];
+
+       if (!cross_compile) {
+               snprintf(envd_file, MAXPATHLEN, "%s", ENVD_BASE);
+       } else {
+               char *ctarget, *end = strrchr(data->name, '-');
+               if (end == NULL)
+                       return 0;
+               ctarget = strdup(data->name);
+               ctarget[end - data->name] = '\0';
+               snprintf(envd_file, MAXPATHLEN, "%s-%s", ENVD_BASE, ctarget);
+               free(ctarget);
+       }
+       envfile = fopen(envd_file, "r");
+       if (envfile == NULL)
+               return 0;
+
+       while (0 != fgets(strp, MAXPATHLEN, envfile)) {
+               /* Keep reading ENVD_FILE until we get a line that
+                * starts with 'PATH='
+                */
+               if (((strp) && (strlen(strp) > strlen("PATH=")) &&
+                   !strncmp("PATH=", strp, strlen("PATH=")))) {
+
+                       token = strtok_r(strp, "=", &state);
+                       if ((token != NULL) && strlen(token))
+                               /* The second token should be the value of PATH .. */
+                               token = strtok_r(NULL, "=", &state);
+                       else
+                               goto bail;
+
+                       if ((token != NULL) && strlen(token)) {
+                               strp = token;
+                               /* A bash variable may be unquoted, quoted with " or
+                                * quoted with ', so extract the value without those ..
+                                */
+                               token = strtok(strp, "\n\"\'");
+
+                               while (token != NULL) {
+                                       if (check_for_target(token, data)) {
+                                               fclose(envfile);
+                                               return 1;
+                                       }
+
+                                       token = strtok(NULL, "\n\"\'");
+                               }
+                       }
+               }
+               strp = str;
+       }
+
+bail:
+       fclose(envfile);
+       return (cross_compile ? 0 : find_target_in_envd(data, 1));
+}
+
+static void find_wrapper_target(struct wrapper_data *data)
+{
+       FILE *inpipe = NULL;
+       char str[MAXPATHLEN + 1];
+
+       if (find_target_in_path(data))
+               return;
+
+       if (find_target_in_envd(data, 0))
+               return;
+
+       /* Only our wrapper is in PATH, so
+          get the CC path using gcc-config and
+          execute the real binary in there... */
+       inpipe = popen(GCC_CONFIG " --get-bin-path", "r");
+       if (inpipe == NULL)
+               wrapper_exit(
+                       "Could not open pipe: %s\n",
+                       wrapper_strerror(errno, data));
+
+       if (fgets(str, MAXPATHLEN, inpipe) == 0)
+               wrapper_exit(
+                       "Could not get compiler binary path: %s\n",
+                       wrapper_strerror(errno, data));
+
+       strncpy(data->bin, str, sizeof(data->bin) - 1);
+       data->bin[strlen(data->bin) - 1] = '/';
+       strncat(data->bin, data->name, sizeof(data->bin) - 1);
+       data->bin[MAXPATHLEN] = 0;
+
+       pclose(inpipe);
+}
+
+/* This function modifies PATH to have gcc's bin path appended */
+static void modify_path(struct wrapper_data *data)
+{
+       char *newpath = NULL, *token = NULL, *state;
+       char dname_data[MAXPATHLEN + 1], str[MAXPATHLEN + 1];
+       char *str2 = dname_data, *dname = dname_data;
+       size_t len = 0;
+
+       if (data->bin == NULL)
+               return;
+
+       snprintf(str2, MAXPATHLEN + 1, "%s", data->bin);
+
+       if ((dname = dirname(str2)) == NULL)
+               return;
+
+       if (data->path == NULL)
+               return;
+
+       /* Make a copy since strtok_r will modify path */
+       snprintf(str, MAXPATHLEN + 1, "%s", data->path);
+
+       token = strtok_r(str, ":", &state);
+
+       /* Check if we already appended our bin location to PATH */
+       if ((token != NULL) && strlen(token)) {
+               if (!strcmp(token, dname))
+                       return;
+       }
+
+       len = strlen(dname) + strlen(data->path) + 2 + strlen("PATH") + 1;
+
+       newpath = (char *)malloc(len);
+       if (newpath == NULL)
+               wrapper_exit("out of memory\n");
+       memset(newpath, 0, len);
+
+       snprintf(newpath, len, "PATH=%s:%s", dname, data->path);
+       putenv(newpath);
+}
+
+static char *abi_flags[] = {
+       "-m32", "-m64", "-mabi", NULL
+};
+static char **build_new_argv(char **argv, const char *newflags_str)
+{
+#define MAX_NEWFLAGS 32
+       char *newflags[MAX_NEWFLAGS];
+       char **retargv;
+       unsigned int argc, i;
+       char *state, *flags_tokenized;
+
+       retargv = argv;
+
+       /* make sure user hasn't specified any ABI flags already ...
+        * if they have, lets just get out of here */
+       for (argc = 0; argv[argc]; ++argc)
+               for (i = 0; abi_flags[i]; ++i)
+                       if (!strncmp(argv[argc], abi_flags[i], strlen(abi_flags[i])))
+                               return retargv;
+
+       /* Tokenize the flag list and put it into newflags array */
+       flags_tokenized = strdup(newflags_str);
+       if (flags_tokenized == NULL)
+               return retargv;
+       i = 0;
+       newflags[i] = strtok_r(flags_tokenized, " \t\n", &state);
+       while (newflags[i] != NULL && i < MAX_NEWFLAGS-1)
+               newflags[++i] = strtok_r(NULL, " \t\n", &state);
+
+       /* allocate memory for our spiffy new argv */
+       retargv = (char**)calloc(argc + i + 1, sizeof(char*));
+       /* start building retargv */
+       retargv[0] = argv[0];
+       /* insert the ABI flags first so cmdline always overrides ABI flags */
+       memcpy(retargv+1, newflags, i * sizeof(char*));
+       /* copy over the old argv */
+       if (argc > 1)
+               memcpy(retargv+1+i, argv+1, (argc-1) * sizeof(char*));
+
+       return retargv;
+}
+
+int main(int argc, char *argv[])
+{
+       struct wrapper_data data;
+       size_t size;
+       int i;
+       char **newargv = argv;
+
+       memset(&data, 0, sizeof(data));
+
+       if (getenv("PATH")) {
+               data.path = strdup(getenv("PATH"));
+               if (data.path == NULL)
+                       wrapper_exit("%s wrapper: out of memory\n", argv[0]);
+       }
+
+       /* What should we find ? */
+       strcpy(data.name, basename(argv[0]));
+
+       /* Allow for common compiler names like cc->gcc */
+       for (i = 0; wrapper_aliases[i].alias; ++i)
+               if (!strcmp(data.name, wrapper_aliases[i].alias))
+                       strcpy(data.name, wrapper_aliases[i].target);
+
+       /* What is the full name of our wrapper? */
+       size = sizeof(data.fullname);
+       i = snprintf(data.fullname, size, "/usr/bin/%s", data.name);
+       if ((i == -1) || (i > (int)size))
+               wrapper_exit("invalid wrapper name: \"%s\"\n", data.name);
+
+       find_wrapper_target(&data);
+
+       modify_path(&data);
+
+       if (data.path)
+               free(data.path);
+       data.path = NULL;
+
+       /* Set argv[0] to the correct binary, else gcc can't find internal headers
+        * http://bugs.gentoo.org/show_bug.cgi?id=8132 */
+       argv[0] = data.bin;
+
+       /* If this is g{cc,++}{32,64}, we need to add -m{32,64}
+        * otherwise  we need to add ${CFLAGS_${ABI}}
+        */
+       size = strlen(data.bin) - 2;
+       if(!strcmp(data.bin + size, "32") ) {
+               *(data.bin + size) = '\0';
+               newargv = build_new_argv(argv, "-m32");
+       } else if (!strcmp(data.bin + size, "64") ) {
+               *(data.bin + size) = '\0';
+               newargv = build_new_argv(argv, "-m64");
+       } else if(getenv("ABI")) {
+               char envvar[50];
+
+               /* We use CFLAGS_${ABI} for gcc, g++, g77, etc as they are
+                * the same no matter which compiler we are using.
+                */
+               snprintf(envvar, sizeof(envvar), "CFLAGS_%s", getenv("ABI"));
+
+               if (getenv(envvar)) {
+                       newargv = build_new_argv(argv, getenv(envvar));
+                       if(!newargv)
+                               wrapper_exit("%s wrapper: out of memory\n", argv[0]);
+               }
+       }
+
+       /* Ok, lets do it one more time ... */
+       if (execv(data.bin, newargv) < 0)
+               wrapper_exit("Could not run/locate \"%s\"\n", data.name);
+
+       return 0;
+}
diff --git a/sys-devel/gcc-config/gcc-config-1.3.16.ebuild b/sys-devel/gcc-config/gcc-config-1.3.16.ebuild
new file mode 100644 (file)
index 0000000..34239c8
--- /dev/null
@@ -0,0 +1,52 @@
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-devel/gcc-config/gcc-config-1.3.16.ebuild,v 1.1 2007/04/11 08:51:31 vapier Exp $
+
+inherit flag-o-matic toolchain-funcs multilib
+
+# Version of .c wrapper to use
+W_VER="1.4.8"
+
+DESCRIPTION="Utility to change the gcc compiler being used"
+HOMEPAGE="http://www.gentoo.org/"
+SRC_URI=""
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~sparc-fbsd ~x86 ~x86-fbsd"
+IUSE=""
+
+RDEPEND="!app-admin/eselect-compiler"
+
+S=${WORKDIR}
+
+src_compile() {
+       strip-flags
+       $(tc-getCC) ${CFLAGS} ${LDFLAGS} -Wall -o wrapper \
+               "${FILESDIR}"/wrapper-${W_VER}.c || die "compile wrapper"
+}
+
+src_install() {
+       newbin "${FILESDIR}"/${PN}-${PV} ${PN} || die "install gcc-config"
+       sed -i \
+               -e "s:PORTAGE-VERSION:${PVR}:g" \
+               -e "s:GENTOO_LIBDIR:$(get_libdir):g" \
+               "${D}"/usr/bin/${PN}
+
+       exeinto /usr/$(get_libdir)/misc
+       newexe wrapper gcc-config || die "install wrapper"
+}
+
+pkg_postinst() {
+       # Do we have a valid multi ver setup ?
+       if gcc-config --get-current-profile &>/dev/null ; then
+               # We not longer use the /usr/include/g++-v3 hacks, as
+               # it is not needed ...
+               [[ -L ${ROOT}/usr/include/g++ ]] && rm -f "${ROOT}"/usr/include/g++
+               [[ -L ${ROOT}/usr/include/g++-v3 ]] && rm -f "${ROOT}"/usr/include/g++-v3
+               gcc-config $(/usr/bin/gcc-config --get-current-profile)
+       fi
+
+       # Make sure old versions dont exist #79062
+       rm -f "${ROOT}"/usr/sbin/gcc-config
+}