genmultilib revision 18334
118334Speter#!/bin/sh 
218334Speter# Generates multilib.h.
318334Speter#   Copyright (C) 1994, 1995 Free Software Foundation, Inc.
418334Speter
518334Speter#This file is part of GNU CC.
618334Speter
718334Speter#GNU CC is free software; you can redistribute it and/or modify
818334Speter#it under the terms of the GNU General Public License as published by
918334Speter#the Free Software Foundation; either version 2, or (at your option)
1018334Speter#any later version.
1118334Speter
1218334Speter#GNU CC is distributed in the hope that it will be useful,
1318334Speter#but WITHOUT ANY WARRANTY; without even the implied warranty of
1418334Speter#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1518334Speter#GNU General Public License for more details.
1618334Speter
1718334Speter#You should have received a copy of the GNU General Public License
1818334Speter#along with GNU CC; see the file COPYING.  If not, write to
1918334Speter#the Free Software Foundation, 59 Temple Place - Suite 330,
2018334Speter#Boston, MA 02111-1307, USA.
2118334Speter
2218334Speter# This shell script produces a header file which the gcc driver
2318334Speter# program uses to pick which library to use based on the machine
2418334Speter# specific options that it is given.
2518334Speter
2618334Speter# The first argument is a list of sets of options.  The elements in
2718334Speter# the list are separated by spaces.  Within an element, the options
2818334Speter# are separated by slashes.  No leading dash is used on the options.
2918334Speter# Each option in a set is mutually incompatible with all other options
3018334Speter# in the set.
3118334Speter
3218334Speter# The optional second argument is a list of subdirectory names.  If
3318334Speter# the second argument is non-empty, there must be as many elements in
3418334Speter# the second argument as there are options in the first argument.  The
3518334Speter# elements in the second list are separated by spaces.  If the second
3618334Speter# argument is empty, the option names will be used as the directory
3718334Speter# names.
3818334Speter
3918334Speter# The optional third argument is a list of options which are
4018334Speter# identical.  The elements in the list are separated by spaces.  Each
4118334Speter# element must be of the form OPTION=OPTION.  The first OPTION should
4218334Speter# appear in the first argument, and the second should be a synonym for
4318334Speter# it.  Question marks are replaced with equal signs in both options.
4418334Speter
4518334Speter# The output looks like
4618334Speter#   #define MULTILIB_MATCHES "\
4718334Speter#   SUBDIRECTORY OPTIONS;\
4818334Speter#   ...
4918334Speter#   "
5018334Speter# The SUBDIRECTORY is the subdirectory to use.  The OPTIONS are
5118334Speter# multiple options separated by spaces.  Each option may start with an
5218334Speter# exclamation point.  gcc will consider each line in turn.  If none of
5318334Speter# the options beginning with an exclamation point are present, and all
5418334Speter# of the other options are present, that subdirectory will be used.
5518334Speter# The order of the subdirectories is such that they can be created in
5618334Speter# order; that is, a subdirectory is preceded by all its parents.
5718334Speter
5818334Speter# Here is a example (this is simplified from the actual 680x0 case):
5918334Speter#   genmultilib "m68000/m68020 msoft-float" "m68000 m68020 msoft-float"
6018334Speter#		"m68000=mc68000"
6118334Speter# This produces:
6218334Speter#   #define MULTILIB_SELECT "\
6318334Speter#   . !m68000 !mc68000 !m68020 !msoft-float;\
6418334Speter#   m68000 m68000 !m68020 !msoft-float;\
6518334Speter#   m68000 mc60000 !m68020 !msoft-float;\
6618334Speter#   m68020 !m68000 !mc68000 m68020 !msoft-float;\
6718334Speter#   msoft-float !m68000 !mc68000 !m68020 msoft-float;\
6818334Speter#   m68000/msoft-float m68000 !m68020 msoft-float;\
6918334Speter#   m68000/msoft-float mc68000 !m68020 msoft-float;\
7018334Speter#   m68020/msoft-float !m68000 !mc68000 m68020 msoft-float;\
7118334Speter#   "
7218334Speter# The effect is that `gcc -msoft-float' (for example) will append
7318334Speter# msoft-float to the directory name when searching for libraries or
7418334Speter# startup files, and `gcc -m68000 -msoft-float' (for example) will
7518334Speter# append m68000/msoft-float.
7618334Speter
7718334Speter# Copy the positional parameters into variables.
7818334Speteroptions=$1
7918334Speterdirnames=$2
8018334Spetermatches=$3
8118334Speter
8218334Speter# What we want to do is select all combinations of the sets in
8318334Speter# options.  Each combination which includes a set of mutually
8418334Speter# exclusive options must then be output multiple times, once for each
8518334Speter# item in the set.  Selecting combinations is a recursive process.
8618334Speter# Since not all versions of sh support functions, we achieve recursion
8718334Speter# by creating a temporary shell script which invokes itself.
8818334Speterrm -f tmpmultilib
8918334Spetercat >tmpmultilib <<\EOF
9018334Speter#!/bin/sh
9118334Speter# This recursive script basically outputs all combinations of its
9218334Speter# input arguments, handling mutually exclusive sets of options by
9318334Speter# repetition.  When the script is called, ${initial} is the list of
9418334Speter# options which should appear before all combinations this will
9518334Speter# output.  The output looks like a list of subdirectory names with
9618334Speter# leading and trailing slashes.
9718334Speterif [ "$#" != "0" ]; then
9818334Speter  first=$1
9918334Speter  shift
10018334Speter  for opt in `echo $first | sed -e 's|/| |'g`; do
10118334Speter    echo ${initial}${opt}/
10218334Speter  done
10318334Speter  ./tmpmultilib $@
10418334Speter  for opt in `echo $first | sed -e 's|/| |'g`; do
10518334Speter    initial="${initial}${opt}/" ./tmpmultilib $@
10618334Speter  done
10718334Speterfi
10818334SpeterEOF
10918334Speterchmod +x tmpmultilib
11018334Speter
11118334Spetercombinations=`initial=/ ./tmpmultilib ${options}`
11218334Speter
11318334Speterrm -f tmpmultilib
11418334Speter
11518334Speter# Construct a sed pattern which will convert option names to directory
11618334Speter# names.
11718334Spetertodirnames=
11818334Speterif [ -n "${dirnames}" ]; then
11918334Speter  set x ${dirnames}
12018334Speter  shift
12118334Speter  for set in ${options}; do
12218334Speter    for opt in `echo ${set} | sed -e 's|/| |'g`; do
12318334Speter      if [ "$1" != "${opt}" ]; then
12418334Speter        todirnames="${todirnames} -e s|/${opt}/|/${1}/|g"
12518334Speter      fi
12618334Speter      shift
12718334Speter    done
12818334Speter  done
12918334Speterfi
13018334Speter
13118334Speter# Construct a sed pattern which will add negations based on the
13218334Speter# matches.  The semicolons are easier than getting the shell to accept
13318334Speter# quoted spaces when expanding a variable.
13418334Spetermatchnegations=
13518334Speterfor i in ${matches}; do
13618334Speter  l=`echo $i | sed -e 's/=.*$//' -e 's/?/=/g'`
13718334Speter  r=`echo $i | sed -e 's/^.*=//' -e 's/?/=/g'`
13818334Speter  matchnegations="${matchnegations} -e s/;!${l};/;!${l};!${r};/"
13918334Speterdone
14018334Speter
14118334Speter# We need another recursive shell script to correctly handle positive
14218334Speter# matches.  If we are invoked as
14318334Speter#   genmultilib "opt1 opt2" "" "opt1=nopt1 opt2=nopt2"
14418334Speter# we must output
14518334Speter#   opt1/opt2 opt1 opt2
14618334Speter#   opt1/opt2 nopt1 opt2
14718334Speter#   opt1/opt2 opt1 nopt2
14818334Speter#   opt1/opt2 nopt1 nopt2
14918334Speter# In other words, we must output all combinations of matches.
15018334Speterrm -f tmpmultilib2
15118334Spetercat >tmpmultilib2 <<\EOF
15218334Speter#!/bin/sh
15318334Speter# The positional parameters are a list of matches to consider.
15418334Speter# ${dirout} is the directory name and ${optout} is the current list of
15518334Speter# options.
15618334Speterif [ "$#" = "0" ]; then
15718334Speter  echo "${dirout} ${optout};\\"
15818334Speterelse
15918334Speter  first=$1
16018334Speter  shift
16118334Speter  dirout="${dirout}" optout="${optout}" ./tmpmultilib2 $@
16218334Speter  l=`echo ${first} | sed -e 's/=.*$//' -e 's/?/=/g'`
16318334Speter  r=`echo ${first} | sed -e 's/^.*=//' -e 's/?/=/g'`
16418334Speter  if expr " ${optout} " : ".* ${l} .*" > /dev/null; then
16518334Speter    newopt=`echo " ${optout} " | sed -e "s/ ${l} / ${r} /" -e 's/^ //' -e 's/ $//'`
16618334Speter    dirout="${dirout}" optout="${newopt}" ./tmpmultilib2 $@
16718334Speter  fi
16818334Speterfi
16918334SpeterEOF
17018334Speterchmod +x tmpmultilib2
17118334Speter
17218334Speter# We are ready to start output.
17318334Speterecho '#define MULTILIB_SELECT "\'
17418334Speter
17518334Speter# Start with the current directory, which includes only negations.
17618334Speteroptout=
17718334Speterfor set in ${options}; do
17818334Speter  for opt in `echo ${set} | sed -e 's|/| |'g`; do
17918334Speter    optout="${optout} !${opt}"
18018334Speter  done
18118334Speterdone
18218334Speteroptout=`echo ${optout} | sed -e 's/^ //'`
18318334Speterif [ -n "${matchnegations}" ]; then
18418334Speter  optout=`echo ";${optout};" | sed -e 's/ /;/g' ${matchnegations} -e 's/^;//' -e 's/;$//' -e 's/;/ /g'`
18518334Speterfi
18618334Speterecho ". ${optout};\\"
18718334Speter
18818334Speter# Work over the list of combinations.  We have to translate each one
18918334Speter# to use the directory names rather than the option names, we have to
19018334Speter# include the information in matches, and we have to generate the
19118334Speter# correct list of options and negations.
19218334Speterfor combo in ${combinations}; do
19318334Speter  # Use the directory names rather than the option names.
19418334Speter  if [ -n "${todirnames}" ]; then
19518334Speter    dirout=`echo ${combo} | sed ${todirnames}`
19618334Speter  else
19718334Speter    dirout=${combo}
19818334Speter  fi
19918334Speter  # Remove the leading and trailing slashes.
20018334Speter  dirout=`echo ${dirout} | sed -e 's|^/||' -e 's|/$||g'`
20118334Speter
20218334Speter  # Look through the options.  We must output each option that is
20318334Speter  # present, and negate each option that is not present.
20418334Speter  optout=
20518334Speter  for set in ${options}; do
20618334Speter    setopts=`echo ${set} | sed -e 's|/| |g'`
20718334Speter    for opt in ${setopts}; do
20818334Speter      if expr "${combo} " : ".*/${opt}/.*" > /dev/null; then
20918334Speter	optout="${optout} ${opt}"
21018334Speter      else
21118334Speter	optout="${optout} !${opt}"
21218334Speter      fi
21318334Speter    done
21418334Speter  done
21518334Speter  optout=`echo ${optout} | sed -e 's/^ //'`
21618334Speter
21718334Speter  # Add any negations of matches.
21818334Speter  if [ -n "${matchnegations}" ]; then
21918334Speter    optout=`echo ";${optout};" | sed -e 's/ /;/g' ${matchnegations} -e 's/^;//' -e 's/;$//' -e 's/;/ /g'`
22018334Speter  fi
22118334Speter
22218334Speter  # Output the line with all appropriate matches.
22318334Speter  dirout="${dirout}" optout="${optout}" ./tmpmultilib2 ${matches}
22418334Speterdone
22518334Speter
22618334Speterrm -f tmpmultilib2
22718334Speter
22818334Speter# That's it.
22918334Speterecho '"'
23018334Speter
23118334Speterexit 0
232