aboutsummaryrefslogtreecommitdiff
path: root/gcc/genmultilib
blob: 02206960400f11a23b1d9c30627521526a98492c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#!/bin/sh 
# Generates multilib.h.
#   Copyright (C) 1994, 1995, 1996, 1997 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, 59 Temple Place - Suite 330,
#Boston, MA 02111-1307, 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.  Question marks are replaced with equal signs in both options.

# The optional fourth argument is a list of multilib directory 
# combinations that should not be built.

# The optional fifth argument is a list of options that should be
# used whenever building multilib libraries.

# 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:
#   ". !m68000 !mc68000 !m68020 !msoft-float;",
#   "m68000 m68000 !m68020 !msoft-float;",
#   "m68000 mc60000 !m68020 !msoft-float;",
#   "m68020 !m68000 !mc68000 m68020 !msoft-float;",
#   "msoft-float !m68000 !mc68000 !m68020 msoft-float;",
#   "m68000/msoft-float m68000 !m68020 msoft-float;",
#   "m68000/msoft-float mc68000 !m68020 msoft-float;",
#   "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
exceptions=$4
extra=$5

echo "static char *multilib_raw[] = {"

# 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

# If there exceptions, weed them out now
if [ -n "${exceptions}" ]; then
  rm -f tmpmultilib2
  cat >tmpmultilib2 <<\EOF
#!/bin/sh
# This recursive script weeds out any combination of multilib
# switches that should not be generated.  The output looks like
# a list of subdirectory names with leading and trailing slashes.

  for opt in $@; do
    case "$opt" in
EOF

  for except in ${exceptions}; do
    echo "      /${except}/) : ;;" >> tmpmultilib2
  done

cat >>tmpmultilib2 <<\EOF
      *) echo ${opt};;
    esac
  done
EOF
  chmod +x tmpmultilib2
  combinations=`./tmpmultilib2 ${combinations}`
  rm -f ./tmpmultilib2
fi

# 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

# 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/=.*$//' -e 's/?/=/g'`
  r=`echo ${first} | sed -e 's/^.*=//' -e 's/?/=/g'`
  if expr " ${optout} " : ".* ${l} .*" > /dev/null; then
    newopt=`echo " ${optout} " | sed -e "s/ ${l} / ${r} /" -e 's/^ //' -e 's/ $//'`
    dirout="${dirout}" optout="${newopt}" ./tmpmultilib2 $@
  fi
fi
EOF
chmod +x tmpmultilib2

# 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/^ //'`
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.
  optout=
  for set in ${options}; do
    setopts=`echo ${set} | sed -e 's|/| |g'`
    for opt in ${setopts}; do
      if expr "${combo} " : ".*/${opt}/.*" > /dev/null; then
	optout="${optout} ${opt}"
      else
	optout="${optout} !${opt}"
      fi
    done
  done
  optout=`echo ${optout} | sed -e 's/^ //'`

  # Output the line with all appropriate matches.
  dirout="${dirout}" optout="${optout}" ./tmpmultilib2
done

# Terminate the list of string.
echo "NULL"
echo "};"

# Output all of the matches now as option and that is the same as that, with
# a semicolon trailer.  Include all of the normal options as well.
# Note, the format of the matches is reversed compared
# to what we want, so switch them around.
echo ""
echo "static char *multilib_matches_raw[] = {"
for match in ${matches}; do
  l=`echo ${match} | sed -e 's/=.*$//' -e 's/?/=/g'`
  r=`echo ${match} | sed -e 's/^.*=//' -e 's/?/=/g'`
  echo "\"${r} ${l};\","
done
for set in ${options}; do
  for opt in `echo ${set} | sed -e 's|/| |'g`; do
    echo "\"${opt} ${opt};\","
  done
done
echo "NULL"
echo "};"

# Output the default options now
echo ""
echo "static char *multilib_extra = \"${extra}\";"
rm -f tmpmultilib2

exit 0