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 / perl / perlxv.U
1 ?RCS: $Id: perlxv.U,v 1.1 2000/08/31 17:53:56 jhi Exp jhi $
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:ivtype uvtype nvtype ivsize uvsize nvsize \
9       i8type u8type i16type u16type i32type u32type i64type u64type \
10       i8size u8size i16size u16size i32size u32size i64size u64size \
11       d_nv_preserves_uv nv_preserves_uv_bits nv_overflows_integers_at \
12       d_nv_zero_is_allbits_zero: \
13         echo rm_try use64bitint d_quad quadtype uquadtype usequadmath \
14         d_longdbl uselongdouble longdblsize doublesize i_quadmath \
15         shortsize intsize longsize i_stdlib i_string libs gccversion \
16         cat Compile i_inttypes test d_volatile signal_t run
17 ?MAKE:  -pick add $@ %<
18 ?S:ivtype:
19 ?S:     This variable contains the C type used for Perl's IV.
20 ?S:.
21 ?S:uvtype:
22 ?S:     This variable contains the C type used for Perl's UV.
23 ?S:.
24 ?S:nvtype:
25 ?S:     This variable contains the C type used for Perl's NV.
26 ?S:.
27 ?S:i8type:
28 ?S:     This variable contains the C type used for Perl's I8.
29 ?S:.
30 ?S:u8type:
31 ?S:     This variable contains the C type used for Perl's U8.
32 ?S:.
33 ?S:i16type:
34 ?S:     This variable contains the C type used for Perl's I16.
35 ?S:.
36 ?S:u16type:
37 ?S:     This variable contains the C type used for Perl's U16.
38 ?S:.
39 ?S:i32type:
40 ?S:     This variable contains the C type used for Perl's I32.
41 ?S:.
42 ?S:u32type:
43 ?S:     This variable contains the C type used for Perl's U32.
44 ?S:.
45 ?S:i64type:
46 ?S:     This variable contains the C type used for Perl's I64.
47 ?S:.
48 ?S:u64type:
49 ?S:     This variable contains the C type used for Perl's U64.
50 ?S:.
51 ?S:ivsize:
52 ?S:     This variable is the size of an IV in bytes.
53 ?S:.
54 ?S:uvsize:
55 ?S:     This variable is the size of a UV in bytes.
56 ?S:.
57 ?S:i8size:
58 ?S:     This variable is the size of an I8 in bytes.
59 ?S:.
60 ?S:u8size:
61 ?S:     This variable is the size of an U8 in bytes.
62 ?S:.
63 ?S:i16size:
64 ?S:     This variable is the size of an I16 in bytes.
65 ?S:.
66 ?S:u16size:
67 ?S:     This variable is the size of an U16 in bytes.
68 ?S:.
69 ?S:i32size:
70 ?S:     This variable is the size of an I32 in bytes.
71 ?S:.
72 ?S:u32size:
73 ?S:     This variable is the size of an U32 in bytes.
74 ?S:.
75 ?S:i64size:
76 ?S:     This variable is the size of an I64 in bytes.
77 ?S:.
78 ?S:u64size:
79 ?S:     This variable is the size of an U64 in bytes.
80 ?S:.
81 ?S:nvsize:
82 ?S:     This variable is the size of a Perl NV in bytes.
83 ?S:     Note that some floating point formats have unused bytes.
84 ?S:.
85 ?S:d_nv_preserves_uv:
86 ?S:     This variable indicates whether a variable of type nvtype
87 ?S:     can preserve all the bits a variable of type uvtype.
88 ?S:.
89 ?S:nv_preserves_uv_bits:
90 ?S:     This variable indicates how many of bits type uvtype
91 ?S:     a variable nvtype can preserve.
92 ?S:.
93 ?S:nv_overflows_integers_at:
94 ?S:     This variable gives the largest integer value that NVs can hold
95 ?S:     as a constant floating point expression.
96 ?S:     If it could not be determined, it holds the value 0.
97 ?S:.
98 ?S:d_nv_zero_is_allbits_zero:
99 ?S:     This variable indicates whether a variable of type nvtype
100 ?S:     stores 0.0 in memory as all bits zero.
101 ?S:.
102 ?C:IVTYPE:
103 ?C:     This symbol defines the C type used for Perl's IV.
104 ?C:.
105 ?C:UVTYPE:
106 ?C:     This symbol defines the C type used for Perl's UV.
107 ?C:.
108 ?C:I8TYPE:
109 ?C:     This symbol defines the C type used for Perl's I8.
110 ?C:.
111 ?C:U8TYPE:
112 ?C:     This symbol defines the C type used for Perl's U8.
113 ?C:.
114 ?C:I16TYPE:
115 ?C:     This symbol defines the C type used for Perl's I16.
116 ?C:.
117 ?C:U16TYPE:
118 ?C:     This symbol defines the C type used for Perl's U16.
119 ?C:.
120 ?C:I32TYPE:
121 ?C:     This symbol defines the C type used for Perl's I32.
122 ?C:.
123 ?C:U32TYPE:
124 ?C:     This symbol defines the C type used for Perl's U32.
125 ?C:.
126 ?C:I64TYPE:
127 ?C:     This symbol defines the C type used for Perl's I64.
128 ?C:.
129 ?C:U64TYPE:
130 ?C:     This symbol defines the C type used for Perl's U64.
131 ?C:.
132 ?C:NVTYPE:
133 ?C:     This symbol defines the C type used for Perl's NV.
134 ?C:.
135 ?C:IVSIZE:
136 ?C:     This symbol contains the sizeof(IV).
137 ?C:.
138 ?C:UVSIZE:
139 ?C:     This symbol contains the sizeof(UV).
140 ?C:.
141 ?C:I8SIZE:
142 ?C:     This symbol contains the sizeof(I8).
143 ?C:.
144 ?C:U8SIZE:
145 ?C:     This symbol contains the sizeof(U8).
146 ?C:.
147 ?C:I16SIZE:
148 ?C:     This symbol contains the sizeof(I16).
149 ?C:.
150 ?C:U16SIZE:
151 ?C:     This symbol contains the sizeof(U16).
152 ?C:.
153 ?C:I32SIZE:
154 ?C:     This symbol contains the sizeof(I32).
155 ?C:.
156 ?C:U32SIZE:
157 ?C:     This symbol contains the sizeof(U32).
158 ?C:.
159 ?C:I64SIZE:
160 ?C:     This symbol contains the sizeof(I64).
161 ?C:.
162 ?C:U64SIZE:
163 ?C:     This symbol contains the sizeof(U64).
164 ?C:.
165 ?C:NVSIZE:
166 ?C:     This symbol contains the sizeof(NV).
167 ?C:     Note that some floating point formats have unused bytes.
168 ?C:     The most notable example is the x86* 80-bit extended precision
169 ?C:     which comes in byte sizes of 12 and 16 (for 32 and 64 bit
170 ?C:     platforms, respectively), but which only uses 10 bytes.
171 ?C:     Perl compiled with -Duselongdouble on x86* is like this.
172 ?C:.
173 ?C:NV_PRESERVES_UV:
174 ?C:     This symbol, if defined, indicates that a variable of type NVTYPE
175 ?C:     can preserve all the bits of a variable of type UVTYPE.
176 ?C:.
177 ?C:NV_PRESERVES_UV_BITS:
178 ?C:     This symbol contains the number of bits a variable of type NVTYPE
179 ?C:     can preserve of a variable of type UVTYPE.
180 ?C:.
181 ?C:NV_OVERFLOWS_INTEGERS_AT:
182 ?C:     This symbol gives the largest integer value that NVs can hold. This
183 ?C:     value + 1.0 cannot be stored accurately. It is expressed as constant
184 ?C:     floating point expression to reduce the chance of decimal/binary
185 ?C:     conversion issues. If it can not be determined, the value 0 is given.
186 ?C:.
187 ?C:NV_ZERO_IS_ALLBITS_ZERO:
188 ?C:     This symbol, if defined, indicates that a variable of type NVTYPE
189 ?C:     stores 0.0 in memory as all bits zero.
190 ?C:.
191 ?H:#define      IVTYPE          $ivtype         /**/
192 ?H:#define      UVTYPE          $uvtype         /**/
193 ?H:#define      I8TYPE          $i8type         /**/
194 ?H:#define      U8TYPE          $u8type         /**/
195 ?H:#define      I16TYPE         $i16type        /**/
196 ?H:#define      U16TYPE         $u16type        /**/
197 ?H:#define      I32TYPE         $i32type        /**/
198 ?H:#define      U32TYPE         $u32type        /**/
199 ?H:?%<:#ifdef HAS_QUAD
200 ?H:?%<:#define  I64TYPE         $i64type        /**/
201 ?H:?%<:#define  U64TYPE         $u64type        /**/
202 ?H:?%<:#endif
203 ?H:#define      NVTYPE          $nvtype         /**/
204 ?H:#define      IVSIZE          $ivsize         /**/
205 ?H:#define      UVSIZE          $uvsize         /**/
206 ?H:#define      I8SIZE          $i8size         /**/
207 ?H:#define      U8SIZE          $u8size         /**/
208 ?H:#define      I16SIZE         $i16size        /**/
209 ?H:#define      U16SIZE         $u16size        /**/
210 ?H:#define      I32SIZE         $i32size        /**/
211 ?H:#define      U32SIZE         $u32size        /**/
212 ?H:?%<:#ifdef HAS_QUAD
213 ?H:?%<:#define  I64SIZE         $i64size        /**/
214 ?H:?%<:#define  U64SIZE         $u64size        /**/
215 ?H:?%<:#endif
216 ?H:#define      NVSIZE          $nvsize         /**/
217 ?H:#$d_nv_preserves_uv  NV_PRESERVES_UV
218 ?H:#define      NV_PRESERVES_UV_BITS    $nv_preserves_uv_bits
219 ?H:#define      NV_OVERFLOWS_INTEGERS_AT        $nv_overflows_integers_at
220 ?H:#$d_nv_zero_is_allbits_zero  NV_ZERO_IS_ALLBITS_ZERO
221 ?H:?%<:#if UVSIZE == 8
222 ?H:?%<:#   ifdef BYTEORDER
223 ?H:?%<:#       if BYTEORDER == 0x1234
224 ?H:?%<:#           undef BYTEORDER
225 ?H:?%<:#           define BYTEORDER 0x12345678
226 ?H:?%<:#       else
227 ?H:?%<:#           if BYTEORDER == 0x4321
228 ?H:?%<:#               undef BYTEORDER
229 ?H:?%<:#               define BYTEORDER 0x87654321
230 ?H:?%<:#           endif
231 ?H:?%<:#       endif
232 ?H:?%<:#   endif
233 ?H:?%<:#endif
234 ?H:.
235 ?T:volatile
236 ?T:xxx
237 ?T:d
238 ?F:!try
239 : Check basic sizes
240 echo " "
241 $echo "Choosing the C types to be used for Perl's internal types..." >&4
242
243 case "$use64bitint:$d_quad:$quadtype" in
244 define:define:?*)
245         ivtype="$quadtype"
246         uvtype="$uquadtype"
247         ivsize=8
248         uvsize=8
249         ;;
250 *)      ivtype="long"
251         uvtype="unsigned long"
252         ivsize=$longsize
253         uvsize=$longsize
254         ;;
255 esac
256
257 case "$uselongdouble:$d_longdbl" in
258 define:define)
259         nvtype="long double"
260         nvsize=$longdblsize
261         ;;
262 *)      nvtype=double
263         nvsize=$doublesize
264         ;;
265 esac
266
267 case "$usequadmath:$i_quadmath" in
268 define:define)
269   nvtype="__float128"
270   nvsize=16
271   case "$libs" in
272   *quadmath*) ;;
273   *) $cat <<EOM >&4
274
275 *** You requested the use of the quadmath library, but you
276 *** do not seem to have the quadmath library installed.
277 *** Cannot continue, aborting.
278 EOM
279     exit 1
280     ;;
281   esac
282   ;;
283 define:*) $cat <<EOM >&4
284
285 *** You requested the use of the quadmath library, but you
286 *** do not seem to have the required header, <quadmath.h>.
287 EOM
288   case "$gccversion" in
289   [23].*|4.[0-5]*)
290    $cat <<EOM >&4
291 *** Your gcc looks a bit old:
292 *** $gccversion
293 EOM
294     ;;
295   '')
296    $cat <<EOM >&4
297 *** You are not running a gcc.
298 EOM
299     ;;
300   esac
301   $cat <<EOM >&4
302 *** For the quadmath library you need at least gcc 4.6.
303 *** Cannot continue, aborting.
304 EOM
305   exit 1
306   ;;
307 esac
308
309 $echo "(IV will be "$ivtype", $ivsize bytes)"
310 $echo "(UV will be "$uvtype", $uvsize bytes)"
311 $echo "(NV will be "$nvtype", $nvsize bytes)"
312
313 $cat >try.c <<EOCP
314 #$i_inttypes I_INTTYPES
315 #ifdef I_INTTYPES
316 #include <inttypes.h>
317 #endif
318 #include <stdio.h>
319 int main() {
320 #ifdef INT8
321    int8_t i =  INT8_MAX;
322   uint8_t u = UINT8_MAX;
323   printf("int8_t\n");
324 #endif
325 #ifdef INT16
326    int16_t i =  INT16_MAX;
327   uint16_t u = UINT16_MAX;
328   printf("int16_t\n");
329 #endif
330 #ifdef INT32
331    int32_t i =  INT32_MAX;
332   uint32_t u = UINT32_MAX;
333   printf("int32_t\n");
334 #endif
335 }
336 EOCP
337
338 i8type="signed char"
339 u8type="unsigned char"
340 i8size=1
341 u8size=1
342
343 case "$i16type" in
344 '')     case "$shortsize" in
345         2)      i16type=short
346                 u16type="unsigned short"
347                 i16size=$shortsize
348                 u16size=$shortsize
349                 ;;
350         esac
351         ;;
352 esac
353 case "$i16type" in
354 '')     set try -DINT16
355         if eval $compile; then
356                 case "`$run ./try`" in
357                 int16_t)
358                         i16type=int16_t
359                         u16type=uint16_t
360                         i16size=2
361                         u16size=2
362                         ;;
363                 esac
364         fi
365         ;;
366 esac
367 case "$i16type" in
368 '')     if $test $shortsize -ge 2; then
369                 i16type=short
370                 u16type="unsigned short"
371                 i16size=$shortsize
372                 u16size=$shortsize
373         fi
374         ;;
375 esac
376
377 case "$i32type" in
378 '')     case "$longsize" in
379         4)      i32type=long
380                 u32type="unsigned long"
381                 i32size=$longsize
382                 u32size=$longsize
383                 ;;
384         *)      case "$intsize" in
385                 4)      i32type=int
386                         u32type="unsigned int"
387                         i32size=$intsize
388                         u32size=$intsize
389                         ;;
390                 esac
391                 ;;
392         esac
393         ;;
394 esac
395 case "$i32type" in
396 '')     set try -DINT32
397         if eval $compile; then
398                 case "`$run ./try`" in
399                 int32_t)
400                         i32type=int32_t
401                         u32type=uint32_t
402                         i32size=4
403                         u32size=4
404                         ;;
405                 esac
406         fi
407         ;;
408 esac
409 case "$i32type" in
410 '')     if $test $intsize -ge 4; then
411                 i32type=int
412                 u32type="unsigned int"
413                 i32size=$intsize
414                 u32size=$intsize
415         fi
416         ;;
417 esac
418
419 case "$i64type" in
420 '')     case "$d_quad:$quadtype" in
421         define:?*)
422                 i64type="$quadtype"
423                 u64type="$uquadtype"
424                 i64size=8
425                 u64size=8
426                 ;;
427         esac
428         ;;
429 esac
430
431 $echo "Checking how many bits of your UVs your NVs can preserve..." >&4
432 : volatile so that the compiler has to store it out to memory.
433 if test X"$d_volatile" = X"$define"; then
434         volatile=volatile
435 fi
436 $cat <<EOP >try.c
437 #include <stdio.h>
438 #$i_stdlib I_STDLIB
439 #ifdef I_STDLIB
440 #include <stdlib.h>
441 #endif
442 #include <sys/types.h>
443 #include <signal.h>
444 #ifdef SIGFPE
445 $volatile int bletched = 0;
446 $signal_t blech(int s) { bletched = 1; }
447 #endif
448 int main() {
449     $uvtype u = 0;
450     $nvtype d;
451     int     n = 8 * $uvsize;
452     int     i;
453 #ifdef SIGFPE
454     signal(SIGFPE, blech);
455 #endif
456
457     for (i = 0; i < n; i++) {
458       u = u << 1 | ($uvtype)1;
459       d = ($nvtype)u;
460       if (($uvtype)d != u)
461         break;
462       if (d <= 0)
463         break;
464       d = ($nvtype)(u - 1);
465       if (($uvtype)d != (u - 1))
466         break;
467 #ifdef SIGFPE
468       if (bletched)
469         break;
470 #endif
471     }
472     printf("%d\n", ((i == n) ? -n : i));
473     exit(0);
474 }
475 EOP
476 set try
477
478 d_nv_preserves_uv="$undef"
479 if eval $compile; then
480         nv_preserves_uv_bits="`$run ./try`"
481 fi
482 case "$nv_preserves_uv_bits" in
483 \-[1-9]*)
484         nv_preserves_uv_bits=`expr 0 - $nv_preserves_uv_bits`
485         $echo "Your NVs can preserve all $nv_preserves_uv_bits bits of your UVs."  2>&1
486         d_nv_preserves_uv="$define"
487         ;;
488 [1-9]*) $echo "Your NVs can preserve only $nv_preserves_uv_bits bits of your UVs."  2>&1
489         d_nv_preserves_uv="$undef" ;;
490 *)      $echo "Can't figure out how many bits your NVs preserve." 2>&1
491         nv_preserves_uv_bits="0" ;;
492 esac
493 $rm_try
494
495 $echo "Checking to find the largest integer value your NVs can hold..." >&4
496 : volatile so that the compiler has to store it out to memory.
497 if test X"$d_volatile" = X"$define"; then
498         volatile=volatile
499 fi
500 $cat <<EOP >try.c
501 #include <stdio.h>
502
503 typedef $nvtype NV;
504
505 int
506 main() {
507   NV value = 2;
508   int count = 1;
509
510   while(count < 256) {
511     $volatile NV up = value + 1.0;
512     $volatile NV negated = -value;
513     $volatile NV down = negated - 1.0;
514     $volatile NV got_up = up - value;
515     int up_good = got_up == 1.0;
516     int got_down = down - negated;
517     int down_good = got_down == -1.0;
518
519     if (down_good != up_good) {
520       fprintf(stderr,
521               "Inconsistency - up %d %f; down %d %f; for 2**%d (%.20f)\n",
522               up_good, (double) got_up, down_good, (double) got_down,
523               count, (double) value);
524       return 1;
525     }
526     if (!up_good) {
527       while (1) {
528         if (count > 8) {
529           count -= 8;
530           fputs("256.0", stdout);
531         } else {
532           count--;
533           fputs("2.0", stdout);
534         }
535         if (!count) {
536           puts("");
537           return 0;
538         }
539         fputs("*", stdout);
540       }
541     }
542     value *= 2;
543     ++count;
544   }
545   fprintf(stderr, "Cannot overflow integer range, even at 2**%d (%.20f)\n",
546           count, (double) value);
547   return 1;
548 }
549 EOP
550 set try
551
552 nv_overflows_integers_at='0'
553 if eval $compile; then
554     xxx="`$run ./try`"
555     case "$?" in
556         0)
557             case "$xxx" in
558                 2*)  cat >&4 <<EOM
559 The largest integer your NVs can preserve is equal to $xxx
560 EOM
561                     nv_overflows_integers_at="$xxx"
562                     ;;
563                 *)  cat >&4 <<EOM
564 Cannot determine the largest integer value your NVs can hold, unexpected output
565 '$xxx'
566 EOM
567                     ;;
568             esac
569             ;;
570         *)  cat >&4 <<EOM
571 Cannot determine the largest integer value your NVs can hold
572 EOM
573             ;;
574     esac
575 fi
576 $rm_try
577
578 $echo "Checking whether NV 0.0 is all bits zero in memory..." >&4
579 : volatile so that the compiler has to store it out to memory.
580 if test X"$d_volatile" = X"$define"; then
581         volatile=volatile
582 fi
583 $cat <<EOP >try.c
584 #include <stdio.h>
585 #$i_stdlib I_STDLIB
586 #ifdef I_STDLIB
587 #include <stdlib.h>
588 #endif
589 #$i_string I_STRING
590 #ifdef I_STRING
591 #  include <string.h>
592 #else
593 #  include <strings.h>
594 #endif
595 #include <sys/types.h>
596 #include <signal.h>
597 #ifdef SIGFPE
598 $volatile int bletched = 0;
599 $signal_t blech(int s) { bletched = 1; }
600 #endif
601
602 int checkit($nvtype d, char *where) {
603     unsigned char *p = (char *)&d;
604     unsigned char *end = p + sizeof(d);
605     int fail = 0;
606
607     while (p < end)
608         fail += *p++;
609
610     if (!fail)
611         return 0;
612
613     p = (char *)&d;
614     printf("No - %s: 0x", where);
615     while (p < end)
616         printf ("%02X", *p++);
617     printf("\n");
618     return 1;
619 }
620
621 int main(int argc, char **argv) {
622     $nvtype d = 0.0;
623     int fail = 0;
624     fail += checkit(d, "0.0");
625
626     /* The compiler shouldn't be assuming that bletched is 0  */
627     d = bletched;
628
629     fail += checkit(d, "bleched");
630
631 #ifdef SIGFPE
632     signal(SIGFPE, blech);
633 #endif
634
635     /* Paranoia - the compiler should have no way of knowing that ANSI says
636        that argv[argc] will always be NULL.  Actually, if it did assume this it
637        would be buggy, as this is C and main() can be called from elsewhere in
638        the program.  */
639     d = argv[argc] ? 1 : 0;
640
641     if (d) {
642         printf("Odd argv[argc]=%p, d=%g\n", argv[argc], d);
643     }
644
645     fail += checkit(d, "ternary");
646
647     memset(&d, sizeof(d), argv[argc] ? 1 : 0);
648
649     if (d != 0.0) {
650         printf("No - memset doesn't give 0.0\n");
651         /* This might just blow up:  */
652         printf("(gives %g)\n", d);
653         return 1;
654     }
655
656 #ifdef SIGFPE
657     if (bletched) {
658         printf("No - something bleched\n");
659         return 1;
660     }
661 #endif
662     if (fail) {
663       printf("No - %d fail(s)\n", fail);
664       return 1;
665     }
666     printf("Yes\n");
667     return 0;
668 }
669 EOP
670 set try
671
672 d_nv_zero_is_allbits_zero="$undef"
673 if eval $compile; then
674     xxx="`$run ./try`"
675     case "$?" in
676         0)
677             case "$xxx" in
678                 Yes)  cat >&4 <<EOM
679 0.0 is represented as all bits zero in memory
680 EOM
681                     d_nv_zero_is_allbits_zero="$define"
682                     ;;
683                 *)  cat >&4 <<EOM
684 0.0 is not represented as all bits zero in memory
685 EOM
686                     d_nv_zero_is_allbits_zero="$undef"
687                     ;;
688             esac
689             ;;
690         *)  cat >&4 <<EOM
691 0.0 is not represented as all bits zero in memory
692 EOM
693             d_nv_zero_is_allbits_zero="$undef"
694             ;;
695     esac
696 fi
697 $rm_try
698