118334Speter#!/bin/sh 
218334Speter# Generates multilib.h.
3132718Skan#   Copyright (C) 1994, 1995, 1996, 1997, 1999, 2002 Free Software Foundation, Inc.
418334Speter
590075Sobrien#This file is part of GCC.
618334Speter
790075Sobrien#GCC is free software; you can redistribute it and/or modify it under
890075Sobrien#the terms of the GNU General Public License as published by the Free
990075Sobrien#Software Foundation; either version 2, or (at your option) any later
1090075Sobrien#version.
1118334Speter
1290075Sobrien#GCC is distributed in the hope that it will be useful, but WITHOUT
1390075Sobrien#ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1490075Sobrien#FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1590075Sobrien#for more details.
1618334Speter
1718334Speter#You should have received a copy of the GNU General Public License
1890075Sobrien#along with GCC; see the file COPYING.  If not, write to the Free
19169689Skan#Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan#02110-1301, 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
2890075Sobrien# are separated by slashes or pipes.  No leading dash is used on the
2990075Sobrien# options.
3090075Sobrien# Each option in a set separated by slashes is mutually incompatible
3190075Sobrien# with all other options
3218334Speter# in the set.
3390075Sobrien# Each option in a set separated by pipes will be used for the library
3490075Sobrien# compilation and any of the options in the set will be sufficient
3590075Sobrien# for it to be triggered.
3618334Speter
3718334Speter# The optional second argument is a list of subdirectory names.  If
3818334Speter# the second argument is non-empty, there must be as many elements in
3918334Speter# the second argument as there are options in the first argument.  The
4018334Speter# elements in the second list are separated by spaces.  If the second
4118334Speter# argument is empty, the option names will be used as the directory
4218334Speter# names.
4318334Speter
4418334Speter# The optional third argument is a list of options which are
4518334Speter# identical.  The elements in the list are separated by spaces.  Each
4618334Speter# element must be of the form OPTION=OPTION.  The first OPTION should
4718334Speter# appear in the first argument, and the second should be a synonym for
4818334Speter# it.  Question marks are replaced with equal signs in both options.
4918334Speter
5051899Sobrien# The optional fourth argument is a list of multilib directory 
5151899Sobrien# combinations that should not be built.
5251899Sobrien
5351899Sobrien# The optional fifth argument is a list of options that should be
5451899Sobrien# used whenever building multilib libraries.
5551899Sobrien
5690075Sobrien# The optional sixth argument is a list of exclusions used internally by
5790075Sobrien# the compiler similar to exceptions. The difference being that exclusions
5890075Sobrien# allow matching default options that genmultilib does not know about and
5990075Sobrien# is done at runtime as opposed to being sorted out at compile time.
6090075Sobrien# Each element in the list is a separate exclusion rule. Each rule is
6190075Sobrien# a list of options (sans preceding '-') separated by a '/'. The options
6290075Sobrien# on the rule are grouped as an AND operation, and all options much match
6390075Sobrien# for the rule to exclude a set. Options can be preceded with a '!' to
6490075Sobrien# match a logical NOT.
6590075Sobrien
66132718Skan# The optional seventh argument is a list of OS subdirectory names.
67132718Skan# The format is either the same as of the second argument, or a set of
68132718Skan# mappings. When it is the same as the second argument, it describes
69132718Skan# the multilib directories using OS conventions, rather than GCC
70132718Skan# conventions.  When it is a set of mappings of the form gccdir=osdir,
71132718Skan# the left side gives the GCC convention and the right gives the
72132718Skan# equivalent OS defined location.  If the osdir part begins with a !,
73132718Skan# the os directory names are used exclusively.  Use the mapping when
74132718Skan# there is no one-to-one equivalence between GCC levels and the OS.
75104752Skan
76104752Skan# The last option should be "yes" if multilibs are enabled.  If it is not
77104752Skan# "yes", all GCC multilib dir names will be ".".
78104752Skan
7918334Speter# The output looks like
8018334Speter#   #define MULTILIB_MATCHES "\
8118334Speter#   SUBDIRECTORY OPTIONS;\
8218334Speter#   ...
8318334Speter#   "
8418334Speter# The SUBDIRECTORY is the subdirectory to use.  The OPTIONS are
8518334Speter# multiple options separated by spaces.  Each option may start with an
8618334Speter# exclamation point.  gcc will consider each line in turn.  If none of
8718334Speter# the options beginning with an exclamation point are present, and all
8818334Speter# of the other options are present, that subdirectory will be used.
8918334Speter# The order of the subdirectories is such that they can be created in
9018334Speter# order; that is, a subdirectory is preceded by all its parents.
9118334Speter
9290075Sobrien# Here is an example (this is from the actual sparc64 case):
9390075Sobrien#   genmultilib 'm64/m32 mno-app-regs|mcmodel=medany' '64 32 alt'
9490075Sobrien#		'mcmodel?medany=mcmodel?medmid' 'm32/mno-app-regs* m32/mcmodel=*'
95104752Skan#		'' 'm32/!m64/mno-app-regs m32/!m64/mcmodel=medany'
96104752Skan#		'../lib64 ../lib32 alt' yes
9718334Speter# This produces:
9890075Sobrien#   ". !m64 !m32 !mno-app-regs !mcmodel=medany;",
99104752Skan#   "64:../lib64 m64 !m32 !mno-app-regs !mcmodel=medany;",
100104752Skan#   "32:../lib32 !m64 m32 !mno-app-regs !mcmodel=medany;",
10190075Sobrien#   "alt !m64 !m32 mno-app-regs mcmodel=medany;",
10290075Sobrien#   "alt !m64 !m32 mno-app-regs !mcmodel=medany;",
10390075Sobrien#   "alt !m64 !m32 !mno-app-regs mcmodel=medany;",
104104752Skan#   "64/alt:../lib64/alt m64 !m32 mno-app-regs mcmodel=medany;",
105104752Skan#   "64/alt:../lib64/alt m64 !m32 mno-app-regs !mcmodel=medany;",
106104752Skan#   "64/alt:../lib64/alt m64 !m32 !mno-app-regs mcmodel=medany;",
10751899Sobrien#
10890075Sobrien# The effect is that `gcc -mno-app-regs' (for example) will append "alt"
10990075Sobrien# to the directory name when searching for libraries or startup files and
11090075Sobrien# `gcc -m32 -mcmodel=medany' (for example) will append "32/alt". Also note
11190075Sobrien# that exclusion above is moot, unless the compiler had a default of -m32,
11290075Sobrien# which would mean that all of the "alt" directories (not the 64/alt ones)
11390075Sobrien# would be ignored (not generated, nor used) since the exclusion also
11490075Sobrien# matches the multilib_default args.
11518334Speter
11618334Speter# Copy the positional parameters into variables.
11718334Speteroptions=$1
11818334Speterdirnames=$2
11918334Spetermatches=$3
12051899Sobrienexceptions=$4
12151899Sobrienextra=$5
12290075Sobrienexclusions=$6
123104752Skanosdirnames=$7
124104752Skanenable_multilib=$8
12518334Speter
12690075Sobrienecho "static const char *const multilib_raw[] = {"
12751899Sobrien
128132718Skanmkdir tmpmultilib.$$ || exit 1
129132718Skan# Use cd ./foo to avoid CDPATH output.
130132718Skancd ./tmpmultilib.$$ || exit 1
131132718Skan
13218334Speter# What we want to do is select all combinations of the sets in
13318334Speter# options.  Each combination which includes a set of mutually
13418334Speter# exclusive options must then be output multiple times, once for each
13518334Speter# item in the set.  Selecting combinations is a recursive process.
13618334Speter# Since not all versions of sh support functions, we achieve recursion
13718334Speter# by creating a temporary shell script which invokes itself.
13818334Speterrm -f tmpmultilib
13918334Spetercat >tmpmultilib <<\EOF
14018334Speter#!/bin/sh
14118334Speter# This recursive script basically outputs all combinations of its
14218334Speter# input arguments, handling mutually exclusive sets of options by
14318334Speter# repetition.  When the script is called, ${initial} is the list of
14418334Speter# options which should appear before all combinations this will
14518334Speter# output.  The output looks like a list of subdirectory names with
14618334Speter# leading and trailing slashes.
14718334Speterif [ "$#" != "0" ]; then
14818334Speter  first=$1
14918334Speter  shift
15090075Sobrien  case "$first" in
15190075Sobrien  *\|*)
15290075Sobrien    all=${initial}`echo $first | sed -e 's_|_/_'g`
15390075Sobrien    first=`echo $first | sed -e 's_|_ _'g`
15490075Sobrien    echo ${all}/
15590075Sobrien    initial="${initial}${all}/" ./tmpmultilib $@
15690075Sobrien    ./tmpmultilib $first $@ | grep -v "^${all}"
15790075Sobrien    ;;
15890075Sobrien  *)
15990075Sobrien    for opt in `echo $first | sed -e 's|/| |'g`; do
16090075Sobrien      echo ${initial}${opt}/
16190075Sobrien    done
16290075Sobrien    ./tmpmultilib $@
16390075Sobrien    for opt in `echo $first | sed -e 's|/| |'g`; do
16490075Sobrien      initial="${initial}${opt}/" ./tmpmultilib $@
16590075Sobrien    done
16690075Sobrien  esac
16718334Speterfi
16818334SpeterEOF
16918334Speterchmod +x tmpmultilib
17018334Speter
17118334Spetercombinations=`initial=/ ./tmpmultilib ${options}`
17218334Speter
17351899Sobrien# If there exceptions, weed them out now
17451899Sobrienif [ -n "${exceptions}" ]; then
17551899Sobrien  cat >tmpmultilib2 <<\EOF
17651899Sobrien#!/bin/sh
17751899Sobrien# This recursive script weeds out any combination of multilib
17851899Sobrien# switches that should not be generated.  The output looks like
17951899Sobrien# a list of subdirectory names with leading and trailing slashes.
18051899Sobrien
18151899Sobrien  for opt in $@; do
18251899Sobrien    case "$opt" in
18351899SobrienEOF
18451899Sobrien
18551899Sobrien  for except in ${exceptions}; do
18651899Sobrien    echo "      /${except}/) : ;;" >> tmpmultilib2
18751899Sobrien  done
18851899Sobrien
18951899Sobriencat >>tmpmultilib2 <<\EOF
19051899Sobrien      *) echo ${opt};;
19151899Sobrien    esac
19251899Sobrien  done
19351899SobrienEOF
19451899Sobrien  chmod +x tmpmultilib2
19551899Sobrien  combinations=`./tmpmultilib2 ${combinations}`
19651899Sobrienfi
19751899Sobrien
19818334Speter# Construct a sed pattern which will convert option names to directory
19918334Speter# names.
20018334Spetertodirnames=
20118334Speterif [ -n "${dirnames}" ]; then
20218334Speter  set x ${dirnames}
20318334Speter  shift
20418334Speter  for set in ${options}; do
20590075Sobrien    for opts in `echo ${set} | sed -e 's|/| |'g`; do
20690075Sobrien      patt="/"
20790075Sobrien      for opt in `echo ${opts} | sed -e 's_|_ _'g`; do
20890075Sobrien        if [ "$1" != "${opt}" ]; then
20990075Sobrien          todirnames="${todirnames} -e s|/${opt}/|/${1}/|g"
21090075Sobrien	  patt="${patt}${1}/"
21190075Sobrien	  if [ "${patt}" != "/${1}/" ]; then
21290075Sobrien	    todirnames="${todirnames} -e s|${patt}|/${1}/|g"
21390075Sobrien          fi
21490075Sobrien        fi
21590075Sobrien      done
21618334Speter      shift
21718334Speter    done
21818334Speter  done
21918334Speterfi
22018334Speter
221104752Skan# Construct a sed pattern which will convert option names to OS directory
222104752Skan# names.
223104752Skantoosdirnames=
224132718Skandefaultosdirname=
225104752Skanif [ -n "${osdirnames}" ]; then
226104752Skan  set x ${osdirnames}
227104752Skan  shift
228132718Skan  while [ $# != 0 ] ; do
229132718Skan    case "$1" in
230132718Skan      .=*)
231132718Skan        defaultosdirname=`echo $1 | sed 's|^.=|:|'`
232132718Skan	shift
233132718Skan	;;
234132718Skan      *=*)
235132718Skan	patt=`echo $1 | sed -e 's|=|/$=/|'`
236132718Skan        toosdirnames="${toosdirnames} -e s=^/${patt}/="
237132718Skan	shift
238132718Skan        ;;
239132718Skan      *)
240132718Skan        break
241132718Skan	;;
242132718Skan    esac
243132718Skan  done
244132718Skan  
245132718Skan  if [ $# != 0 ]; then
246132718Skan    for set in ${options}; do
247132718Skan      for opts in `echo ${set} | sed -e 's|/| |'g`; do
248132718Skan        patt="/"
249132718Skan        for opt in `echo ${opts} | sed -e 's_|_ _'g`; do
250132718Skan          if [ "$1" != "${opt}" ]; then
251132718Skan            toosdirnames="${toosdirnames} -e s|/${opt}/|/${1}/|g"
252132718Skan	    patt="${patt}${1}/"
253132718Skan	    if [ "${patt}" != "/${1}/" ]; then
254132718Skan	      toosdirnames="${toosdirnames} -e s|${patt}|/${1}/|g"
255132718Skan            fi
256104752Skan          fi
257132718Skan        done
258132718Skan        shift
259104752Skan      done
260104752Skan    done
261132718Skan  fi
262104752Skanfi
263104752Skan
26418334Speter# We need another recursive shell script to correctly handle positive
26518334Speter# matches.  If we are invoked as
26618334Speter#   genmultilib "opt1 opt2" "" "opt1=nopt1 opt2=nopt2"
26718334Speter# we must output
26818334Speter#   opt1/opt2 opt1 opt2
26918334Speter#   opt1/opt2 nopt1 opt2
27018334Speter#   opt1/opt2 opt1 nopt2
27118334Speter#   opt1/opt2 nopt1 nopt2
27218334Speter# In other words, we must output all combinations of matches.
27318334Speterrm -f tmpmultilib2
27418334Spetercat >tmpmultilib2 <<\EOF
27518334Speter#!/bin/sh
27618334Speter# The positional parameters are a list of matches to consider.
27718334Speter# ${dirout} is the directory name and ${optout} is the current list of
27818334Speter# options.
27918334Speterif [ "$#" = "0" ]; then
28051899Sobrien  echo "\"${dirout} ${optout};\","
28118334Speterelse
28218334Speter  first=$1
28318334Speter  shift
28418334Speter  dirout="${dirout}" optout="${optout}" ./tmpmultilib2 $@
28518334Speter  l=`echo ${first} | sed -e 's/=.*$//' -e 's/?/=/g'`
28618334Speter  r=`echo ${first} | sed -e 's/^.*=//' -e 's/?/=/g'`
28718334Speter  if expr " ${optout} " : ".* ${l} .*" > /dev/null; then
28818334Speter    newopt=`echo " ${optout} " | sed -e "s/ ${l} / ${r} /" -e 's/^ //' -e 's/ $//'`
28918334Speter    dirout="${dirout}" optout="${newopt}" ./tmpmultilib2 $@
29018334Speter  fi
29118334Speterfi
29218334SpeterEOF
29318334Speterchmod +x tmpmultilib2
29418334Speter
29518334Speter# Start with the current directory, which includes only negations.
29618334Speteroptout=
29718334Speterfor set in ${options}; do
29890075Sobrien  for opt in `echo ${set} | sed -e 's_[/|]_ _g'`; do
29918334Speter    optout="${optout} !${opt}"
30018334Speter  done
30118334Speterdone
30218334Speteroptout=`echo ${optout} | sed -e 's/^ //'`
303132718Skanecho "\".${defaultosdirname} ${optout};\","
30418334Speter
30518334Speter# Work over the list of combinations.  We have to translate each one
30618334Speter# to use the directory names rather than the option names, we have to
30718334Speter# include the information in matches, and we have to generate the
30818334Speter# correct list of options and negations.
30918334Speterfor combo in ${combinations}; do
31018334Speter  # Use the directory names rather than the option names.
31118334Speter  if [ -n "${todirnames}" ]; then
31218334Speter    dirout=`echo ${combo} | sed ${todirnames}`
31318334Speter  else
314169689Skan    dirout=`echo ${combo} | sed -e 's/=/-/g'`
31518334Speter  fi
31618334Speter  # Remove the leading and trailing slashes.
31718334Speter  dirout=`echo ${dirout} | sed -e 's|^/||' -e 's|/$||g'`
31818334Speter
319104752Skan  # Use the OS directory names rather than the option names.
320104752Skan  if [ -n "${toosdirnames}" ]; then
321104752Skan    osdirout=`echo ${combo} | sed ${toosdirnames}`
322104752Skan    # Remove the leading and trailing slashes.
323104752Skan    osdirout=`echo ${osdirout} | sed -e 's|^/||' -e 's|/$||g'`
324104752Skan    if [ "x${enable_multilib}" != xyes ]; then
325104752Skan      dirout=".:${osdirout}"
326132718Skan      disable_multilib=yes
327104752Skan    else
328132718Skan      case "${osdirout}" in
329132718Skan        !*)
330132718Skan	  dirout=`echo ${osdirout} | sed 's/^!//'`
331132718Skan	  ;;
332132718Skan	*)
333132718Skan	  dirout="${dirout}:${osdirout}"
334132718Skan	  ;;
335132718Skan      esac
336104752Skan    fi
337104752Skan  else
338104752Skan    if [ "x${enable_multilib}" != xyes ]; then
339104752Skan      # genmultilib with --disable-multilib should be
340104752Skan      # called with '' '' '' '' '' '' '' no
341104752Skan      # if MULTILIB_OSDIRNAMES is empty.
342104752Skan      exit 1
343104752Skan    fi
344104752Skan  fi
345104752Skan
34618334Speter  # Look through the options.  We must output each option that is
34718334Speter  # present, and negate each option that is not present.
34818334Speter  optout=
34918334Speter  for set in ${options}; do
35090075Sobrien    setopts=`echo ${set} | sed -e 's_[/|]_ _g'`
35118334Speter    for opt in ${setopts}; do
35218334Speter      if expr "${combo} " : ".*/${opt}/.*" > /dev/null; then
35318334Speter	optout="${optout} ${opt}"
35418334Speter      else
35518334Speter	optout="${optout} !${opt}"
35618334Speter      fi
35718334Speter    done
35818334Speter  done
35918334Speter  optout=`echo ${optout} | sed -e 's/^ //'`
36018334Speter
36118334Speter  # Output the line with all appropriate matches.
36251899Sobrien  dirout="${dirout}" optout="${optout}" ./tmpmultilib2
36318334Speterdone
36418334Speter
36551899Sobrien# Terminate the list of string.
36651899Sobrienecho "NULL"
36751899Sobrienecho "};"
36851899Sobrien
36951899Sobrien# Output all of the matches now as option and that is the same as that, with
37051899Sobrien# a semicolon trailer.  Include all of the normal options as well.
37151899Sobrien# Note, the format of the matches is reversed compared
37251899Sobrien# to what we want, so switch them around.
37351899Sobrienecho ""
37490075Sobrienecho "static const char *const multilib_matches_raw[] = {"
37551899Sobrienfor match in ${matches}; do
37651899Sobrien  l=`echo ${match} | sed -e 's/=.*$//' -e 's/?/=/g'`
37751899Sobrien  r=`echo ${match} | sed -e 's/^.*=//' -e 's/?/=/g'`
37851899Sobrien  echo "\"${r} ${l};\","
37951899Sobriendone
38051899Sobrienfor set in ${options}; do
38190075Sobrien  for opt in `echo ${set} | sed -e 's_[/|]_ _'g`; do
38251899Sobrien    echo "\"${opt} ${opt};\","
38351899Sobrien  done
38451899Sobriendone
38551899Sobrienecho "NULL"
38651899Sobrienecho "};"
38751899Sobrien
38851899Sobrien# Output the default options now
38951899Sobrienecho ""
39090075Sobrienecho "static const char *multilib_extra = \"${extra}\";"
39190075Sobrien
39290075Sobrien# Output the exclusion rules now
39390075Sobrienecho ""
39490075Sobrienecho "static const char *const multilib_exclusions_raw[] = {"
39590075Sobrienfor rule in ${exclusions}; do
39690075Sobrien  s=`echo ${rule} | sed -e 's,/, ,g'`
39790075Sobrien  echo "\"${s};\","
39890075Sobriendone
39990075Sobrienecho "NULL"
40090075Sobrienecho "};"
40190075Sobrien
402104752Skan# Output the options now
403104752Skanmoptions=`echo ${options} | sed -e 's,[ 	][ 	]*, ,g'`
404104752Skanecho ""
405104752Skanecho "static const char *multilib_options = \"${moptions}\";"
406104752Skan
407132718Skan# Finally output the disable flag if specified
408132718Skanif [ "x${disable_multilib}" = xyes ]; then
409132718Skan  echo ""
410132718Skan  echo "#define DISABLE_MULTILIB  1"
411132718Skanfi
41218334Speter
413132718Skancd ..
414132718Skanrm -r tmpmultilib.$$
415132718Skan
41618334Speterexit 0
417