This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Configure: add note about nvsize sometimes lying
[metaconfig.git] / U / modified / d_longdbl.U
1 ?RCS: $Id: d_longdbl.U,v $
2 ?RCS:
3 ?RCS: Copyright (c) 1998 Andy Dougherty
4 ?RCS:
5 ?RCS: You may distribute under the terms of either the GNU General Public
6 ?RCS: License or the Artistic License, as specified in the README file.
7 ?RCS:
8 ?RCS: $Log: d_longdbl.U,v $
9 ?RCS:
10 ?MAKE:d_longdbl longdblsize d_ldexpl longdblkind: Compile Setvar Myread \
11         Inlibc run echo cat rm_try test doublesize i_stdlib i_float
12 ?MAKE:  -pick add $@ %<
13 ?S:d_longdbl:
14 ?S:     This variable conditionally defines HAS_LONG_DOUBLE if
15 ?S:     the long double type is supported.
16 ?S:.
17 ?S:d_ldexpl:
18 ?S:     This variable conditionally defines the HAS_LDEXPL symbol, which
19 ?S:     indicates to the C program that the ldexpl() routine is available.
20 ?S:.
21 ?S:longdblsize:
22 ?S:     This variable contains the value of the LONG_DOUBLESIZE symbol, which
23 ?S:     indicates to the C program how many bytes there are in a long double,
24 ?S:     if this system supports long doubles.  Note that this is
25 ?S:     sizeof(long double), which may include unused bytes.
26 ?S:.
27 ?S:longdblkind:
28 ?S:     This variable, if defined, encodes the type of a long double:
29 ?S:     0 = double, 1 = IEEE 754 128-bit big little endian,
30 ?S:     2 = IEEE 754 128-bit big big endian, 3 = x86 80-bit little endian,
31 ?S:     4 = x86 80-bit big endian, 5 = double-double 128-bit little endian,
32 ?S:     6 = double-double 128-bit big endian, -1 = unknown format.
33 ?S:.
34 ?C:HAS_LONG_DOUBLE:
35 ?C:     This symbol will be defined if the C compiler supports long
36 ?C:     doubles.
37 ?C:.
38 ?C:LONG_DOUBLESIZE:
39 ?C:     This symbol contains the size of a long double, so that the
40 ?C:     C preprocessor can make decisions based on it.  It is only
41 ?C:     defined if the system supports long doubles.  Note that this
42 ?C:     is sizeof(long double), which may include unused bytes.
43 ?C:.
44 ?C:HAS_LDEXPL:
45 ?C:     This symbol, if defined, indicates that the ldexpl routine is
46 ?C:     available to shift a long double floating-point number
47 ?C:     by an integral power of 2.
48 ?C:.
49 ?C:LONG_DOUBLEKIND:
50 ?C:     LONG_DOUBLEKIND will be one of
51 ?C:     LONG_DOUBLE_IS_DOUBLE
52 ?C:     LONG_DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN
53 ?C:     LONG_DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN
54 ?C:     LONG_DOUBLE_IS_X86_80_BIT_LITTLE_ENDIAN
55 ?C:     LONG_DOUBLE_IS_X86_80_BIT_BIG_ENDIAN
56 ?C:     LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LITTLE_ENDIAN
57 ?C:     LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BIG_ENDIAN
58 ?C:     LONG_DOUBLE_IS_UNKNOWN_FORMAT
59 ?C:     It is only defined if the system supports long doubles.
60 ?C:.
61 ?H:#$d_ldexpl  HAS_LDEXPL               /**/
62 ?H:#$d_longdbl HAS_LONG_DOUBLE          /**/
63 ?H:?LONG_DOUBLESIZE:#ifdef HAS_LONG_DOUBLE
64 ?H:?LONG_DOUBLESIZE:#define LONG_DOUBLESIZE $longdblsize                /**/
65 ?H:?LONG_DOUBLESIZE:#define LONG_DOUBLEKIND $longdblkind                /**/
66 ?H:?LONG_DOUBLESIZE:#define LONG_DOUBLE_IS_DOUBLE                               0
67 ?H:?LONG_DOUBLESIZE:#define LONG_DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN       1
68 ?H:?LONG_DOUBLESIZE:#define LONG_DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN  2
69 ?H:?LONG_DOUBLESIZE:#define LONG_DOUBLE_IS_X86_80_BIT_LITTLE_ENDIAN             3
70 ?H:?LONG_DOUBLESIZE:#define LONG_DOUBLE_IS_X86_80_BIT_BIG_ENDIAN                4
71 ?H:?LONG_DOUBLESIZE:#define LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LITTLE_ENDIAN   5
72 ?H:?LONG_DOUBLESIZE:#define LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BIG_ENDIAN      6
73 ?H:?LONG_DOUBLESIZE:#define LONG_DOUBLE_IS_UNKNOWN_FORMAT                       -1
74 ?H:?LONG_DOUBLESIZE:#endif
75 ?H:.
76 ?F:!try
77 ?LINT:known LONG_DOUBLE_IS_DOUBLE LONG_DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN
78 ?LINT:known LONG_DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN LONG_DOUBLE_IS_X86_80_BIT_LITTLE_ENDIAN
79 ?LINT:known LONG_DOUBLE_IS_X86_80_BIT_BIG_ENDIAN LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_LITTLE_ENDIAN
80 ?LINT:known LONG_DOUBLE_IS_DOUBLEDOUBLE_128_BIT_BIG_ENDIAN LONG_DOUBLE_IS_UNKNOWN_FORMAT
81 ?LINT:set d_longdbl
82 ?LINT:set d_ldexpl
83 : check for long doubles
84 echo " "
85 echo "Checking to see if you have long double..." >&4
86 echo 'int main() { long double x = 7.0; }' > try.c
87 set try
88 if eval $compile; then
89         val="$define"
90         echo "You have long double."
91 else
92         val="$undef"
93         echo "You do not have long double."
94 fi
95 $rm_try
96 set d_longdbl
97 eval $setvar
98
99 : see if ldexpl exists
100 set ldexpl d_ldexpl
101 eval $inlibc
102
103 @if LONG_DOUBLESIZE || longdblsize
104 : check for length of long double
105 ?X:  Check only if d_longdbl and if longdblsize is not already set.
106 case "${d_longdbl}${longdblsize}" in
107 $define)
108         echo " "
109         echo "Checking to see how big your long doubles are..." >&4
110         $cat >try.c <<'EOCP'
111 #include <stdio.h>
112 int main()
113 {
114         printf("%d\n", sizeof(long double));
115 }
116 EOCP
117         set try
118 ?X:     Don't use compile_ok because some compilers warn you that they have
119 ?X:     'long double' as just 'double'.
120         set try
121         if eval $compile; then
122                 longdblsize=`$run ./try`
123                 echo "Your long doubles are $longdblsize bytes long."
124         else
125                 dflt='8'
126                 echo " "
127                 echo "(I can't seem to compile the test program.  Guessing...)" >&4
128                 rp="What is the size of a long double (in bytes)?"
129                 . ./myread
130                 longdblsize="$ans"
131         fi
132         if $test "X$doublesize" = "X$longdblsize"; then
133                 echo "That isn't any different from an ordinary double."
134                 echo "I'll keep your setting anyway, but you may see some"
135                 echo "harmless compilation warnings."
136         fi
137         ;;
138 esac
139 $rm_try
140 @end
141
142 $echo "Checking the kind of long doubles you have..." >&4
143 case "$d_longdbl" in
144 define)
145 $cat <<EOP >try.c
146 #$i_float I_FLOAT
147 #$i_stdlib I_STDLIB
148 #define LONGDBLSIZE $longdblsize
149 #define DOUBLESIZE $doublesize
150 #ifdef I_FLOAT
151 #include <float.h>
152 #endif
153 #ifdef I_STDLIB
154 #include <stdlib.h>
155 #endif
156 #include <stdio.h>
157 static const long double d = -0.1L;
158 int main() {
159   unsigned const char* b = (unsigned const char*)(&d);
160 #if DOUBLESIZE == LONGDBLSIZE
161   printf("0\n"); /* if it floats like double */
162   exit(0);
163 #endif
164 #if (LDBL_MANT_DIG == 113 || FLT128_MANT_DIG == 113) && LONGDBLSIZE == 16
165   if (b[0] == 0x9A && b[1] == 0x99 && b[15] == 0xBF) {
166     /* IEEE 754 128-bit little-endian */
167     printf("1\n");
168     exit(0);
169   }
170   if (b[0] == 0xBF && b[14] == 0x99 && b[15] == 0x9A) {
171     /* IEEE 128-bit big-endian, e.g. solaris sparc */
172     printf("2\n");
173     exit(0);
174   }
175 #endif
176 /* For alignment 32-bit platforms have the 80 bits in 12 bytes,
177  * while 64-bits platforms have it in 16 bytes. */
178 #if LDBL_MANT_DIG == 64 && (LONGDBLSIZE == 16 || LONGDBLSIZE == 12)
179   if (b[0] == 0xCD && b[9] == 0xBF && b[10] == 0x00) {
180     /* x86 80-bit little-endian, sizeof 12 (ILP32, Solaris x86)
181      * or 16 (LP64, Linux and OS X), 4 or 6 bytes of padding.
182      * Also known as "extended precision". */
183     printf("3\n");
184     exit(0);
185   }
186   if (b[0] == 0xBF && b[9] == 0xCD && b[10] == 0x00) {
187     /* is there ever big-endian 80-bit, really? */
188     printf("4\n");
189     exit(0);
190   }
191 #endif
192 #if (LDBL_MANT_DIG == 106 || LDBL_MANT_DIG == 107) && LONGDBLSIZE == 16
193   /* software "double double", the 106 is 53+53.
194    * but irix thinks it is 107. */
195   if (b[0] == 0x9A && b[7] == 0x3C && b[8] == 0x9A && b[15] == 0xBF) {
196     /* double double 128-bit little-endian,
197      * 9a 99 99 99 99 99 59 3c 9a 99 99 99 99 99 b9 bf */
198     printf("5\n");
199     exit(0);
200   }
201   if (b[0] == 0xBF && b[7] == 0x9A && b[8] == 0x3C && b[15] == 0x9A) {
202     /* double double 128-bit big-endian, e.g. PPC/Power and MIPS:
203      * bf b9 99 99 99 99 99 9a 3c 59 99 99 99 99 99 9a */
204     printf("6\n");
205     exit(0);
206   }
207 #endif
208   printf("-1\n"); /* unknown */
209   exit(0);
210 }
211 EOP
212 set try
213 if eval $compile; then
214     longdblkind=`$run ./try`
215 else
216     longdblkind=-1
217 fi
218 ;;
219 *) longdblkind=0 ;;
220 esac
221 case "$longdblkind" in
222 0) echo "Your long doubles are doubles." >&4 ;;
223 1) echo "You have IEEE 754 128-bit little endian long doubles." >&4 ;;
224 2) echo "You have IEEE 754 128-bit big endian long doubles." >&4 ;;
225 3) echo "You have x86 80-bit little endian long doubles." >& 4 ;;
226 4) echo "You have x86 80-bit big endian long doubles." >& 4 ;;
227 5) echo "You have 128-bit little-endian double-double long doubles." >& 4 ;;
228 6) echo "You have 128-bit big-endian double-double long doubles." >& 4 ;;
229 *) echo "Cannot figure out your long double." >&4 ;;
230 esac
231 $rm_try
232