This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
e67bea08f9c643198a12c6b8e020388ea880fdb8
[metaconfig.git] / U / perl / longdblfio.U
1 ?RCS: $Id$
2 ?RCS:
3 ?RCS: Copyright (c) 1999 Jarkko Hietaniemi
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 ?MAKE:d_PRIfldbl sPRIfldbl d_PRIgldbl d_PRIFUldbl sPRIGUldbl d_PRIEUldbl \
9         sPRIgldbl d_PRIeldbl sPRIeldbl sPRIFUldbl d_PRIGUldbl sPRIEUldbl \
10         d_SCNfldbl \
11         sSCNfldbl doublekind: \
12         d_longdbl longdblsize doublesize uselongdouble test echo cat rm_try \
13         Setvar Compile run i_stdlib osname gccversion ccflags
14 ?MAKE:  -pick add $@ %<
15 ?S:doublekind:
16 ?S:     This variable, if defined, encodes the type of a double:
17 ?S:      1 = IEEE 754 32-bit big little endian,
18 ?S:      2 = IEEE 754 32-bit big big endian,
19 ?S:      3 = IEEE 754 64-bit big little endian,
20 ?S:      4 = IEEE 754 64-bit big big endian,
21 ?S:      5 = IEEE 754 128-bit big little endian,
22 ?S:      6 = IEEE 754 128-bit big big endian,
23 ?S:      7 = IEEE 754 64-bit big mixed endian le-be,
24 ?S:      8 = IEEE 754 64-bit big mixed endian be-le,
25 ?S:     -1 = unknown format.
26 ?S:.
27 ?S:d_PRIfldbl:
28 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
29 ?S:     indicates that stdio has a symbol to print long doubles.
30 ?S:.
31 ?S:d_PRIgldbl:
32 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
33 ?S:     indicates that stdio has a symbol to print long doubles.
34 ?S:.
35 ?S:d_PRIeldbl:
36 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
37 ?S:     indicates that stdio has a symbol to print long doubles.
38 ?S:.
39 ?S:d_PRIFUldbl:
40 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
41 ?S:     indicates that stdio has a symbol to print long doubles.
42 ?S:     The 'U' in the name is to separate this from d_PRIfldbl so that even
43 ?S:     case-blind systems can see the difference.
44 ?S:.
45 ?S:d_PRIGUldbl:
46 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
47 ?S:     indicates that stdio has a symbol to print long doubles.
48 ?S:     The 'U' in the name is to separate this from d_PRIgldbl so that even
49 ?S:     case-blind systems can see the difference.
50 ?S:.
51 ?S:d_PRIEUldbl:
52 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
53 ?S:     indicates that stdio has a symbol to print long doubles.
54 ?S:     The 'U' in the name is to separate this from d_PRIeldbl so that even
55 ?S:     case-blind systems can see the difference.
56 ?S:.
57 ?S:d_SCNfldbl:
58 ?S:     This variable conditionally defines the PERL_PRIfldbl symbol, which
59 ?S:     indicates that stdio has a symbol to scan long doubles.
60 ?S:.
61 ?S:sPRIfldbl:
62 ?S:     This variable, if defined, contains the string used by stdio to
63 ?S:     format long doubles (format 'f') for output.
64 ?S:.
65 ?S:sPRIgldbl:
66 ?S:     This variable, if defined, contains the string used by stdio to
67 ?S:     format long doubles (format 'g') for output.
68 ?S:.
69 ?S:sPRIeldbl:
70 ?S:     This variable, if defined, contains the string used by stdio to
71 ?S:     format long doubles (format 'e') for output.
72 ?S:.
73 ?S:sPRIFUldbl:
74 ?S:     This variable, if defined, contains the string used by stdio to
75 ?S:     format long doubles (format 'F') for output.
76 ?S:     The 'U' in the name is to separate this from sPRIfldbl so that even
77 ?S:     case-blind systems can see the difference.
78 ?S:.
79 ?S:sPRIGUldbl:
80 ?S:     This variable, if defined, contains the string used by stdio to
81 ?S:     format long doubles (format 'G') for output.
82 ?S:     The 'U' in the name is to separate this from sPRIgldbl so that even
83 ?S:     case-blind systems can see the difference.
84 ?S:.
85 ?S:sPRIEUldbl:
86 ?S:     This variable, if defined, contains the string used by stdio to
87 ?S:     format long doubles (format 'E') for output.
88 ?S:     The 'U' in the name is to separate this from sPRIeldbl so that even
89 ?S:     case-blind systems can see the difference.
90 ?S:.
91 ?S:sSCNfldbl:
92 ?S:     This variable, if defined, contains the string used by stdio to
93 ?S:     format long doubles (format 'f') for input.
94 ?S:.
95 ?C:PERL_PRIfldbl:
96 ?C:     This symbol, if defined, contains the string used by stdio to
97 ?C:     format long doubles (format 'f') for output.
98 ?C:.
99 ?C:PERL_PRIgldbl:
100 ?C:     This symbol, if defined, contains the string used by stdio to
101 ?C:     format long doubles (format 'g') for output.
102 ?C:.
103 ?C:PERL_PRIeldbl:
104 ?C:     This symbol, if defined, contains the string used by stdio to
105 ?C:     format long doubles (format 'e') for output.
106 ?C:.
107 ?C:PERL_PRIFldbl:
108 ?C:     This symbol, if defined, contains the string used by stdio to
109 ?C:     format long doubles (format 'f') for output.
110 ?C:.
111 ?C:PERL_PRIGldbl:
112 ?C:     This symbol, if defined, contains the string used by stdio to
113 ?C:     format long doubles (format 'g') for output.
114 ?C:.
115 ?C:PERL_PRIEldbl:
116 ?C:     This symbol, if defined, contains the string used by stdio to
117 ?C:     format long doubles (format 'e') for output.
118 ?C:.
119 ?C:PERL_SCNfldbl:
120 ?C:     This symbol, if defined, contains the string used by stdio to
121 ?C:     format long doubles (format 'f') for input.
122 ?C:.
123 ?C:DOUBLEKIND:
124 ?C:     DOUBLEKIND will be one of
125 ?C:     DOUBLE_IS_IEEE_754_32_BIT_LITTLE_ENDIAN
126 ?C:     DOUBLE_IS_IEEE_754_32_BIT_BIG_ENDIAN
127 ?C:     DOUBLE_IS_IEEE_754_64_BIT_LITTLE_ENDIAN
128 ?C:     DOUBLE_IS_IEEE_754_64_BIT_BIG_ENDIAN
129 ?C:     DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN
130 ?C:     DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN
131 ?C:     DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_LE_BE
132 ?C:     DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_BE_LE
133 ?C:     DOUBLE_IS_UNKNOWN_FORMAT
134 ?C:.
135 ?LINT:known DOUBLE_IS_IEEE_754_32_BIT_LITTLE_ENDIAN
136 ?LINT:known DOUBLE_IS_IEEE_754_32_BIT_BIG_ENDIAN
137 ?LINT:known DOUBLE_IS_IEEE_754_64_BIT_LITTLE_ENDIAN
138 ?LINT:known DOUBLE_IS_IEEE_754_64_BIT_BIG_ENDIAN
139 ?LINT:known DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN
140 ?LINT:known DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN
141 ?LINT:known DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_LE_BE
142 ?LINT:known DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_BE_LE
143 ?LINT:known DOUBLE_IS_UNKNOWN_FORMAT
144 ?H:#define DOUBLEKIND $doublekind               /**/
145 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_32_BIT_LITTLE_ENDIAN  1
146 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_32_BIT_BIG_ENDIAN     2
147 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_64_BIT_LITTLE_ENDIAN  3
148 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_64_BIT_BIG_ENDIAN     4
149 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_128_BIT_LITTLE_ENDIAN 5
150 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_128_BIT_BIG_ENDIAN    6
151 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_LE_BE     7
152 ?H:?DOUBLEKIND:#define DOUBLE_IS_IEEE_754_64_BIT_MIXED_ENDIAN_BE_LE     8
153 ?H:?DOUBLEKIND:#define DOUBLE_IS_UNKNOWN_FORMAT         -1
154 ?H:#$d_PRIfldbl PERL_PRIfldbl   $sPRIfldbl      /**/
155 ?H:#$d_PRIgldbl PERL_PRIgldbl   $sPRIgldbl      /**/
156 ?H:#$d_PRIeldbl PERL_PRIeldbl   $sPRIeldbl      /**/
157 ?H:#$d_PRIFUldbl PERL_PRIFldbl  $sPRIFUldbl     /**/
158 ?H:#$d_PRIGUldbl PERL_PRIGldbl  $sPRIGUldbl     /**/
159 ?H:#$d_PRIEUldbl PERL_PRIEldbl  $sPRIEUldbl     /**/
160 ?H:#$d_SCNfldbl PERL_SCNfldbl   $sSCNfldbl      /**/
161 ?H:.
162 ?T:yyy message saveccflags
163 ?F:!try
164 ?LINT:change ccflags
165 ?LINT:change uselongdouble
166 : Check what kind of doubles your system has
167 $echo "Checking the kind of doubles you have..." >&4
168 $cat >try.c <<EOP
169 #$i_stdlib I_STDLIB
170 #define DOUBLESIZE $doublesize
171 #ifdef I_STDLIB
172 #include <stdlib.h>
173 #endif
174 #include <stdio.h>
175 static const double d = -0.1;
176 int main() {
177   unsigned const char* b = (unsigned const char*)(&d);
178 #if DOUBLESIZE == 4
179   if (b[0] == 0xCD && b[3] == 0xBD) {
180     /* IEEE 754 32-bit little-endian */
181     printf("1\n");
182     exit(0);
183   }
184   if (b[0] == 0xBD && b[3] == 0xCD) {
185     /* IEEE 754 32-bit big-endian */
186     printf("2\n");
187     exit(0);
188   }
189 #endif
190 #if DOUBLESIZE == 8
191   if (b[0] == 0x9A && b[7] == 0xBF) {
192     /* IEEE 754 64-bit little-endian */
193     printf("3\n");
194     exit(0);
195   }
196   if (b[0] == 0xBF && b[7] == 0x9A) {
197     /* IEEE 754 64-bit big-endian */
198     printf("4\n");
199     exit(0);
200   }
201   if (b[0] == 0x99 && b[3] == 0xBF && b[4] == 0x9A && b[7] == 0x99) {
202    /* ARM mixed endian: two little-endian 32-bit floats, in big endian order:
203     * 4 5 6 7 0 1 2 3 (MSB = 7, LSB = 0)
204     * 99 99 b9 bf 9a 99 99 99 */
205     printf("7\n");
206     exit(0);
207   }
208   if (b[0] == 0x99 && b[3] == 0x9A && b[4] == 0xBF && b[7] == 0x99) {
209    /* The opposite of case 7, mixed endian: two big-endian 32-bit floats,
210     * in little endian order: 3 2 1 0 7 6 5 4 (MSB = 7, LSB = 0)
211     * 99 99 99 9a bf b9 99 99 */
212     printf("8\n");
213     exit(0);
214   }
215 #endif
216 #if DOUBLESIZE == 16
217   if (b[0] == 0x9A && b[15] == 0xBF) {
218     /* IEEE 754 128-bit little-endian */
219     printf("5\n");
220     exit(0);
221   }
222   if (b[0] == 0xBF && b[15] == 0x9A) {
223     /* IEEE 754 128-bit big-endian */
224     printf("6\n");
225     exit(0);
226   }
227 #endif
228   /* Then there are old mainframe/miniframe formats like VAX, IBM, and CRAY.
229    * Whether those environments can still build Perl is debatable. */
230   printf("-1\n"); /* unknown */
231   exit(0);
232 }
233 EOP
234 set try
235 if eval $compile; then
236     doublekind=`$run ./try`
237 else
238     doublekind=-1
239 fi
240 case "$doublekind" in
241 1) echo "You have IEEE 754 32-bit little endian doubles." >&4 ;;
242 2) echo "You have IEEE 754 32-bit big endian doubles." >&4 ;;
243 3) echo "You have IEEE 754 64-bit little endian doubles." >&4 ;;
244 4) echo "You have IEEE 754 64-bit big endian doubles." >&4 ;;
245 5) echo "You have IEEE 754 128-bit little endian doubles." >&4 ;;
246 6) echo "You have IEEE 754 128-bit big endian doubles." >&4 ;;
247 *) echo "Cannot figure out your double.  You VAX, or something?" >&4 ;;
248 esac
249 $rm_try
250
251 : Check print/scan long double stuff
252 echo " "
253
254 if $test X"$d_longdbl" = X"$define"; then
255
256 echo "Checking how to print long doubles..." >&4
257
258 if $test X"$sPRIfldbl" = X -a X"$doublesize" = X"$longdblsize"; then
259         $cat >try.c <<'EOCP'
260 #include <sys/types.h>
261 #include <stdio.h>
262 int main() {
263   double d = 123.456;
264   printf("%.3f\n", d);
265 }
266 EOCP
267         set try
268         if eval $compile; then
269                 yyy=`$run ./try`
270                 case "$yyy" in
271                 123.456)
272                         sPRIfldbl='"f"'; sPRIgldbl='"g"'; sPRIeldbl='"e"';
273                         sPRIFUldbl='"F"'; sPRIGUldbl='"G"'; sPRIEUldbl='"E"';
274                         echo "We will use %f."
275                         ;;
276                 esac
277         fi
278 fi
279
280 if $test X"$sPRIfldbl" = X; then
281         $cat >try.c <<'EOCP'
282 #include <sys/types.h>
283 #include <stdio.h>
284 int main() {
285   long double d = 123.456;
286   printf("%.3Lf\n", d);
287 }
288 EOCP
289         set try
290         if eval $compile; then
291                 yyy=`$run ./try`
292                 case "$yyy" in
293                 123.456)
294                         sPRIfldbl='"Lf"'; sPRIgldbl='"Lg"'; sPRIeldbl='"Le"';
295                         sPRIFUldbl='"LF"'; sPRIGUldbl='"LG"'; sPRIEUldbl='"LE"';
296                         echo "We will use %Lf."
297                         ;;
298                 esac
299         fi
300 fi
301
302 if $test X"$sPRIfldbl" = X; then
303         $cat >try.c <<'EOCP'
304 #include <sys/types.h>
305 #include <stdio.h>
306 int main() {
307   long double d = 123.456;
308   printf("%.3llf\n", d);
309 }
310 EOCP
311         set try
312         if eval $compile; then
313                 yyy=`$run ./try`
314                 case "$yyy" in
315                 123.456)
316                         sPRIfldbl='"llf"'; sPRIgldbl='"llg"'; sPRIeldbl='"lle"';
317                         sPRIFUldbl='"llF"'; sPRIGUldbl='"llG"'; sPRIEUldbl='"llE"';
318                         echo "We will use %llf."
319                         ;;
320                 esac
321         fi
322 fi
323
324 if $test X"$sPRIfldbl" = X; then
325         $cat >try.c <<'EOCP'
326 #include <sys/types.h>
327 #include <stdio.h>
328 int main() {
329   long double d = 123.456;
330   printf("%.3lf\n", d);
331 }
332 EOCP
333         set try
334         if eval $compile; then
335                 yyy=`$run ./try`
336                 case "$yyy" in
337                 123.456)
338                         sPRIfldbl='"lf"'; sPRIgldbl='"lg"'; sPRIeldbl='"le"';
339                         sPRIFUldbl='"lF"'; sPRIGUldbl='"lG"'; sPRIEUldbl='"lE"';
340                         echo "We will use %lf."
341                         ;;
342                 esac
343         fi
344 fi
345
346 if $test X"$sPRIfldbl" = X; then
347         echo "Cannot figure out how to print long doubles." >&4
348 else
349         sSCNfldbl=$sPRIfldbl    # expect consistency
350 fi
351
352 $rm_try
353
354 fi # d_longdbl
355
356 case "$sPRIfldbl" in
357 '')     d_PRIfldbl="$undef"; d_PRIgldbl="$undef"; d_PRIeldbl="$undef";
358         d_PRIFUldbl="$undef"; d_PRIGUldbl="$undef"; d_PRIEUldbl="$undef";
359         d_SCNfldbl="$undef";
360         ;;
361 *)      d_PRIfldbl="$define"; d_PRIgldbl="$define"; d_PRIeldbl="$define";
362         d_PRIFUldbl="$define"; d_PRIGUldbl="$define"; d_PRIEUldbl="$define";
363         d_SCNfldbl="$define";
364         ;;
365 esac
366
367 : Before committing on uselongdouble, see whether that looks sane.
368 if $test "$uselongdouble" = "$define"; then
369     message=""
370     echo " "
371     echo "Checking if your long double math functions work right..." >&4
372     $cat > try.c <<EOF
373 #include <math.h>
374 #include <stdio.h>
375 int main() {
376   printf("%"$sPRIgldbl"\n", sqrtl(logl(expl(cosl(sinl(0.0L))))+powl(2.0L, 3.0L)));
377 }
378 EOF
379     case "$osname:$gccversion" in
380     aix:)       saveccflags="$ccflags"
381                 ccflags="$ccflags -qlongdouble" ;; # to avoid core dump
382     esac
383     set try
384     if eval $compile_ok; then
385       yyy=`$run ./try`
386     fi
387     case "$yyy" in
388     3) echo "Your long double math functions are working correctly." >&4 ;;
389     *) echo "Your long double math functions are broken, not using long doubles." >&4
390        uselongdouble=$undef
391        ;;
392     esac
393     $rm_try
394     case "$osname:$gccversion" in
395     aix:)       ccflags="$saveccflags" ;; # restore
396     esac
397 fi
398