diff --git a/gcc/genmultilib b/gcc/genmultilib new file mode 100644 index 00000000000..9118ad07b1a --- /dev/null +++ b/gcc/genmultilib @@ -0,0 +1,241 @@ +#!/bin/sh +# Generates multilib.h. +# Copyright (C) 1994 Free Software Foundation, Inc. + +#This file is part of GNU CC. + +#GNU CC 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, or (at your option) +#any later version. + +#GNU CC 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 GNU CC; see the file COPYING. If not, write to +#the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +# This shell script produces a header file which the gcc driver +# program uses to pick which library to use based on the machine +# specific options that it is given. + +# The first argument is a list of sets of options. The elements in +# the list are separated by spaces. Within an element, the options +# are separated by slashes. No leading dash is used on the options. +# Each option in a set is mutually incompatible with all other options +# in the set. + +# The optional second argument is a list of subdirectory names. If +# the second argument is non-empty, there must be as many elements in +# the second argument as there are options in the first argument. The +# elements in the second list are separated by spaces. If the second +# argument is empty, the option names will be used as the directory +# names. + +# The optional third argument is a list of options which are +# identical. The elements in the list are separated by spaces. Each +# element must be of the form OPTION=OPTION. The first OPTION should +# appear in the first argument, and the second should be a synonym for +# it. + +# The output looks like +# #define MULTILIB_MATCHES "\ +# SUBDIRECTORY OPTIONS;\ +# ... +# " +# The SUBDIRECTORY is the subdirectory to use. The OPTIONS are +# multiple options separated by spaces. Each option may start with an +# exclamation point. gcc will consider each line in turn. If none of +# the options beginning with an exclamation point are present, and all +# of the other options are present, that subdirectory will be used. +# The order of the subdirectories is such that they can be created in +# order; that is, a subdirectory is preceded by all its parents. + +# Here is a example (this is simplified from the actual 680x0 case): +# genmultilib "m68000/m68020 msoft-float" "m68000 m68020 msoft-float" +# "m68000=mc68000" +# This produces: +# #define MULTILIB_MATCHES "\ +# m68000/msoft-float m68000 msoft-float;\ +# m68000/msoft-float mc68000 msoft-float;\ +# m68020/msoft-float m68020 msoft-float;\ +# msoft-float !m68000 !mc68000 !m68020 msoft-float;\ +# m68000 m68000 !msoft-float;\ +# m68000 mc60000 !msoft-float;\ +# m68020 m68020 !msoft-float;\ +# . !m68000 !mc68000 !m68020 !msoft-float;\ +# " +# The effect is that `gcc -msoft-float' (for example) will append +# msoft-float to the directory name when searching for libraries or +# startup files, and `gcc -m68000 -msoft-float' (for example) will +# append m68000/msoft-float. + +# Copy the positional parameters into variables. +options=$1 +dirnames=$2 +matches=$3 + +# What we want to do is select all combinations of the sets in +# options. Each combination which includes a set of mutually +# exclusive options must then be output multiple times, once for each +# item in the set. Selecting combinations is a recursive process. +# Since not all versions of sh support functions, we achieve recursion +# by creating a temporary shell script which invokes itself. +rm -f tmpmultilib +cat >tmpmultilib <<\EOF +#!/bin/sh +# This recursive script basically outputs all combinations of its +# input arguments, handling mutually exclusive sets of options by +# repetition. When the script is called, ${initial} is the list of +# options which should appear before all combinations this will +# output. The output looks like a list of subdirectory names with +# leading and trailing slashes. +if [ "$#" != "0" ]; then + first=$1 + shift + for opt in `echo $first | sed -e 's|/| |'g`; do + echo ${initial}${opt}/ + done + ./tmpmultilib $@ + for opt in `echo $first | sed -e 's|/| |'g`; do + initial="${initial}${opt}/" ./tmpmultilib $@ + done +fi +EOF +chmod +x tmpmultilib + +combinations=`initial=/ ./tmpmultilib ${options}` + +rm -f tmpmultilib + +# Construct a sed pattern which will convert option names to directory +# names. +todirnames= +if [ -n "${dirnames}" ]; then + set x ${dirnames} + shift + for set in ${options}; do + for opt in `echo ${set} | sed -e 's|/| |'g`; do + if [ "$1" != "${opt}" ]; then + todirnames="${todirnames} -e s|/${opt}/|/${1}/|g" + fi + shift + done + done +fi + +# Construct a sed pattern which will add negations based on the +# matches. The semicolons are easier than getting the shell to accept +# quoted spaces when expanding a variable. +matchnegations= +for i in ${matches}; do + l=`echo $i | sed -e 's/=.*$//'` + r=`echo $i | sed -e 's/^.*=//'` + matchnegations="${matchnegations} -e s/;!${l};/;!${l};!${r};/" +done + +# We need another recursive shell script to correctly handle positive +# matches. If we are invoked as +# genmultilib "opt1 opt2" "" "opt1=nopt1 opt2=nopt2" +# we must output +# opt1/opt2 opt1 opt2 +# opt1/opt2 nopt1 opt2 +# opt1/opt2 opt1 nopt2 +# opt1/opt2 nopt1 nopt2 +# In other words, we must output all combinations of matches. +rm -f tmpmultilib2 +cat >tmpmultilib2 <<\EOF +#!/bin/sh +# The positional parameters are a list of matches to consider. +# ${dirout} is the directory name and ${optout} is the current list of +# options. +if [ "$#" = "0" ]; then + echo "${dirout} ${optout};\\" +else + first=$1 + shift + dirout="${dirout}" optout="${optout}" ./tmpmultilib2 $@ + l=`echo ${first} | sed -e 's/=.*$//'` + r=`echo ${first} | sed -e 's/^.*=//'` + case " ${optout} " in + *" ${l} "*) + newopt=`echo " ${optout} " | sed -e "s/ ${l} / ${r} /" -e 's/^ //' -e 's/ $//'` + dirout="${dirout}" optout="${newopt}" ./tmpmultilib2 $@ + ;; + esac +fi +EOF +chmod +x tmpmultilib2 + +# We are ready to start output. +echo '#define MULTILIB_SELECT "\' + +# Start with the current directory, which includes only negations. +optout= +for set in ${options}; do + for opt in `echo ${set} | sed -e 's|/| |'g`; do + optout="${optout} !${opt}" + done +done +optout=`echo ${optout} | sed -e 's/^ //'` +if [ -n "${matchnegations}" ]; then + optout=`echo ";${optout};" | sed -e 's/ /;/g' ${matchnegations} -e 's/^;//' -e 's/;$//' -e 's/;/ /g'` +fi +echo ". ${optout};\\" + +# Work over the list of combinations. We have to translate each one +# to use the directory names rather than the option names, we have to +# include the information in matches, and we have to generate the +# correct list of options and negations. +for combo in ${combinations}; do + # Use the directory names rather than the option names. + if [ -n "${todirnames}" ]; then + dirout=`echo ${combo} | sed ${todirnames}` + else + dirout=${combo} + fi + # Remove the leading and trailing slashes. + dirout=`echo ${dirout} | sed -e 's|^/||' -e 's|/$||g'` + + # Look through the options. We must output each option that is + # present, and negate each option that is not present. If an + # element of a set is present, we need not negate the other elements + # of the set. + optout= + for set in ${options}; do + setopts=`echo ${set} | sed -e 's|/| |g'` + found= + for opt in ${setopts}; do + case "${combo}" in + *"/${opt}/"*) + optout="${optout} ${opt}" + found=yes + ;; + esac + done + if [ "${found}" = "" ]; then + for opt in ${setopts}; do + optout="${optout} !${opt}" + done + fi + done + optout=`echo ${optout} | sed -e 's/^ //'` + + # Add any negations of matches. + if [ -n "${matchnegations}" ]; then + optout=`echo ";${optout};" | sed -e 's/ /;/g' ${matchnegations} -e 's/^;//' -e 's/;$//' -e 's/;/ /g'` + fi + + # Output the line with all appropriate matches. + dirout="${dirout}" optout="${optout}" ./tmpmultilib2 ${matches} +done + +rm -f tmpmultilib2 + +# That's it. +echo '"' + +exit 0